37#include "llvm/ADT/ArrayRef.h"
38#include "llvm/ADT/STLExtras.h"
39#include "llvm/ADT/SmallVector.h"
40#include "llvm/ADT/StringExtras.h"
41#include "llvm/ADT/StringRef.h"
42#include "llvm/ADT/Twine.h"
43#include "llvm/Frontend/HLSL/HLSLBinding.h"
44#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
45#include "llvm/Support/Casting.h"
46#include "llvm/Support/DXILABI.h"
47#include "llvm/Support/ErrorHandling.h"
48#include "llvm/Support/FormatVariadic.h"
49#include "llvm/TargetParser/Triple.h"
58using llvm::hlsl::InterpolationModifier;
59using llvm::hlsl::IOType;
60using llvm::hlsl::SemanticStageInfo;
69 return VT->getElementType();
71 return MT->getElementType();
77 case ResourceClass::SRV:
78 return RegisterType::SRV;
79 case ResourceClass::UAV:
80 return RegisterType::UAV;
81 case ResourceClass::CBuffer:
82 return RegisterType::CBuffer;
83 case ResourceClass::Sampler:
84 return RegisterType::Sampler;
86 llvm_unreachable(
"unexpected ResourceClass value");
95 case ResourceClass::SRV:
96 case ResourceClass::UAV:
98 case ResourceClass::CBuffer:
100 case ResourceClass::Sampler:
103 llvm_unreachable(
"unexpected ResourceClass value");
109 assert(RT !=
nullptr);
113 *RT = RegisterType::SRV;
117 *RT = RegisterType::UAV;
121 *RT = RegisterType::CBuffer;
125 *RT = RegisterType::Sampler;
129 *RT = RegisterType::C;
133 *RT = RegisterType::I;
142 case RegisterType::SRV:
144 case RegisterType::UAV:
146 case RegisterType::CBuffer:
148 case RegisterType::Sampler:
150 case RegisterType::C:
152 case RegisterType::I:
155 llvm_unreachable(
"unexpected RegisterType value");
160 case RegisterType::SRV:
161 return ResourceClass::SRV;
162 case RegisterType::UAV:
163 return ResourceClass::UAV;
164 case RegisterType::CBuffer:
165 return ResourceClass::CBuffer;
166 case RegisterType::Sampler:
167 return ResourceClass::Sampler;
168 case RegisterType::C:
169 case RegisterType::I:
173 llvm_unreachable(
"unexpected RegisterType value");
177 const auto *BT = dyn_cast<BuiltinType>(
Type);
181 return Builtin::BI__builtin_get_spirv_spec_constant_int;
184 switch (BT->getKind()) {
185 case BuiltinType::Bool:
186 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
187 case BuiltinType::Short:
188 return Builtin::BI__builtin_get_spirv_spec_constant_short;
189 case BuiltinType::Int:
190 return Builtin::BI__builtin_get_spirv_spec_constant_int;
191 case BuiltinType::LongLong:
192 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
193 case BuiltinType::UShort:
194 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
195 case BuiltinType::UInt:
196 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
197 case BuiltinType::ULongLong:
198 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
199 case BuiltinType::Half:
200 return Builtin::BI__builtin_get_spirv_spec_constant_half;
201 case BuiltinType::Float:
202 return Builtin::BI__builtin_get_spirv_spec_constant_float;
203 case BuiltinType::Double:
204 return Builtin::BI__builtin_get_spirv_spec_constant_double;
213 llvm::raw_svector_ostream OS(Buffer);
220 ResourceClass ResClass) {
222 "DeclBindingInfo already added");
228 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
229 return &BindingsList.emplace_back(VD, ResClass);
233 ResourceClass ResClass) {
234 auto Entry = DeclToBindingListIndex.find(VD);
235 if (Entry != DeclToBindingListIndex.end()) {
236 for (
unsigned Index = Entry->getSecond();
237 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
239 if (BindingsList[Index].ResClass == ResClass)
240 return &BindingsList[Index];
247 return DeclToBindingListIndex.contains(VD);
259 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
262 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
263 : llvm::hlsl::ResourceClass::SRV;
275 if (
T->isArrayType() ||
T->isStructureType() ||
T->isConstantMatrixType())
282 assert(Context.getTypeSize(
T) <= 64 &&
283 "Scalar bit widths larger than 64 not supported");
286 return Context.getTypeSize(
T) / 8;
293 constexpr unsigned CBufferAlign = 16;
294 if (
const auto *RD =
T->getAsRecordDecl()) {
296 for (
const FieldDecl *Field : RD->fields()) {
303 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
304 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
305 FieldAlign = CBufferAlign;
308 Size = llvm::alignTo(Size, FieldAlign);
315 unsigned ElementCount = AT->getSize().getZExtValue();
316 if (ElementCount == 0)
319 unsigned ElementSize =
321 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
322 return AlignedElementSize * (ElementCount - 1) + ElementSize;
326 unsigned ElementCount = VT->getNumElements();
327 unsigned ElementSize =
329 return ElementSize * ElementCount;
332 return Context.getTypeSize(
T) / 8;
343 bool HasPackOffset =
false;
344 bool HasNonPackOffset =
false;
346 VarDecl *Var = dyn_cast<VarDecl>(Field);
349 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
350 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
351 HasPackOffset =
true;
353 HasNonPackOffset =
true;
360 if (HasNonPackOffset)
367 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
368 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
369 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
370 return LHS.second->getOffsetInBytes() <
371 RHS.second->getOffsetInBytes();
373 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
374 VarDecl *Var = PackOffsetVec[i].first;
375 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
377 unsigned Begin =
Attr->getOffsetInBytes();
378 unsigned End = Begin + Size;
379 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
380 if (End > NextBegin) {
381 VarDecl *NextVar = PackOffsetVec[i + 1].first;
393 CAT = dyn_cast<ConstantArrayType>(
395 return CAT !=
nullptr;
406static const HLSLAttributedResourceType *
409 "expected array of resource records");
411 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
413 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
416static const HLSLAttributedResourceType *
430 return RD->isEmpty();
459 Base.getType()->castAsCXXRecordDecl()))
470 assert(RD ==
nullptr &&
471 "there should be at most 1 record by a given name in a scope");
488 Name.append(NameBaseII->
getName());
495 size_t NameLength = Name.size();
504 Name.append(llvm::Twine(suffix).str());
505 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
512 Name.truncate(NameLength);
527 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
529 S, CAT->getElementType()->getUnqualifiedDesugaredType());
534 CAT->getSizeModifier(),
535 CAT->getIndexTypeCVRQualifiers())
584 "struct is already HLSL buffer compatible");
598 LS->
addAttr(PackedAttr::CreateImplicit(AST));
602 if (
unsigned NumBases = StructDecl->
getNumBases()) {
603 assert(NumBases == 1 &&
"HLSL supports only one base type");
653 LS->
addAttr(PackedAttr::CreateImplicit(AST));
658 VarDecl *VD = dyn_cast<VarDecl>(D);
674 "host layout field for $Globals decl failed to be created");
693 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
694 Attr->setBinding(RT, std::nullopt, 0);
695 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
702 BufDecl->setRBraceLoc(RBrace);
719 BufDecl->isCBuffer() ? RegisterType::CBuffer
729 int X,
int Y,
int Z) {
730 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
731 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
732 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
733 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
743 int Min,
int Max,
int Preferred,
744 int SpelledArgsCount) {
745 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
746 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
747 WS->getPreferred() != Preferred ||
748 WS->getSpelledArgsCount() != SpelledArgsCount) {
749 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
750 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
756 Result->setSpelledArgsCount(SpelledArgsCount);
760HLSLVkConstantIdAttr *
766 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
774 Diag(VD->getLocation(), diag::err_specialization_const);
778 if (!VD->getType().isConstQualified()) {
779 Diag(VD->getLocation(), diag::err_specialization_const);
783 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
784 if (CI->getId() != Id) {
785 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
786 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
791 HLSLVkConstantIdAttr *
Result =
798 llvm::Triple::EnvironmentType ShaderType) {
799 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
800 if (NT->getType() != ShaderType) {
801 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
802 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
806 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
809HLSLParamModifierAttr *
811 HLSLParamModifierAttr::Spelling Spelling) {
814 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
815 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
816 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
817 D->
dropAttr<HLSLParamModifierAttr>();
819 return HLSLParamModifierAttr::Create(
821 HLSLParamModifierAttr::Keyword_inout);
823 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
824 Diag(PA->getLocation(), diag::note_conflicting_attribute);
831 InterpolationModifier Modifier;
832 switch (
static_cast<HLSLInterpolationModifierAttr::Spelling
>(
834 case HLSLInterpolationModifierAttr::Keyword_nointerpolation:
835 Modifier = InterpolationModifier::NoInterpolation;
837 case HLSLInterpolationModifierAttr::Keyword_linear:
838 Modifier = InterpolationModifier::Linear;
840 case HLSLInterpolationModifierAttr::Keyword_centroid:
841 Modifier = InterpolationModifier::Centroid;
843 case HLSLInterpolationModifierAttr::Keyword_noperspective:
844 Modifier = InterpolationModifier::NoPerspective;
846 case HLSLInterpolationModifierAttr::Keyword_sample:
847 Modifier = InterpolationModifier::Sample;
849 case HLSLInterpolationModifierAttr::Keyword_center:
850 Modifier = InterpolationModifier::Center;
852 case HLSLInterpolationModifierAttr::SpellingNotCalculated:
853 llvm_unreachable(
"interpolation modifier spelling was not calculated");
856 InterpolationModifier Modifiers = Modifier;
858 auto Old =
static_cast<InterpolationModifier
>(
Previous->getModifiers());
860 if (
any(Old & Modifier)) {
861 Diag(AL.
getLoc(), diag::warn_hlsl_duplicate_interpolation) << AL;
862 }
else if (llvm::hlsl::getInterpolationMode(Modifiers) ==
863 llvm::dxbc::PSV::InterpolationMode::Invalid &&
864 llvm::hlsl::getInterpolationMode(Old) !=
865 llvm::dxbc::PSV::InterpolationMode::Invalid) {
866 Diag(AL.
getLoc(), diag::err_hlsl_interpolation_conflict);
867 Diag(
Previous->getLocation(), diag::note_conflicting_attribute);
870 InterpolationModifier OldLocation =
871 llvm::hlsl::getInterpolationSamplingLocation(Old);
872 InterpolationModifier NewLocation =
873 llvm::hlsl::getInterpolationSamplingLocation(Modifier);
874 if (
any(OldLocation) &&
any(NewLocation)) {
875 Diag(AL.
getLoc(), diag::warn_hlsl_interpolation_override)
876 << (std::max(OldLocation, NewLocation) ==
877 InterpolationModifier::Sample)
878 << (std::min(OldLocation, NewLocation) ==
879 InterpolationModifier::Centroid);
882 D->
dropAttr<HLSLInterpolationModifierAttr>();
884 D->
addAttr(HLSLInterpolationModifierAttr::Create(
888bool SemaHLSL::checkInterpolationModifiers(
889 const DeclaratorDecl *D,
const HLSLInterpolationModifierAttr *Inherited,
890 const HLSLParsedSemanticAttr *Semantic) {
893 const auto *A = D->
getAttr<HLSLInterpolationModifierAttr>();
897 Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
899 const auto *FD = dyn_cast<FunctionDecl>(D);
902 if (
T->isDependentType())
904 if (
const auto *RT =
T->getAs<RecordType>()) {
910 Valid &= checkInterpolationModifiers(Field, A, Semantic);
916 auto Modifiers =
static_cast<InterpolationModifier
>(A->getModifiers());
917 if (Modifiers == InterpolationModifier::NoInterpolation) {
919 Semantic && llvm::hlsl::getSemanticKind(Semantic->getSemanticName()) ==
920 SemanticKind::Position;
923 Diag(A->getLocation(), diag::err_hlsl_interpolation_position);
924 Diag(Semantic->getLocation(), diag::note_conflicting_attribute);
931 Diag(A->getLocation(), diag::err_hlsl_interpolation_type) <<
T;
957 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
958 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
961 if (Shader->getType() != Env) {
962 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
974 case llvm::Triple::UnknownEnvironment:
975 case llvm::Triple::Library:
977 case llvm::Triple::RootSignature:
978 llvm_unreachable(
"rootsig environment has no functions");
980 llvm_unreachable(
"Unhandled environment in triple");
986 HLSLAppliedSemanticAttr *Semantic,
991 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
992 assert(ShaderAttr &&
"Entry point has no shader attribute");
993 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
994 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
997 case SemanticKind::Position:
1001 return (ST == llvm::Triple::Vertex && !IsInput) ||
1002 (ST == llvm::Triple::Pixel && IsInput);
1003 case SemanticKind::VertexID:
1005 case SemanticKind::InstanceID:
1006 return ST == llvm::Triple::Vertex && IsInput;
1012bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1015 SemanticInfo &ActiveSemantic,
1016 SemaHLSL::SemanticContext &SC) {
1017 if (ActiveSemantic.Semantic ==
nullptr) {
1018 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1019 if (ActiveSemantic.Semantic)
1020 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1023 if (!ActiveSemantic.Semantic) {
1029 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1030 ActiveSemantic.Semantic->getAttrName()->getName(),
1031 ActiveSemantic.Index.value_or(0));
1035 checkSemanticAnnotation(FD, D, A, SC);
1036 OutputDecl->addAttr(A);
1038 unsigned Location = ActiveSemantic.Index.value_or(0);
1041 any(SC.CurrentIOType & IOType::In))) {
1042 bool HasVkLocation =
false;
1043 if (
auto *A = D->getAttr<HLSLVkLocationAttr>()) {
1044 HasVkLocation = true;
1045 Location = A->getLocation();
1048 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1049 Diag(D->getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1052 SC.UsesExplicitVkLocations = HasVkLocation;
1055 const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->getType());
1056 unsigned ElementCount = AT ? AT->
getZExtSize() : 1;
1057 ActiveSemantic.Index = Location + ElementCount;
1059 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
1060 for (
unsigned I = 0; I < ElementCount; ++I) {
1061 Twine VariableName = BaseName.concat(Twine(Location + I));
1063 auto [_, Inserted] = SC.ActiveSemantics.insert(VariableName.str());
1065 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
1066 << VariableName.str();
1074bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1077 SemanticInfo &ActiveSemantic,
1078 SemaHLSL::SemanticContext &SC) {
1079 if (ActiveSemantic.Semantic ==
nullptr) {
1080 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1081 if (ActiveSemantic.Semantic)
1082 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1088 const RecordType *RT = dyn_cast<RecordType>(
T);
1090 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1093 const RecordDecl *RD = RT->getDecl();
1094 for (FieldDecl *Field : RD->
fields()) {
1095 SemanticInfo Info = ActiveSemantic;
1096 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1097 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1100 if (ActiveSemantic.Semantic)
1101 ActiveSemantic = Info;
1108 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1109 assert(ShaderAttr &&
"Entry point has no shader attribute");
1110 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1114 case llvm::Triple::Pixel:
1115 case llvm::Triple::Vertex:
1116 case llvm::Triple::Geometry:
1117 case llvm::Triple::Hull:
1118 case llvm::Triple::Domain:
1119 case llvm::Triple::RayGeneration:
1120 case llvm::Triple::Intersection:
1121 case llvm::Triple::AnyHit:
1122 case llvm::Triple::ClosestHit:
1123 case llvm::Triple::Miss:
1124 case llvm::Triple::Callable:
1125 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1126 diagnoseAttrStageMismatch(NT, ST,
1127 {llvm::Triple::Compute,
1128 llvm::Triple::Amplification,
1129 llvm::Triple::Mesh});
1132 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1133 diagnoseAttrStageMismatch(WS, ST,
1134 {llvm::Triple::Compute,
1135 llvm::Triple::Amplification,
1136 llvm::Triple::Mesh});
1141 case llvm::Triple::Compute:
1142 case llvm::Triple::Amplification:
1143 case llvm::Triple::Mesh:
1144 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1146 << llvm::Triple::getEnvironmentTypeName(ST);
1149 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1151 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1152 }
else if (Ver < VersionTuple(6, 6)) {
1153 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1156 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1159 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1160 << WS << WS->getSpelledArgsCount() <<
"6.8";
1165 case llvm::Triple::RootSignature:
1166 llvm_unreachable(
"rootsig environment has no function entry point");
1168 llvm_unreachable(
"Unhandled environment in triple");
1171 SemaHLSL::SemanticContext InputSC = {};
1172 InputSC.CurrentIOType = IOType::In;
1173 SemaHLSL::SemanticContext OutputSC = {};
1174 OutputSC.CurrentIOType = IOType::Out;
1177 SemanticInfo ActiveSemantic;
1178 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1179 if (ActiveSemantic.Semantic)
1180 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1184 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1185 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1189 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1190 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1191 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1194 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1195 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1200 SemanticInfo ActiveSemantic;
1201 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1202 if (ActiveSemantic.Semantic)
1203 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1205 if (ST == llvm::Triple::Vertex &&
1206 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1208 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1212void SemaHLSL::checkSemanticAnnotation(
1214 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC) {
1215 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1216 assert(ShaderAttr &&
"Entry point has no shader attribute");
1217 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1220 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1221 llvm::hlsl::SemanticInterpretation Interpretation =
1222 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1223 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
1224 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1227 case SemanticKind::DispatchThreadID:
1228 case SemanticKind::GroupID:
1229 case SemanticKind::GroupIndex:
1230 case SemanticKind::GroupThreadID:
1231 case SemanticKind::InstanceID:
1232 if (SemanticAttr->getSemanticIndex() != 0) {
1233 std::string PrettyName =
1234 "'" + SemanticAttr->getSemanticName().str() +
"'";
1235 Diag(SemanticAttr->getLoc(),
1236 diag::err_hlsl_semantic_indexing_not_supported)
1245void SemaHLSL::diagnoseAttrStageMismatch(
1246 const Attr *A, llvm::Triple::EnvironmentType Stage,
1247 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1248 SmallVector<StringRef, 8> StageStrings;
1249 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1250 [](llvm::Triple::EnvironmentType ST) {
1252 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1254 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1255 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1256 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1259void SemaHLSL::diagnoseSemanticStageMismatch(
1260 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1263 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1264 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1265 return Info.Stage == Stage;
1268 StringRef CurrentIOTypeName =
"patch constants or primitives";
1269 if (
any(CurrentIOType & IOType::In))
1270 CurrentIOTypeName =
"inputs";
1271 else if (
any(CurrentIOType & IOType::Out))
1272 CurrentIOTypeName =
"outputs";
1275 if (It == Allowed.end()) {
1276 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1277 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1278 << CurrentIOTypeName;
1282 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1283 if (!(AllowedIOTypes & CurrentIOType)) {
1284 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1285 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1286 << CurrentIOTypeName;
1291template <CastKind Kind>
1294 Ty = VTy->getElementType();
1299template <CastKind Kind>
1311 if (LHSFloat && RHSFloat) {
1339 if (LHSSigned == RHSSigned) {
1340 if (IsCompAssign || IntOrder >= 0)
1348 if (IntOrder != (LHSSigned ? 1 : -1)) {
1349 if (IsCompAssign || RHSSigned)
1357 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1358 if (IsCompAssign || LHSSigned)
1374 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1375 QualType NewTy = Ctx.getExtVectorType(
1385 return CK_FloatingCast;
1387 return CK_IntegralCast;
1389 return CK_IntegralToFloating;
1391 return CK_FloatingToIntegral;
1397 bool IsCompAssign) {
1404 if (!LVecTy && IsCompAssign) {
1406 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1408 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1410 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1415 unsigned EndSz = std::numeric_limits<unsigned>::max();
1418 LSz = EndSz = LVecTy->getNumElements();
1421 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1422 "one of the above should have had a value");
1426 if (IsCompAssign && LSz != EndSz) {
1428 diag::err_hlsl_vector_compound_assignment_truncation)
1429 << LHSType << RHSType;
1435 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1440 if (!IsCompAssign && !LVecTy)
1444 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1445 return Ctx.getCommonSugaredType(LHSType, RHSType);
1453 LElTy, RElTy, IsCompAssign);
1456 "HLSL Vectors can only contain integer or floating point types");
1458 LElTy, RElTy, IsCompAssign);
1463 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1464 "Called with non-logical operator");
1466 llvm::raw_svector_ostream OS(Buff);
1468 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1469 OS << NewFnName <<
"(";
1479std::pair<IdentifierInfo *, bool>
1482 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1489 return {DeclIdent,
Found};
1500 for (
auto &RootSigElement : RootElements)
1501 Elements.push_back(RootSigElement.getElement());
1505 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1507 SignatureDecl->setImplicit();
1513 if (RootSigOverrideIdent) {
1516 if (
SemaRef.LookupQualifiedName(R, DC))
1517 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1525struct PerVisibilityBindingChecker {
1528 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1532 llvm::dxbc::ShaderVisibility Vis;
1537 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1539 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1540 llvm::dxil::ResourceClass RC,
uint32_t Space,
1542 const hlsl::RootSignatureElement *Elem) {
1544 assert(BuilderIndex < Builders.size() &&
1545 "Not enough builders for visibility type");
1546 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1547 static_cast<const void *
>(Elem));
1549 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1550 "'All' visibility must come first");
1551 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1552 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1553 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1554 static_cast<const void *
>(Elem));
1556 ElemInfoMap.push_back({Elem,
Visibility,
false});
1559 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1560 auto It = llvm::lower_bound(
1562 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1563 assert(It->Elem == Elem &&
"Element not in map");
1567 bool checkOverlap() {
1568 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1569 return LHS.Elem < RHS.Elem;
1572 bool HadOverlap =
false;
1574 using llvm::hlsl::BindingInfoBuilder;
1575 auto ReportOverlap = [
this,
1576 &HadOverlap](
const BindingInfoBuilder &Builder,
1577 const llvm::hlsl::Binding &Reported) {
1581 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1582 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1583 const auto *PrevElem =
1584 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1586 ElemInfo &Info =
getInfo(Elem);
1591 Info.Diagnosed =
true;
1593 ElemInfo &PrevInfo =
getInfo(PrevElem);
1594 llvm::dxbc::ShaderVisibility CommonVis =
1595 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1598 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1599 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1600 << Reported.isUnbounded() << Reported.UpperBound
1605 this->S->
Diag(PrevElem->getLocation(),
1606 diag::note_hlsl_resource_range_here);
1609 for (BindingInfoBuilder &Builder : Builders)
1610 Builder.calculateBindingInfo(ReportOverlap);
1630 bool HadError =
false;
1631 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1632 uint32_t UpperBound) {
1634 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1635 << LowerBound << UpperBound;
1642 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1643 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1644 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1647 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1648 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1649 ReportError(Loc, 0, 0xfffffffe);
1652 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1653 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1654 ReportError(Loc, 0, 0xffffffef);
1657 const uint32_t Version =
1658 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1659 const uint32_t VersionEnum = Version - 1;
1660 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1662 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1669 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1670 if (
const auto *Descriptor =
1671 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1672 VerifyRegister(Loc, Descriptor->Reg.Number);
1673 VerifySpace(Loc, Descriptor->Space);
1675 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1677 ReportFlagError(Loc);
1678 }
else if (
const auto *Constants =
1679 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1680 VerifyRegister(Loc, Constants->Reg.Number);
1681 VerifySpace(Loc, Constants->Space);
1682 }
else if (
const auto *Sampler =
1683 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1684 VerifyRegister(Loc, Sampler->Reg.Number);
1685 VerifySpace(Loc, Sampler->Space);
1688 "By construction, parseFloatParam can't produce a NaN from a "
1689 "float_literal token");
1691 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1692 ReportError(Loc, 0, 16);
1693 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1694 ReportFloatError(Loc, -16.f, 15.99f);
1695 }
else if (
const auto *Clause =
1696 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1698 VerifyRegister(Loc, Clause->Reg.Number);
1699 VerifySpace(Loc, Clause->Space);
1701 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1705 ReportError(Loc, 1, 0xfffffffe);
1708 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1710 ReportFlagError(Loc);
1714 PerVisibilityBindingChecker BindingChecker(
this);
1715 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1720 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1721 if (
const auto *Descriptor =
1722 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1723 uint32_t LowerBound(Descriptor->Reg.Number);
1724 uint32_t UpperBound(LowerBound);
1726 BindingChecker.trackBinding(
1727 Descriptor->Visibility,
1728 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1729 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1730 }
else if (
const auto *Constants =
1731 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1732 uint32_t LowerBound(Constants->Reg.Number);
1733 uint32_t UpperBound(LowerBound);
1735 BindingChecker.trackBinding(
1736 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1737 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1738 }
else if (
const auto *Sampler =
1739 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1740 uint32_t LowerBound(Sampler->Reg.Number);
1741 uint32_t UpperBound(LowerBound);
1743 BindingChecker.trackBinding(
1744 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1745 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1746 }
else if (
const auto *Clause =
1747 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1750 UnboundClauses.emplace_back(Clause, &RootSigElem);
1751 }
else if (
const auto *Table =
1752 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1753 assert(UnboundClauses.size() == Table->NumClauses &&
1754 "Number of unbound elements must match the number of clauses");
1755 bool HasAnySampler =
false;
1756 bool HasAnyNonSampler =
false;
1757 uint64_t Offset = 0;
1758 bool IsPrevUnbound =
false;
1759 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1761 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1762 HasAnySampler =
true;
1764 HasAnyNonSampler =
true;
1766 if (HasAnySampler && HasAnyNonSampler)
1767 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1772 if (Clause->NumDescriptors == 0)
1776 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1778 Offset = Clause->Offset;
1780 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1781 Offset, Clause->NumDescriptors);
1783 if (IsPrevUnbound && IsAppending)
1784 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1785 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1786 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1789 Offset = RangeBound + 1;
1790 IsPrevUnbound = Clause->NumDescriptors ==
1791 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1794 uint32_t LowerBound(Clause->Reg.Number);
1795 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1796 LowerBound, Clause->NumDescriptors);
1798 BindingChecker.trackBinding(
1800 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1801 LowerBound, UpperBound, ClauseElem);
1803 UnboundClauses.clear();
1807 return BindingChecker.checkOverlap();
1812 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1817 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1818 if (RS->getSignatureIdent() != Ident) {
1819 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1823 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1829 if (
auto *SignatureDecl =
1830 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1837 llvm::VersionTuple SMVersion =
1842 uint32_t ZMax = 1024;
1843 uint32_t ThreadMax = 1024;
1844 if (IsDXIL && SMVersion.getMajor() <= 4) {
1847 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1857 diag::err_hlsl_numthreads_argument_oor)
1866 diag::err_hlsl_numthreads_argument_oor)
1875 diag::err_hlsl_numthreads_argument_oor)
1880 if (
X * Y * Z > ThreadMax) {
1881 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1898 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1906 if (SpelledArgsCount > 1 &&
1910 uint32_t Preferred = 0;
1911 if (SpelledArgsCount > 2 &&
1915 if (SpelledArgsCount > 2) {
1918 diag::err_attribute_power_of_two_in_range)
1919 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1924 if (Preferred < Min || Preferred >
Max) {
1926 diag::err_attribute_power_of_two_in_range)
1927 << AL <<
Min <<
Max << Preferred;
1930 }
else if (SpelledArgsCount > 1) {
1933 diag::err_attribute_power_of_two_in_range)
1934 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1938 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1941 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1946 diag::err_attribute_power_of_two_in_range)
1947 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1952 HLSLWaveSizeAttr *NewAttr =
1989 uint32_t Binding = 0;
2013 if (!
T->hasUnsignedIntegerRepresentation() ||
2014 (VT && VT->getNumElements() > 3)) {
2015 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
2016 << AL <<
"uint/uint2/uint3";
2025 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
2026 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
2027 << AL <<
"float/float1/float2/float3/float4";
2036 std::optional<unsigned> Index) {
2038 QualType ValueType = VD->getType();
2039 if (
auto *FD = dyn_cast<FunctionDecl>(D))
2043 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>())
2048 case SemanticKind::DispatchThreadID:
2049 case SemanticKind::GroupThreadID:
2050 case SemanticKind::GroupID:
2053 case SemanticKind::GroupIndex:
2055 case SemanticKind::Position:
2056 case SemanticKind::Target:
2059 case SemanticKind::VertexID: {
2060 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
2061 if (!ValueType->isUnsignedIntegerType() || SizeInBits != 32)
2062 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
2065 case SemanticKind::InstanceID: {
2066 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
2070 if (!ValueType->isUnsignedIntegerType() ||
2071 !(SizeInBits == 32 || (!IsSPIRV && SizeInBits == 16)))
2072 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
2076 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2084 uint32_t IndexValue(0), ExplicitIndex(0);
2087 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2089 assert(IndexValue > 0 ? ExplicitIndex :
true);
2090 std::optional<unsigned> Index =
2091 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
2094 if (Kind == SemanticKind::Arbitrary)
2102 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2103 << AL <<
"shader constant in a constant buffer";
2107 uint32_t SubComponent;
2117 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2122 if (IsAggregateTy) {
2123 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2127 if ((Component * 32 + Size) > 128) {
2128 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2133 EltTy = VT->getElementType();
2135 if (Align > 32 && Component == 1) {
2138 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2152 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2155 llvm::Triple::EnvironmentType ShaderType;
2156 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2157 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2158 << AL << Str << ArgLoc;
2172 Expr *SampleCountExpr) {
2173 assert(AttrList.size() &&
"expected list of resource attributes");
2180 HLSLAttributedResourceType::Attributes ResAttrs;
2182 bool HasResourceClass =
false;
2183 bool HasResourceDimension =
false;
2184 for (
const Attr *A : AttrList) {
2189 case attr::HLSLResourceClass: {
2191 if (HasResourceClass) {
2193 ? diag::warn_duplicate_attribute_exact
2194 : diag::warn_duplicate_attribute)
2198 ResAttrs.ResourceClass = RC;
2199 HasResourceClass =
true;
2202 case attr::HLSLResourceDimension: {
2203 llvm::dxil::ResourceDimension RD =
2205 if (HasResourceDimension) {
2207 ? diag::warn_duplicate_attribute_exact
2208 : diag::warn_duplicate_attribute)
2212 ResAttrs.ResourceDimension = RD;
2213 HasResourceDimension =
true;
2216 case attr::HLSLIsROV:
2217 if (ResAttrs.IsROV) {
2221 ResAttrs.IsROV =
true;
2223 case attr::HLSLRawBuffer:
2224 if (ResAttrs.RawBuffer) {
2228 ResAttrs.RawBuffer =
true;
2230 case attr::HLSLIsArray:
2231 if (ResAttrs.IsArray) {
2235 ResAttrs.IsArray =
true;
2237 case attr::HLSLIsMultiSampled:
2238 if (ResAttrs.SampleCountExpr) {
2244 ResAttrs.SampleCountExpr =
2250 case attr::HLSLIsCounter:
2251 if (ResAttrs.IsCounter) {
2255 ResAttrs.IsCounter =
true;
2257 case attr::HLSLContainedType: {
2260 if (!ContainedTy.
isNull()) {
2262 ? diag::warn_duplicate_attribute_exact
2263 : diag::warn_duplicate_attribute)
2272 llvm_unreachable(
"unhandled resource attribute type");
2276 if (!HasResourceClass) {
2277 S.
Diag(AttrList.back()->getRange().getEnd(),
2278 diag::err_hlsl_missing_resource_class);
2283 Wrapped, ContainedTy, ResAttrs);
2285 if (LocInfo && ContainedTyInfo) {
2298 if (!
T->isHLSLResourceType()) {
2299 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2314 AttributeCommonInfo::AS_CXX11, 0, false ,
2319 case ParsedAttr::AT_HLSLResourceClass: {
2320 StringRef Identifier;
2322 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2327 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2328 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2329 <<
"ResourceClass" << Identifier;
2332 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2336 case ParsedAttr::AT_HLSLResourceDimension: {
2337 StringRef Identifier;
2339 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2343 llvm::dxil::ResourceDimension RD;
2344 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2346 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2347 <<
"ResourceDimension" << Identifier;
2350 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2354 case ParsedAttr::AT_HLSLIsROV:
2358 case ParsedAttr::AT_HLSLRawBuffer:
2362 case ParsedAttr::AT_HLSLIsCounter:
2366 case ParsedAttr::AT_HLSLIsArray:
2370 case ParsedAttr::AT_HLSLIsMultiSampled:
2374 case ParsedAttr::AT_HLSLContainedType: {
2376 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2382 assert(TSI &&
"no type source info for attribute argument");
2384 diag::err_incomplete_type))
2386 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2391 llvm_unreachable(
"unhandled HLSL attribute");
2394 HLSLResourcesTypeAttrs.emplace_back(A);
2400 if (!HLSLResourcesTypeAttrs.size())
2406 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2407 const HLSLAttributedResourceType *RT =
2414 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2416 HLSLResourcesTypeAttrs.clear();
2424 auto I = LocsForHLSLAttributedResources.find(RT);
2425 if (I != LocsForHLSLAttributedResources.end()) {
2426 LocInfo = I->second;
2427 LocsForHLSLAttributedResources.erase(I);
2436void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2437 const RecordType *RT) {
2445 "incomplete arrays inside user defined types are not supported");
2454 if (
const HLSLAttributedResourceType *AttrResType =
2455 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2460 Bindings.addDeclBindingInfo(VD, RC);
2461 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2467 collectResourceBindingsOnUserRecordDecl(VD, RT);
2479 bool SpecifiedSpace) {
2480 int RegTypeNum =
static_cast<int>(RegType);
2483 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2484 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2489 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2490 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2491 : ResourceClass::SRV;
2501 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2505 if (
const HLSLAttributedResourceType *AttrResType =
2506 HLSLAttributedResourceType::findHandleTypeOnResource(
2523 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2524 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2529 if (RegType == RegisterType::CBuffer)
2530 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2531 else if (RegType != RegisterType::C)
2532 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2536 if (RegType == RegisterType::C)
2537 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2539 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2549 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2557 bool RegisterTypesDetected[5] = {
false};
2558 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2561 if (HLSLResourceBindingAttr *
attr =
2562 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2565 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2566 int otherRegTypeNum =
static_cast<int>(otherRegType);
2568 diag::err_hlsl_duplicate_register_annotation)
2572 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2580 bool SpecifiedSpace) {
2585 "expecting VarDecl or HLSLBufferDecl");
2597 const uint64_t &Limit,
2600 uint64_t ArrayCount = 1) {
2605 if (StartSlot > Limit)
2609 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2612 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2613 Count = CAT->
getSize().getZExtValue();
2617 ArrayCount * Count);
2621 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2624 if (ResTy->getAttrs().ResourceClass != ResClass)
2628 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2629 if (EndSlot > Limit)
2633 StartSlot = EndSlot + 1;
2638 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2641 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2644 ResClass, Ctx, ArrayCount))
2651 ResClass, Ctx, ArrayCount))
2665 const uint64_t Limit = UINT32_MAX;
2666 if (SlotNum > Limit)
2671 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2674 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2675 uint64_t BaseSlot = SlotNum;
2683 return (BaseSlot > Limit);
2690 return (SlotNum > Limit);
2693 llvm_unreachable(
"unexpected decl type");
2697 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2699 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2700 Ty = IAT->getElementType();
2702 diag::err_incomplete_type))
2706 StringRef Slot =
"";
2707 StringRef Space =
"";
2711 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2721 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2727 SpaceLoc = Loc->
getLoc();
2730 if (Str.starts_with(
"space")) {
2732 SpaceLoc = Loc->
getLoc();
2741 std::optional<unsigned> SlotNum;
2742 unsigned SpaceNum = 0;
2745 if (!Slot.empty()) {
2747 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2750 if (RegType == RegisterType::I) {
2751 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2754 const StringRef SlotNumStr = Slot.substr(1);
2759 if (SlotNumStr.getAsInteger(10, N)) {
2760 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2768 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2777 if (!Space.starts_with(
"space")) {
2778 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2781 StringRef SpaceNumStr = Space.substr(5);
2782 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2783 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2788 if (SlotNum.has_value())
2793 HLSLResourceBindingAttr *NewAttr =
2794 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2796 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2820 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2822 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2826 Cur = AT->getModifiedType();
2837 ? attr::HLSLRowMajor
2838 : attr::HLSLColumnMajor;
2842 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2851 if (ExistingKind == AttrK) {
2852 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2854 Diag(AL.
getLoc(), diag::note_previous_attribute);
2858 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2859 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2861 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2866 if (AttrK == attr::HLSLRowMajor)
2867 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2868 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2879 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2881 if (
T.isNull() ||
T->isDependentType())
2886 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2887 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2895using llvm::dxil::BarrierMemoryTypeFlag;
2896using llvm::dxil::BarrierSemanticFlag;
2898template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
2899 return llvm::to_underlying(Flag);
2913 bool DiagnoseAvailability;
2940 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2944 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2945 unsigned CurrentShaderStageBit;
2950 bool ReportOnlyShaderStageIssues;
2953 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2954 static_assert(
sizeof(
unsigned) >= 4);
2955 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2956 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2957 "ShaderType is too big for this bitmap");
2960 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2961 CurrentShaderEnvironment = ShaderType;
2962 CurrentShaderStageBit = (1 << bitmapIndex);
2965 void SetUnknownShaderStageContext() {
2966 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2967 CurrentShaderStageBit = (1 << 31);
2970 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2971 return CurrentShaderEnvironment;
2974 bool InUnknownShaderStageContext()
const {
2975 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2979 void AddToScannedFunctions(
const FunctionDecl *FD) {
2980 unsigned &ScannedStages = ScannedDecls[FD];
2981 ScannedStages |= CurrentShaderStageBit;
2984 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2986 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2987 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2990 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2991 return ScannerStages & CurrentShaderStageBit;
2994 static bool NeverBeenScanned(
unsigned ScannedStages) {
2995 return ScannedStages == 0;
2999 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3000 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3002 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3003 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3004 void DiagnoseBarrierCall(CallExpr *CE);
3005 uint64_t DiagnoseBarrierGroupMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3006 bool HasVisibleGroup,
bool IsAllMemory);
3007 uint64_t DiagnoseBarrierNodeMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3008 bool HasKnownStage,
bool IsAllMemory);
3009 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg, uint64_t SemanticFlags,
3010 bool HasVisibleGroup);
3011 void DiagnoseBarrierScope(Expr *SemanticArg, uint64_t MemoryFlags,
3012 uint64_t SemanticFlags);
3015 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3016 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3017 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3018 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3021 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3022 void RunOnFunction(
const FunctionDecl *FD);
3024 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3025 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3027 HandleFunctionOrMethodRef(FD, DRE);
3031 bool VisitMemberExpr(MemberExpr *ME)
override {
3032 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3034 HandleFunctionOrMethodRef(FD, ME);
3038 bool VisitCallExpr(CallExpr *CE)
override {
3039 DiagnoseBarrierCall(CE);
3044uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3045 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasVisibleGroup,
3048 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3049 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3054 diag::err_hlsl_barrier_flag_requires_group)
3059 return MemoryFlags & ~GroupSharedMemory;
3062uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3063 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasKnownStage,
3066 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3067 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3072 diag::err_hlsl_barrier_node_memory_requires_node);
3076 return MemoryFlags & ~NodeMemory;
3079void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3080 Expr *SemanticArg, uint64_t SemanticFlags,
bool HasVisibleGroup) {
3081 if (HasVisibleGroup ||
3082 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3086 diag::err_hlsl_barrier_flag_requires_group)
3087 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3093void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3094 uint64_t MemoryFlags,
3095 uint64_t SemanticFlags) {
3096 if (ReportOnlyShaderStageIssues)
3100 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3101 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3102 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3104 (MemoryFlags & DeviceScopeMemory) == 0)
3106 diag::err_hlsl_barrier_scope_requires_memory)
3108 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3112 diag::err_hlsl_barrier_scope_requires_memory)
3116void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3118 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3121 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3122 const bool HasKnownStage = !InUnknownShaderStageContext();
3123 const bool HasVisibleGroup =
3124 !HasKnownStage || Stage == llvm::Triple::Compute ||
3125 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3127 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3130 std::optional<llvm::APSInt>
Value =
3134 MemoryFlags =
Value->getZExtValue();
3135 const bool IsAllMemory =
3136 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3138 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3139 HasVisibleGroup, IsAllMemory);
3140 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3141 HasKnownStage, IsAllMemory);
3142 }
else if (!HasVisibleGroup) {
3144 diag::err_hlsl_barrier_resource_requires_group);
3149 std::optional<llvm::APSInt>
Value =
3155 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3158 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3161void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3164 "expected DeclRefExpr or MemberExpr");
3166 if (DiagnoseAvailability)
3167 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3168 CheckDeclAvailability(
3173 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3174 DeclsToScan.push_back(FDWithBody);
3177void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3182 llvm::Triple::EnvironmentType::Library;
3191 DeclContextsToScan.push_back(TU);
3193 while (!DeclContextsToScan.empty()) {
3194 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3195 for (
auto &D : DC->
decls()) {
3202 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3203 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3208 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3213 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3214 if (!IsLibraryShader && FD->
getName() == EntryName) {
3217 diag::err_hlsl_ambiguous_entry_point)
3219 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3225 SetShaderStageContext(ShaderAttr->getType());
3234 for (
const auto *Redecl : FD->
redecls()) {
3235 if (Redecl->isInExportDeclContext()) {
3242 SetUnknownShaderStageContext();
3249 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3256void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3257 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3258 DeclsToScan.push_back(FD);
3260 while (!DeclsToScan.empty()) {
3268 const unsigned ScannedStages = GetScannedStages(FD);
3269 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3272 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3274 AddToScannedFunctions(FD);
3279bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3280 const AvailabilityAttr *AA) {
3285 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3286 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3289 llvm::Triple::EnvironmentType AttrEnv =
3290 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3292 return CurrentEnv == AttrEnv;
3295const AvailabilityAttr *
3296DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3297 AvailabilityAttr
const *PartialMatch =
nullptr;
3301 for (
const auto *A : D->
attrs()) {
3302 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3303 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3304 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3305 StringRef TargetPlatform =
3309 if (AttrPlatform == TargetPlatform) {
3311 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3313 PartialMatch = Avail;
3317 return PartialMatch;
3322void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3323 const AvailabilityAttr *AA,
3342 if (ReportOnlyShaderStageIssues)
3348 if (InUnknownShaderStageContext())
3353 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3354 VersionTuple Introduced = AA->getIntroduced();
3363 llvm::StringRef PlatformName(
3366 llvm::StringRef CurrentEnvStr =
3367 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3369 llvm::StringRef AttrEnvStr =
3370 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3371 bool UseEnvironment = !AttrEnvStr.empty();
3373 if (EnvironmentMatches) {
3374 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3375 <<
Range << D << PlatformName << Introduced.getAsString()
3376 << UseEnvironment << CurrentEnvStr;
3378 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3382 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3383 << D << PlatformName << Introduced.getAsString()
3385 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3392 if (!DefaultCBufferDecls.empty()) {
3395 DefaultCBufferDecls);
3398 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3402 for (
const Decl *VD : DefaultCBufferDecls) {
3403 const HLSLResourceBindingAttr *RBA =
3404 VD->
getAttr<HLSLResourceBindingAttr>();
3405 if (RBA && RBA->hasRegisterSlot() &&
3406 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3413 SemaRef.Consumer.HandleTopLevelDecl(DG);
3415 diagnoseAvailabilityViolations(TU);
3424 "expected member expr to have resource record type or array of them");
3430 const Expr *NonConstIndexExpr =
nullptr;
3433 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3434 if (!NonConstIndexExpr)
3442 diag::err_hlsl_resource_member_array_access_not_constant);
3446 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3447 const Expr *IdxExpr = ASE->getIdx();
3449 NonConstIndexExpr = IdxExpr;
3451 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3452 E = SubME->getBase();
3453 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3454 E = ICE->getSubExpr();
3456 llvm_unreachable(
"unexpected expr type in resource member access");
3465 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3468 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3471 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3475 [[maybe_unused]]
bool LookupSucceeded =
3476 SemaRef.LookupQualifiedName(ConvR, RD);
3477 assert(LookupSucceeded);
3486std::optional<ExprResult>
3489 const HLSLAttributedResourceType *ResTy =
3490 HLSLAttributedResourceType::findHandleTypeOnResource(
3491 BaseType.getTypePtr());
3493 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3494 return std::nullopt;
3496 QualType TemplateType = ResTy->getContainedType();
3500 assert(NamedConversionDecl &&
3501 "Could not find conversion function for ConstantBuffer.");
3502 auto *ConversionDecl =
3505 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3515 const bool DiagnoseAvailability =
3517 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3518 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3519 .RunOnTranslationUnit(TU);
3526 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3529 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3554 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3569 if (!BaseType->isFloat32Type())
3570 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3571 << ArgOrdinal << 5 << 0
3581 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3582 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3583 << ArgOrdinal << 5 << 0
3592 if (!BaseType->isDoubleType()) {
3595 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3596 << ArgOrdinal << PassedType;
3603 unsigned ArgIndex) {
3604 auto *Arg = TheCall->
getArg(ArgIndex);
3606 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3609 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3623 << (ArgIndex + 1) << LValueTy;
3633 if (VecTy->getElementType()->isDoubleType())
3634 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3635 << ArgOrdinal << 1 << 0 << 1
3645 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3646 << ArgOrdinal << 5 << 1
3655 if (VecTy->getElementType()->isUnsignedIntegerType())
3658 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3659 << ArgOrdinal << 4 << 3 << 0
3668 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3669 << ArgOrdinal << 5 << 3
3675 unsigned ArgOrdinal,
unsigned Width) {
3678 ArgTy = VTy->getElementType();
3680 uint64_t ElementBitCount =
3682 if (ElementBitCount != Width) {
3684 diag::err_integer_incorrect_bit_count)
3685 << Width << ElementBitCount;
3696 else if (
auto *MatTyA =
3699 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3705 unsigned ArgIndex) {
3714 diag::err_typecheck_expect_scalar_or_vector)
3715 << ArgType << Scalar;
3722 QualType Scalar,
unsigned ArgIndex) {
3733 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3746 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3747 << ArgType << Scalar;
3752 unsigned ArgIndex) {
3757 if (!(ArgType->isScalarType() ||
3758 (VTy && VTy->getElementType()->isScalarType()))) {
3760 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3768 unsigned ArgIndex) {
3771 if (ArgType->isDependentType())
3775 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3776 ElementType = VectorTy->getElementType();
3778 ElementType = MatrixTy->getElementType();
3780 if (ElementType->isBooleanType())
3783 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3785 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3790 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3798 unsigned ArgIndex) {
3800 assert(ArgIndex < TheCall->getNumArgs());
3808 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3833 diag::err_typecheck_call_different_arg_types)
3852 Arg1ScalarTy = VTy->getElementType();
3856 Arg2ScalarTy = VTy->getElementType();
3859 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3860 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3870 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3872 diag::err_typecheck_vector_lengths_not_equal)
3878 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3880 diag::err_typecheck_vector_lengths_not_equal)
3900 Arg1ScalarTy = MTy->getElementType();
3904 Arg2ScalarTy = MTy->getElementType();
3907 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3908 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3913 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
3915 for (
Expr *Arg : {Arg1, Arg2}) {
3918 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
3920 diag::err_typecheck_vector_lengths_not_equal)
3922 << Arg->getSourceRange();
3938 unsigned ArgIndex) {
3943 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3946 unsigned int ActualDim = 1;
3948 ActualDim = VTy->getNumElements();
3949 IndexTy = VTy->getElementType();
3953 diag::err_typecheck_expect_int)
3959 const HLSLAttributedResourceType *ResTy =
3961 assert(ResTy &&
"Resource argument must be a resource");
3962 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3964 unsigned int ExpectedDim = 1;
3965 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3967 (ResAttrs.IsArray ? 1 : 0);
3969 if (ActualDim != ExpectedDim) {
3971 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3982 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3986 const HLSLAttributedResourceType *ResTy =
3990 diag::err_typecheck_expect_hlsl_resource)
3994 if (Check && Check(ResTy)) {
3996 diag::err_invalid_hlsl_resource_type)
4006 "expected resource handle type");
4007 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4008 auto MainAttrs = MainResType->getAttrs();
4009 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4010 MainAttrs.IsCounter =
true;
4012 MainResType->getContainedType(),
4023 return "SampleBias";
4025 return "SampleGrad";
4027 return "SampleLevel";
4031 return "SampleCmpLevelZero";
4033 llvm_unreachable(
"Invalid SampleKind");
4043 if (!MD || !MD->getDeclName().isIdentifier())
4050 return MD->getName();
4058 return VecTy->getElementType();
4059 return ContainedType;
4067 StringRef DefaultName) {
4072 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4099 if (SMVersion >= VersionTuple(6, 7))
4102 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4104 << ContainedType << SMVersion.getAsString();
4109 bool IncludeArraySlice =
true) {
4112 [](
const HLSLAttributedResourceType *ResType) {
4113 return ResType->getAttrs().ResourceDimension ==
4114 llvm::dxil::ResourceDimension::Unknown;
4120 [](
const HLSLAttributedResourceType *ResType) {
4121 return ResType->getAttrs().ResourceClass !=
4122 llvm::hlsl::ResourceClass::Sampler;
4130 unsigned ExpectedDim =
4132 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4161 unsigned NextIdx = 3;
4173 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4177 std::optional<llvm::APSInt> ComponentOpt =
4180 int64_t ComponentVal = ComponentOpt->getSExtValue();
4181 if (ComponentVal != 0) {
4184 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4185 "The component is not in the expected range.");
4187 diag::err_hlsl_gathercmp_invalid_component)
4197 const HLSLAttributedResourceType *ResourceTy =
4200 unsigned ExpectedDim =
4203 &S, TheCall->
getArg(NextIdx),
4209 assert(ResourceTy->hasContainedType() &&
4210 "Expecting a contained type for resource with a dimension "
4212 QualType ReturnType = ResourceTy->getContainedType();
4215 IsCmp ?
"GatherCmp" :
"Gather"))
4220 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4226 ReturnType = VecTy->getElementType();
4239 [](
const HLSLAttributedResourceType *ResType) {
4240 return ResType->getAttrs().ResourceDimension ==
4241 llvm::dxil::ResourceDimension::Unknown;
4251 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4258 unsigned ResourceDim =
4260 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4276 TheCall->
setType(ResourceTy->getContainedType());
4286 [](
const HLSLAttributedResourceType *ResType) {
4287 return !ResType->isMultiSampled();
4296 unsigned ResourceDim =
4298 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4316 TheCall->
setType(ResourceTy->getContainedType());
4321 unsigned MinArgs, MaxArgs;
4349 const HLSLAttributedResourceType *ResourceTy =
4351 unsigned ExpectedDim =
4354 unsigned NextIdx = 3;
4379 &S, TheCall->
getArg(NextIdx),
4392 assert(ResourceTy->hasContainedType() &&
4393 "Expecting a contained type for resource with a dimension "
4395 QualType ReturnType = ResourceTy->getContainedType();
4406 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4423 unsigned MinArgs,
unsigned MaxArgs,
4425 bool ReportsOriginalValue) {
4426 if (MinArgs == MaxArgs) {
4429 }
else if (TheCall->
getNumArgs() < MinArgs) {
4430 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4440 const bool DestIsOK =
4446 diag::err_builtin_invalid_arg_type)
4460 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4476 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4482 const unsigned NumArgs = TheCall->
getNumArgs();
4483 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4494 switch (BuiltinID) {
4495 case Builtin::BI__builtin_hlsl_barrier: {
4496 if (
SemaRef.checkArgCount(TheCall, 2))
4499 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4500 llvm::Triple::dxil) {
4508 std::optional<llvm::APSInt> MemoryFlags =
4512 diag::err_constant_integer_arg_type)
4516 if ((MemoryFlags->getZExtValue() &
4517 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4519 diag::err_hlsl_invalid_barrier_memory_flags);
4523 const HLSLAttributedResourceType *ResTy =
4524 HLSLAttributedResourceType::findHandleTypeOnResource(
4528 diag::err_typecheck_expect_hlsl_resource)
4532 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4534 diag::err_invalid_hlsl_resource_type)
4541 std::optional<llvm::APSInt> SemanticFlags =
4543 if (!SemanticFlags) {
4545 diag::err_constant_integer_arg_type)
4549 if ((SemanticFlags->getZExtValue() &
4550 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4552 diag::err_hlsl_invalid_barrier_semantic_flags);
4559 case Builtin::BI__builtin_hlsl_adduint64: {
4560 if (
SemaRef.checkArgCount(TheCall, 2))
4574 if (NumElementsArg != 2 && NumElementsArg != 4) {
4576 << 1 << 64 << NumElementsArg * 32;
4590 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4591 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4598 QualType ContainedTy = ResourceTy->getContainedType();
4599 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4602 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4607 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4608 if (
SemaRef.checkArgCount(TheCall, 3) ||
4615 "expected pointer type for second argument");
4622 diag::err_invalid_use_of_array_type);
4626 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4629 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4634 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4635 if (
SemaRef.checkArgCount(TheCall, 2) ||
4637 SemaRef.getASTContext().IntTy))
4644 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4645 if (
SemaRef.checkArgCount(TheCall, 3) ||
4648 SemaRef.getASTContext().UnsignedIntTy) ||
4650 SemaRef.getASTContext().UnsignedIntTy) ||
4656 QualType ReturnType = ResourceTy->getContainedType();
4661 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4662 if (
SemaRef.checkArgCount(TheCall, 4) ||
4665 SemaRef.getASTContext().UnsignedIntTy) ||
4667 SemaRef.getASTContext().UnsignedIntTy) ||
4673 "expected pointer type for second argument");
4680 diag::err_invalid_use_of_array_type);
4686 case Builtin::BI__builtin_hlsl_resource_load_level:
4688 case Builtin::BI__builtin_hlsl_resource_load_ms:
4690 case Builtin::BI__builtin_hlsl_resource_sample:
4692 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4694 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4696 case Builtin::BI__builtin_hlsl_resource_sample_level:
4698 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4700 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4702 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4703 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4705 case Builtin::BI__builtin_hlsl_resource_gather:
4707 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4709 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4710 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4716 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4717 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4723 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4724 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4730 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4731 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4737 TheCall->
setType(CounterHandleTy);
4740 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4741 if (
SemaRef.checkArgCount(TheCall, 2) ||
4744 SemaRef.getASTContext().UnsignedIntTy))
4752 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4753 if (
SemaRef.checkArgCount(TheCall, 1) ||
4761 TheCall->
setType(CounterHandleTy);
4764 case Builtin::BI__builtin_hlsl_and:
4765 case Builtin::BI__builtin_hlsl_or: {
4766 if (
SemaRef.checkArgCount(TheCall, 2))
4780 case Builtin::BI__builtin_hlsl_all:
4781 case Builtin::BI__builtin_hlsl_any: {
4782 if (
SemaRef.checkArgCount(TheCall, 1))
4788 case Builtin::BI__builtin_hlsl_asdouble: {
4789 if (
SemaRef.checkArgCount(TheCall, 2))
4793 SemaRef.Context.UnsignedIntTy,
4798 SemaRef.Context.UnsignedIntTy,
4807 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4808 if (
SemaRef.BuiltinElementwiseTernaryMath(
4814 case Builtin::BI__builtin_hlsl_dot: {
4816 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4822 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4823 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4824 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4834 EltTy = VecTy->getElementType();
4835 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4848 case Builtin::BI__builtin_hlsl_select: {
4849 if (
SemaRef.checkArgCount(TheCall, 3))
4858 if (VTy && VTy->getElementType()->isBooleanType() &&
4862 if (MTy && MTy->getElementType()->isBooleanType() &&
4867 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4868 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4869 if (
SemaRef.checkArgCount(TheCall, 1))
4875 diag::err_builtin_invalid_arg_type)
4878 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4882 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4883 case Builtin::BI__builtin_hlsl_elementwise_frac:
4884 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4885 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4886 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4887 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4888 if (
SemaRef.checkArgCount(TheCall, 1))
4893 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4897 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4898 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4899 if (
SemaRef.checkArgCount(TheCall, 1))
4904 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4909 case Builtin::BI__builtin_hlsl_mad: {
4910 if (
SemaRef.BuiltinElementwiseTernaryMath(
4916 case Builtin::BI__builtin_hlsl_mul: {
4917 if (
SemaRef.checkArgCount(TheCall, 2))
4927 return VTy->getElementType();
4929 return MTy->getElementType();
4933 QualType EltTy0 = getElemType(Ty0);
4942 if (IsVec0 && IsMat1) {
4945 }
else if (IsMat0 && IsVec1) {
4949 assert(IsMat0 && IsMat1);
4959 case Builtin::BI__builtin_elementwise_fma: {
4960 if (
SemaRef.checkArgCount(TheCall, 3) ||
4975 case Builtin::BI__builtin_hlsl_transpose: {
4976 if (
SemaRef.checkArgCount(TheCall, 1))
4985 << 1 << 3 << 0 << 0 << ArgTy;
4990 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4994 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4995 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5003 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5004 if (
SemaRef.checkArgCount(TheCall, 1))
5018 unsigned NumElts = VecTy->getNumElements();
5028 case Builtin::BI__builtin_hlsl_wave_active_max:
5029 case Builtin::BI__builtin_hlsl_wave_active_min:
5030 case Builtin::BI__builtin_hlsl_wave_active_sum:
5031 case Builtin::BI__builtin_hlsl_wave_active_product: {
5032 if (
SemaRef.checkArgCount(TheCall, 1))
5045 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5046 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5047 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5048 if (
SemaRef.checkArgCount(TheCall, 1))
5063 (VTy && VTy->getElementType()->isIntegerType()))) {
5065 diag::err_builtin_invalid_arg_type)
5066 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5074 case Builtin::BI__builtin_hlsl_interlocked_add:
5075 case Builtin::BI__builtin_hlsl_interlocked_and:
5076 case Builtin::BI__builtin_hlsl_interlocked_max:
5077 case Builtin::BI__builtin_hlsl_interlocked_min:
5078 case Builtin::BI__builtin_hlsl_interlocked_or:
5079 case Builtin::BI__builtin_hlsl_interlocked_xor:
5085 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5091 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5097 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5103 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5109 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5117 case Builtin::BI__builtin_elementwise_bitreverse: {
5125 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
5126 if (
SemaRef.checkArgCount(TheCall, 1))
5131 if (!(
ArgType->isScalarType())) {
5133 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5138 if (!(
ArgType->isBooleanType())) {
5140 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5147 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5148 if (
SemaRef.checkArgCount(TheCall, 2))
5156 diag::err_typecheck_convert_incompatible)
5157 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5170 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5171 if (
SemaRef.checkArgCount(TheCall, 1))
5180 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5181 if (
SemaRef.checkArgCount(TheCall, 0))
5185 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5186 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5187 if (
SemaRef.checkArgCount(TheCall, 1))
5200 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5201 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5202 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5203 if (
SemaRef.checkArgCount(TheCall, 1))
5215 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5216 if (
SemaRef.checkArgCount(TheCall, 3))
5222 SemaRef.Context.UnsignedIntTy, 1) ||
5224 SemaRef.Context.UnsignedIntTy, 2))
5232 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5233 if (
SemaRef.checkArgCount(TheCall, 1))
5240 case Builtin::BI__builtin_elementwise_acos:
5241 case Builtin::BI__builtin_elementwise_asin:
5242 case Builtin::BI__builtin_elementwise_atan:
5243 case Builtin::BI__builtin_elementwise_atan2:
5244 case Builtin::BI__builtin_elementwise_ceil:
5245 case Builtin::BI__builtin_elementwise_cos:
5246 case Builtin::BI__builtin_elementwise_cosh:
5247 case Builtin::BI__builtin_elementwise_exp:
5248 case Builtin::BI__builtin_elementwise_exp2:
5249 case Builtin::BI__builtin_elementwise_exp10:
5250 case Builtin::BI__builtin_elementwise_floor:
5251 case Builtin::BI__builtin_elementwise_fmod:
5252 case Builtin::BI__builtin_elementwise_log:
5253 case Builtin::BI__builtin_elementwise_log2:
5254 case Builtin::BI__builtin_elementwise_log10:
5255 case Builtin::BI__builtin_elementwise_pow:
5256 case Builtin::BI__builtin_elementwise_roundeven:
5257 case Builtin::BI__builtin_elementwise_sin:
5258 case Builtin::BI__builtin_elementwise_sinh:
5259 case Builtin::BI__builtin_elementwise_sqrt:
5260 case Builtin::BI__builtin_elementwise_tan:
5261 case Builtin::BI__builtin_elementwise_tanh:
5262 case Builtin::BI__builtin_elementwise_trunc: {
5268 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5269 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5270 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5271 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5272 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5277 std::optional<llvm::APSInt> Offset =
5279 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5281 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5287 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5288 if (
SemaRef.checkArgCount(TheCall, 1))
5299 ArgTy = VTy->getElementType();
5302 diag::err_builtin_invalid_arg_type)
5311 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5312 if (
SemaRef.checkArgCount(TheCall, 1))
5327 WorkList.push_back(BaseTy);
5328 while (!WorkList.empty()) {
5330 T =
T.getCanonicalType().getUnqualifiedType();
5331 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5339 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
5340 llvm::append_range(List, ElementFields);
5345 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5346 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5349 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5350 List.insert(List.end(), MT->getNumElementsFlattened(),
5351 MT->getElementType());
5354 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5355 if (RD->isStandardLayout())
5356 RD = RD->getStandardLayoutBaseWithFields();
5360 if (RD->
isUnion() || !RD->isAggregate()) {
5366 for (
const auto *FD : RD->
fields())
5367 if (!FD->isUnnamedBitField())
5368 FieldTypes.push_back(FD->
getType());
5370 std::reverse(FieldTypes.begin(), FieldTypes.end());
5371 llvm::append_range(WorkList, FieldTypes);
5375 if (!RD->isStandardLayout()) {
5377 for (
const auto &
Base : RD->bases())
5378 FieldTypes.push_back(
Base.getType());
5379 std::reverse(FieldTypes.begin(), FieldTypes.end());
5380 llvm::append_range(WorkList, FieldTypes);
5415 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5421 int ArraySize = VT->getNumElements();
5426 QualType ElTy = VT->getElementType();
5430 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5446 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5455 return llvm::equal(T1Types, T2Types,
5457 return SemaRef.IsLayoutCompatible(LHS, RHS);
5466 bool HadError =
false;
5468 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5476 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5477 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5478 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5479 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5481 if (NSpellingIdx != OSpellingIdx) {
5483 diag::err_hlsl_param_qualifier_mismatch)
5484 << NDAttr << NewParam;
5500 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5515 llvm_unreachable(
"HLSL doesn't support pointers.");
5518 llvm_unreachable(
"HLSL doesn't support complex types.");
5520 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5522 llvm_unreachable(
"Should have returned before this");
5532 llvm_unreachable(
"HLSL doesn't support complex types.");
5534 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5539 llvm_unreachable(
"HLSL doesn't support pointers.");
5541 llvm_unreachable(
"Should have returned before this");
5547 llvm_unreachable(
"HLSL doesn't support pointers.");
5550 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5554 llvm_unreachable(
"HLSL doesn't support complex types.");
5557 llvm_unreachable(
"Unhandled scalar cast");
5578 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5584 SrcTy = SrcMatTy->getElementType();
5589 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5590 if (DestTypes[I]->isUnionType())
5622 if (SrcTypes.size() < DestTypes.size())
5625 unsigned SrcSize = SrcTypes.size();
5626 unsigned DstSize = DestTypes.size();
5628 for (I = 0; I < DstSize && I < SrcSize; I++) {
5629 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5637 for (; I < SrcSize; I++) {
5638 if (SrcTypes[I]->isUnionType())
5658 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5659 "We should not get here without a parameter modifier expression");
5660 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5667 << Arg << (IsInOut ? 1 : 0);
5673 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5680 << Arg << (IsInOut ? 1 : 0);
5692 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5698 auto *OpV =
new (Ctx)
5704 tok::equal, ArgOpV, OpV);
5720 "Pointer and reference types cannot be inout or out parameters");
5721 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5737 for (
const auto *FD : RD->
fields()) {
5741 assert(RD->getNumBases() <= 1 &&
5742 "HLSL doesn't support multiple inheritance");
5743 return RD->getNumBases()
5748 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5749 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5761 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5766 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5772 if (
Decl->getType().hasAddressSpace())
5775 if (
Decl->getType()->isDependentType())
5787 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5801 llvm::Triple::Vulkan;
5802 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5803 if (HasDeclaredAPushConstant)
5809 HasDeclaredAPushConstant =
true;
5836class StructBindingContext {
5839 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5840 unsigned RegBindingOffset[4];
5843 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5844 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5845 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5846 static_cast<unsigned>(RegisterType::Sampler) == 3,
5847 "unexpected register type values");
5850 HLSLVkBindingAttr *VkBindingAttr;
5851 unsigned VkBindingOffset;
5856 StructBindingContext(
VarDecl *VD) {
5857 for (
unsigned i = 0; i < 4; ++i) {
5858 RegBindingsAttrs[i] =
nullptr;
5859 RegBindingOffset[i] = 0;
5861 VkBindingAttr =
nullptr;
5862 VkBindingOffset = 0;
5868 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5870 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5873 RegBindingsAttrs[RegTypeIdx] = RBA;
5878 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5879 VkBindingAttr = VBA;
5886 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5887 unsigned Range,
bool HasCounter) {
5888 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5890 if (VkBindingAttr) {
5891 unsigned Offset = VkBindingOffset;
5892 VkBindingOffset +=
Range;
5893 return HLSLVkBindingAttr::CreateImplicit(
5894 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5895 VkBindingAttr->getRange());
5898 HLSLResourceBindingAttr *RBA =
5899 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5900 HLSLResourceBindingAttr *NewAttr =
nullptr;
5902 if (RBA && RBA->hasRegisterSlot()) {
5905 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5906 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5908 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5909 StringRef NewSlotNumberStr =
5911 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5912 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5913 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5917 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5918 NewAttr->setBinding(RegType, std::nullopt,
5919 RBA ? RBA->getSpaceNumber() : 0);
5923 NewAttr->setImplicitCounterBindingOrderID(
5932static void createGlobalResourceDeclForStruct(
5934 QualType ResTy, StructBindingContext &BindingCtx) {
5936 "expected resource type or array of resources");
5947 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5948 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5953 const HLSLAttributedResourceType *ResHandleTy =
5954 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5958 Attr *BindingAttr = BindingCtx.createBindingAttr(
5960 ResDecl->
addAttr(BindingAttr);
5961 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5970 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5977static void handleArrayOfStructWithResources(
5979 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5984static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5986 EmbeddedResourceNameBuilder &NameBuilder,
5987 StructBindingContext &BindingCtx) {
5990 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5997 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6011 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6014 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6016 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6018 "resource arrays should have been already handled");
6019 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6028handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6030 EmbeddedResourceNameBuilder &NameBuilder,
6031 StructBindingContext &BindingCtx) {
6039 if (!SubCAT && !ElementRD)
6042 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6045 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6048 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6061void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6062 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6063 StructBindingContext BindingCtx(VD);
6067 "Expected non-resource struct or array type");
6070 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6074 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6075 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6083 if (
SemaRef.RequireCompleteType(
6086 diag::err_typecheck_decl_incomplete_type)) {
6100 DefaultCBufferDecls.push_back(VD);
6105 collectResourceBindingsOnVarDecl(VD);
6107 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6119 processExplicitBindingsOnDecl(VD);
6157 handleGlobalStructOrArrayOfWithResources(VD);
6161 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6170 "expected resource record type");
6186 const char *CreateMethodName;
6188 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6189 :
"__createFromBinding";
6191 CreateMethodName = HasCounter
6192 ?
"__createFromImplicitBindingWithImplicitCounter"
6193 :
"__createFromImplicitBinding";
6198 if (!CreateMethod) {
6203 "create method lookup should always succeed for built-in resource "
6212 Args.push_back(RegSlot);
6220 Args.push_back(OrderId);
6226 Args.push_back(Space);
6230 Args.push_back(RangeSize);
6234 Args.push_back(Index);
6236 StringRef VarName = VD->
getName();
6244 Args.push_back(NameCast);
6252 Args.push_back(CounterId);
6275 SemaRef.CheckCompleteVariableDeclaration(VD);
6281 "expected array of resource records");
6302 lookupMethod(
SemaRef, ResourceDecl,
6303 HasCounter ?
"__createFromBindingWithImplicitCounter"
6304 :
"__createFromBinding",
6308 CreateMethod = lookupMethod(
6310 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6311 :
"__createFromImplicitBinding",
6354std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6355 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6356 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6357 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6358 if (!TrueInfo || !FalseInfo)
6359 return std::nullopt;
6360 if (*TrueInfo != *FalseInfo)
6361 return std::nullopt;
6365 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6374 if (
const auto *AttrResType =
6375 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6377 return Bindings.getDeclBindingInfo(VD, RC);
6384void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6385 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6388 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6393 if (*ExprBinding ==
nullptr)
6396 auto PrevBinding = Assigns.find(VD);
6397 if (PrevBinding == Assigns.end()) {
6399 Assigns.insert({VD, *ExprBinding});
6404 if (*ExprBinding != PrevBinding->second) {
6406 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6408 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6419 "expected LHS to be a resource record or array of resource records");
6420 if (Opc != BO_Assign)
6425 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6433 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6438 trackLocalResource(VD, RHSExpr);
6455void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6457 "expected global variable that contains HLSL resource");
6460 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6461 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6462 ? ResourceClass::CBuffer
6463 : ResourceClass::SRV);
6476 if (
const HLSLAttributedResourceType *AttrResType =
6477 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6478 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6483 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6484 collectResourceBindingsOnUserRecordDecl(VD, RT);
6490void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6493 bool HasBinding =
false;
6494 for (Attr *A : VD->
attrs()) {
6497 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6498 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6501 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6502 if (!RBA || !RBA->hasRegisterSlot())
6507 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6508 "never have an attribute created");
6510 if (RT == RegisterType::C) {
6511 if (Bindings.hasBindingInfoForDecl(VD))
6513 diag::warn_hlsl_user_defined_type_missing_member)
6514 <<
static_cast<int>(RT);
6522 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6527 diag::warn_hlsl_user_defined_type_missing_member)
6528 <<
static_cast<int>(RT);
6536class InitListTransformer {
6540 QualType *DstIt =
nullptr;
6541 Expr **ArgIt =
nullptr;
6547 bool castInitializer(Expr *E) {
6548 assert(DstIt &&
"This should always be something!");
6549 if (DstIt == DestTypes.end()) {
6551 ArgExprs.push_back(E);
6556 DstIt = DestTypes.begin();
6559 Ctx, *DstIt,
false);
6564 ArgExprs.push_back(
Init);
6569 bool buildInitializerListImpl(Expr *E) {
6571 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6572 for (
auto *SubInit :
Init->inits())
6573 if (!buildInitializerListImpl(SubInit))
6583 return castInitializer(E);
6597 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6602 for (uint64_t I = 0; I <
Size; ++I) {
6604 SizeTy, SourceLocation());
6610 if (!castInitializer(ElExpr.
get()))
6615 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6616 unsigned Rows = MTy->getNumRows();
6617 unsigned Cols = MTy->getNumColumns();
6618 QualType ElemTy = MTy->getElementType();
6620 for (
unsigned R = 0;
R < Rows; ++
R) {
6621 for (
unsigned C = 0;
C < Cols; ++
C) {
6634 if (!castInitializer(ElExpr.
get()))
6642 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6646 for (uint64_t I = 0; I <
Size; ++I) {
6648 SizeTy, SourceLocation());
6653 if (!buildInitializerListImpl(ElExpr.
get()))
6660 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6661 RecordDecls.push_back(RD);
6662 while (RecordDecls.back()->getNumBases()) {
6663 CXXRecordDecl *D = RecordDecls.back();
6665 "HLSL doesn't support multiple inheritance");
6666 RecordDecls.push_back(
6669 while (!RecordDecls.empty()) {
6670 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6671 for (
auto *FD : RD->
fields()) {
6672 if (FD->isUnnamedBitField())
6680 if (!buildInitializerListImpl(Res.
get()))
6688 Expr *generateInitListsImpl(QualType Ty) {
6690 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6695 llvm::SmallVector<Expr *>
Inits;
6700 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6701 ElTy = ATy->getElementType();
6702 Size = ATy->getNumElements();
6703 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6704 ElTy = CMTy->getElementType();
6705 Size = CMTy->getNumElementsFlattened();
6708 ElTy = VTy->getElementType();
6709 Size = VTy->getZExtSize();
6711 for (uint64_t I = 0; I <
Size; ++I)
6712 Inits.push_back(generateInitListsImpl(ElTy));
6715 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6716 RecordDecls.push_back(RD);
6717 while (RecordDecls.back()->getNumBases()) {
6718 CXXRecordDecl *D = RecordDecls.back();
6720 "HLSL doesn't support multiple inheritance");
6721 RecordDecls.push_back(
6724 while (!RecordDecls.empty()) {
6725 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6726 for (
auto *FD : RD->
fields())
6727 if (!FD->isUnnamedBitField())
6732 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6733 Inits.back()->getEndLoc(),
false);
6734 NewInit->setType(Ty);
6739 llvm::SmallVector<QualType, 16> DestTypes;
6740 llvm::SmallVector<Expr *, 16> ArgExprs;
6741 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6742 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6743 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6744 InitTy = Entity.
getType().getNonReferenceType();
6754 DstIt = DestTypes.begin();
6757 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6759 Expr *generateInitLists() {
6760 assert(!ArgExprs.empty() &&
6761 "Call buildInitializerList to generate argument expressions.");
6762 ArgIt = ArgExprs.begin();
6764 return generateInitListsImpl(InitTy);
6765 llvm::SmallVector<Expr *>
Inits;
6766 while (ArgIt != ArgExprs.end())
6767 Inits.push_back(generateInitListsImpl(InitTy));
6770 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6771 Inits.back()->getEndLoc(),
false);
6772 llvm::APInt ArySize(64,
Inits.size());
6774 ArraySizeModifier::Normal, 0));
6786 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6793 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6797 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6817 if (
Init->getType()->isScalarType())
6820 InitListTransformer ILT(
SemaRef, Entity);
6822 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6830 Init->setInit(I, E);
6832 if (!ILT.buildInitializerList(E))
6835 size_t ExpectedSize = ILT.DestTypes.size();
6836 size_t ActualSize = ILT.ArgExprs.size();
6837 if (ExpectedSize == 0 && ActualSize == 0)
6844 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6846 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6847 << (int)(ExpectedSize < ActualSize) << InitTy
6848 << ExpectedSize << ActualSize;
6858 assert(ExpectedSize > 0 &&
6859 "The expected size of an incomplete array type must be at least 1.");
6861 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6869 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6870 if (ExpectedSize != ActualSize) {
6871 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6872 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6873 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6880 Init->resizeInits(Ctx, NewInit->getNumInits());
6881 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6882 Init->updateInit(Ctx, I, NewInit->getInit(I));
6890 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6900 StringRef AccessorName = CompName->
getName();
6901 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6903 unsigned Rows = MT->getNumRows();
6904 unsigned Cols = MT->getNumColumns();
6905 bool IsZeroBasedAccessor =
false;
6906 unsigned ChunkLen = 0;
6907 if (AccessorName.size() < 2)
6909 "length 4 for zero based: \'_mRC\' or "
6910 "length 3 for one-based: \'_RC\' accessor",
6913 if (AccessorName[0] ==
'_') {
6914 if (AccessorName[1] ==
'm') {
6915 IsZeroBasedAccessor =
true;
6922 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6925 if (AccessorName.size() % ChunkLen != 0) {
6926 const llvm::StringRef
Expected = IsZeroBasedAccessor
6927 ?
"zero based: '_mRC' accessor"
6928 :
"one-based: '_RC' accessor";
6933 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6934 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6935 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6937 bool HasRepeated =
false;
6939 unsigned NumComponents = 0;
6940 const char *Begin = AccessorName.data();
6942 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6943 const char *Chunk = Begin + I;
6944 char RowChar = 0, ColChar = 0;
6945 if (IsZeroBasedAccessor) {
6947 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6948 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6950 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6957 if (Chunk[0] !=
'_')
6959 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6966 bool IsDigitsError =
false;
6968 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6972 IsDigitsError =
true;
6976 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6980 IsDigitsError =
true;
6985 unsigned Row = RowChar -
'0';
6986 unsigned Col = ColChar -
'0';
6988 bool HasIndexingError =
false;
6989 if (IsZeroBasedAccessor) {
6991 if (!isZeroBasedIndex(Row)) {
6992 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6994 HasIndexingError =
true;
6996 if (!isZeroBasedIndex(Col)) {
6997 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6999 HasIndexingError =
true;
7003 if (!isOneBasedIndex(Row)) {
7004 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7006 HasIndexingError =
true;
7008 if (!isOneBasedIndex(Col)) {
7009 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7011 HasIndexingError =
true;
7018 if (HasIndexingError)
7024 bool HasBoundsError =
false;
7026 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7028 HasBoundsError =
true;
7031 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7033 HasBoundsError =
true;
7038 unsigned FlatIndex = Row * Cols + Col;
7039 if (Seen[FlatIndex])
7041 Seen[FlatIndex] =
true;
7044 if (NumComponents == 0 || NumComponents > 4) {
7045 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7050 QualType ElemTy = MT->getElementType();
7051 if (NumComponents == 1)
7057 for (Sema::ExtVectorDeclsType::iterator
7061 if ((*I)->getUnderlyingType() == VT)
7072 trackLocalResource(VDecl,
Init);
7074 const HLSLVkConstantIdAttr *ConstIdAttr =
7075 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7082 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7092 int ConstantID = ConstIdAttr->getId();
7093 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7095 ConstIdAttr->getLocation());
7099 if (
C->getType()->getCanonicalTypeUnqualified() !=
7103 Context.getTrivialTypeSourceInfo(
7104 Init->getType(),
Init->getExprLoc()),
7123 if (!Params || Params->
size() != 1)
7136 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7137 if (TTP->hasDefaultArgument()) {
7138 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7141 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7142 if (NTTP->hasDefaultArgument()) {
7143 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7146 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7147 if (TTPD->hasDefaultArgument()) {
7148 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7155 return SemaRef.CheckTemplateIdType(
7157 TemplateArgs,
nullptr,
false);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool containsIncompleteArrayType(QualType Ty)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static StringRef createRegisterString(ASTContext &AST, RegisterType RegType, unsigned N)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static QualType ReportMatrixInvalidMember(Sema &S, StringRef Name, StringRef Expected, SourceLocation OpLoc, SourceLocation CompLoc)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool CheckScalarFloatOperand(Sema &S, CallExpr *TheCall, unsigned ArgIndex)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckAnyScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool hasConstantBufferLayout(QualType QT)
llvm::dxbc::PSV::SemanticKind SemanticKind
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckIntegerElementTypeShaderModel(Sema &S, CallExpr *TheCall, QualType ContainedType, SampleKind Kind)
static bool isMatrixType(QualType QT)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckCalculateLodBuiltin(Sema &S, CallExpr *TheCall)
static QualType getScalarComponentType(QualType T)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckNoDoubleElementType(Sema &S, CallExpr *TheCall, QualType ContainedType, StringRef DefaultName)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static const Type * createHostLayoutType(Sema &S, const Type *Ty)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool CheckInterlockedBuiltin(Sema &S, CallExpr *TheCall, unsigned MinArgs, unsigned MaxArgs, InterlockedDest Dest, bool ReportsOriginalValue)
Check a call to an HLSL interlocked builtin.
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool CheckMatrixSelect(Sema *S, CallExpr *TheCall)
static bool CheckArgAddrSpaceOneOf(Sema *S, CallExpr *TheCall, unsigned ArgIndex, ArrayRef< LangAS > AllowedSpaces)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static StringRef getSampleMethodName(SampleKind Kind)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall)
static RegisterType getRegisterType(ResourceClass RC)
static bool ValidateRegisterNumber(uint64_t SlotNum, Decl *TheDecl, ASTContext &Ctx, RegisterType RegTy)
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static char getRegisterTypeChar(RegisterType RT)
static bool CheckNotBoolScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType getTypedResourceElementType(QualType ContainedType)
static bool findExistingMatrixLayoutMarker(QualType T, attr::Kind &ExistingKind)
Walks the existing AttributedType sugar of T looking for a previously applied HLSLRowMajor/HLSLColumn...
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckWavePrefix(Sema *S, CallExpr *TheCall)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static LangAS getLangASFromResourceClass(ResourceClass RC)
static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall, bool IncludeArraySlice=true)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static const Type * getHostLayoutFieldType(QualType QT)
InterlockedDest
The dest types an interlocked operation accepts. Float is 32-bit only.
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static QualType getVectorOrScalarType(Sema &S, QualType BaseType, unsigned Count)
static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind)
static bool CheckScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckFloatRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyDoubleRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
static StringRef getCurrentResourceMethodName(Sema &S, StringRef DefaultName)
static bool IsDefaultBufferConstantDecl(const ASTContext &Ctx, VarDecl *VD)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool CheckGatherBuiltin(Sema &S, CallExpr *TheCall, bool IsCmp)
static bool isValidWaveSizeValue(unsigned Value)
static bool isResourceRecordTypeOrArrayOf(QualType Ty)
static bool CheckLoadMSBuiltin(Sema &S, CallExpr *TheCall)
static bool AccumulateHLSLResourceSlots(QualType Ty, uint64_t &StartSlot, const uint64_t &Limit, const ResourceClass ResClass, ASTContext &Ctx, uint64_t ArrayCount=1)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns, std::optional< MatrixType::LayoutKind > Layout=std::nullopt) const
Return the unique reference to the matrix type of the specified element type and size.
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
llvm::StringRef backupStr(llvm::StringRef S) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getLocation() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
base_class_iterator bases_end()
void completeDefinition() override
Indicates that the definition of this class is now complete.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
bool isHLSLBuiltinRecord() const
Returns true if the class is a built-in HLSL record.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceLocation getEndLoc() const
static CanQual< Type > CreateUnsafe(QualType Other)
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
llvm::APInt getSize() const
Return the constant array size as an APInt.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
unsigned getNumRows() const
Returns the number of rows in the matrix.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
attr_iterator attr_end() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
attr_iterator attr_begin() const
DeclContext * getNonTransparentDeclContext()
Return the non transparent context.
bool isInvalidDecl() const
SourceLocation getLocation() const
void setImplicit(bool I=true)
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
Represents a ValueDecl that came out of a declarator.
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
ExtVectorType - Extended vector type.
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
DeclarationNameInfo getNameInfo() const
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
void addLayoutStruct(CXXRecordDecl *LS)
void setHasValidPackoffset(bool PO)
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
buffer_decl_range buffer_decls() const
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
iterator begin(ExternalSemaSource *source, bool LocalOnly=false)
Represents the results of name lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Represents a matrix type, as defined in the Matrix Types clang extensions.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
NamedDecl * getUnderlyingDecl()
Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
A C++ nested-name-specifier augmented with source location information.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
bool hasParsedType() const
void setInvalid(bool b=true) const
const ParsedType & getTypeArg() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
AttributeCommonInfo::Kind getKind() const
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
RecordDecl * getDefinitionOrSelf() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
ASTContext & getASTContext() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
void handleVkLocationAttr(Decl *D, const ParsedAttr &AL)
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
void handleSemanticAttr(Decl *D, const ParsedAttr &AL)
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleInterpolationModifierAttr(Decl *D, const ParsedAttr &AL)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
uint32_t getNextImplicitBindingOrderID()
void CheckEntryPoint(FunctionDecl *FD)
void handleVkExtBuiltinOutputAttr(Decl *D, const ParsedAttr &AL)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)
bool initGlobalResourceDecl(VarDecl *VD)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
bool initGlobalResourceArrayDecl(VarDecl *VD)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
Attr * buildMatrixLayoutTypeAttr(QualType T, const ParsedAttr &AL)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool diagnoseIndexType(QualType T, const ParsedAttr &AL)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool ActOnResourceMemberAccessExpr(MemberExpr *ME)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
QualType ActOnTemplateShorthand(TemplateDecl *Template, SourceLocation NameLoc)
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
QualType checkMatrixComponent(Sema &S, QualType baseType, ExprValueKind &VK, SourceLocation OpLoc, const IdentifierInfo *CompName, SourceLocation CompLoc)
bool IsConstantBufferElementCompatible(QualType T1)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
bool ActOnUninitializedVarDecl(VarDecl *D)
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
bool canHaveOverloadedBinOp(QualType Ty, BinaryOperatorKind Opc)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
void handleVkPushConstantAttr(Decl *D, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
NamedDecl * getConstantBufferConversionFunction(QualType Type, CXXRecordDecl *RD)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional< unsigned > Index)
QualType getInoutParameterType(QualType Ty)
bool diagnoseFloatType(QualType T, const ParsedAttr &AL)
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
std::optional< ExprResult > tryPerformConstantBufferConversion(Expr *BaseExpr)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
bool diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T, SourceLocation Loc)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
bool CanPerformPackedTypeCast(Expr *Src, QualType DestTy)
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount)
Checks that a call expression's argument count is at most the desired number.
ExtVectorDeclsType ExtVectorDecls
ExtVectorDecls - This is a list all the extended vector types.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult TemporaryMaterializationConversion(Expr *E)
If E is a prvalue denoting an unmaterialized temporary, materialize it as an xvalue.
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExternalSemaSource * getExternalSource() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isHLSLBuiltinPackedType() const
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
void pushBaseName(llvm::StringRef N)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
Defines the clang::TargetInfo interface.
uint32_t getResourceDimensions(llvm::dxil::ResourceDimension Dim)
bool hasResourceOffset(llvm::dxil::ResourceDimension Dim)
bool hasCounterHandle(const CXXRecordDecl *RD)
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
@ Template
We are parsing a template declaration.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr, Expr *SampleCountExpr=nullptr)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
unsigned getImplicitOrderID() const
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
bool hasImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const