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"
64 case ResourceClass::SRV:
65 return RegisterType::SRV;
66 case ResourceClass::UAV:
67 return RegisterType::UAV;
68 case ResourceClass::CBuffer:
69 return RegisterType::CBuffer;
70 case ResourceClass::Sampler:
71 return RegisterType::Sampler;
73 llvm_unreachable(
"unexpected ResourceClass value");
82 case ResourceClass::SRV:
83 case ResourceClass::UAV:
85 case ResourceClass::CBuffer:
87 case ResourceClass::Sampler:
90 llvm_unreachable(
"unexpected ResourceClass value");
96 assert(RT !=
nullptr);
100 *RT = RegisterType::SRV;
104 *RT = RegisterType::UAV;
108 *RT = RegisterType::CBuffer;
112 *RT = RegisterType::Sampler;
116 *RT = RegisterType::C;
120 *RT = RegisterType::I;
129 case RegisterType::SRV:
131 case RegisterType::UAV:
133 case RegisterType::CBuffer:
135 case RegisterType::Sampler:
137 case RegisterType::C:
139 case RegisterType::I:
142 llvm_unreachable(
"unexpected RegisterType value");
147 case RegisterType::SRV:
148 return ResourceClass::SRV;
149 case RegisterType::UAV:
150 return ResourceClass::UAV;
151 case RegisterType::CBuffer:
152 return ResourceClass::CBuffer;
153 case RegisterType::Sampler:
154 return ResourceClass::Sampler;
155 case RegisterType::C:
156 case RegisterType::I:
160 llvm_unreachable(
"unexpected RegisterType value");
164 const auto *BT = dyn_cast<BuiltinType>(
Type);
168 return Builtin::BI__builtin_get_spirv_spec_constant_int;
171 switch (BT->getKind()) {
172 case BuiltinType::Bool:
173 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
174 case BuiltinType::Short:
175 return Builtin::BI__builtin_get_spirv_spec_constant_short;
176 case BuiltinType::Int:
177 return Builtin::BI__builtin_get_spirv_spec_constant_int;
178 case BuiltinType::LongLong:
179 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
180 case BuiltinType::UShort:
181 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
182 case BuiltinType::UInt:
183 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
184 case BuiltinType::ULongLong:
185 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
186 case BuiltinType::Half:
187 return Builtin::BI__builtin_get_spirv_spec_constant_half;
188 case BuiltinType::Float:
189 return Builtin::BI__builtin_get_spirv_spec_constant_float;
190 case BuiltinType::Double:
191 return Builtin::BI__builtin_get_spirv_spec_constant_double;
200 llvm::raw_svector_ostream OS(Buffer);
207 ResourceClass ResClass) {
209 "DeclBindingInfo already added");
215 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
216 return &BindingsList.emplace_back(VD, ResClass);
220 ResourceClass ResClass) {
221 auto Entry = DeclToBindingListIndex.find(VD);
222 if (Entry != DeclToBindingListIndex.end()) {
223 for (
unsigned Index = Entry->getSecond();
224 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
226 if (BindingsList[Index].ResClass == ResClass)
227 return &BindingsList[Index];
234 return DeclToBindingListIndex.contains(VD);
246 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
249 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
250 : llvm::hlsl::ResourceClass::SRV;
262 if (T->isArrayType() || T->isStructureType() || T->isConstantMatrixType())
269 assert(Context.getTypeSize(T) <= 64 &&
270 "Scalar bit widths larger than 64 not supported");
273 return Context.getTypeSize(T) / 8;
280 constexpr unsigned CBufferAlign = 16;
281 if (
const auto *RD = T->getAsRecordDecl()) {
283 for (
const FieldDecl *Field : RD->fields()) {
290 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
291 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
292 FieldAlign = CBufferAlign;
295 Size = llvm::alignTo(Size, FieldAlign);
302 unsigned ElementCount = AT->getSize().getZExtValue();
303 if (ElementCount == 0)
306 unsigned ElementSize =
308 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
309 return AlignedElementSize * (ElementCount - 1) + ElementSize;
313 unsigned ElementCount = VT->getNumElements();
314 unsigned ElementSize =
316 return ElementSize * ElementCount;
319 return Context.getTypeSize(T) / 8;
330 bool HasPackOffset =
false;
331 bool HasNonPackOffset =
false;
333 VarDecl *Var = dyn_cast<VarDecl>(Field);
336 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
337 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
338 HasPackOffset =
true;
340 HasNonPackOffset =
true;
347 if (HasNonPackOffset)
354 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
355 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
356 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
357 return LHS.second->getOffsetInBytes() <
358 RHS.second->getOffsetInBytes();
360 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
361 VarDecl *Var = PackOffsetVec[i].first;
362 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
364 unsigned Begin =
Attr->getOffsetInBytes();
365 unsigned End = Begin + Size;
366 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
367 if (End > NextBegin) {
368 VarDecl *NextVar = PackOffsetVec[i + 1].first;
380 CAT = dyn_cast<ConstantArrayType>(
382 return CAT !=
nullptr;
393static const HLSLAttributedResourceType *
396 "expected array of resource records");
398 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
400 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
403static const HLSLAttributedResourceType *
417 return RD->isEmpty();
446 Base.getType()->castAsCXXRecordDecl()))
457 assert(RD ==
nullptr &&
458 "there should be at most 1 record by a given name in a scope");
475 Name.append(NameBaseII->
getName());
482 size_t NameLength = Name.size();
491 Name.append(llvm::Twine(suffix).str());
492 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
499 Name.truncate(NameLength);
514 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
516 S, CAT->getElementType()->getUnqualifiedDesugaredType());
521 CAT->getSizeModifier(),
522 CAT->getIndexTypeCVRQualifiers())
571 "struct is already HLSL buffer compatible");
585 LS->
addAttr(PackedAttr::CreateImplicit(AST));
589 if (
unsigned NumBases = StructDecl->
getNumBases()) {
590 assert(NumBases == 1 &&
"HLSL supports only one base type");
640 LS->
addAttr(PackedAttr::CreateImplicit(AST));
645 VarDecl *VD = dyn_cast<VarDecl>(D);
661 "host layout field for $Globals decl failed to be created");
680 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
681 Attr->setBinding(RT, std::nullopt, 0);
682 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
689 BufDecl->setRBraceLoc(RBrace);
706 BufDecl->isCBuffer() ? RegisterType::CBuffer
716 int X,
int Y,
int Z) {
717 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
718 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
719 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
720 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
730 int Min,
int Max,
int Preferred,
731 int SpelledArgsCount) {
732 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
733 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
734 WS->getPreferred() != Preferred ||
735 WS->getSpelledArgsCount() != SpelledArgsCount) {
736 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
737 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
743 Result->setSpelledArgsCount(SpelledArgsCount);
747HLSLVkConstantIdAttr *
753 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
761 Diag(VD->getLocation(), diag::err_specialization_const);
765 if (!VD->getType().isConstQualified()) {
766 Diag(VD->getLocation(), diag::err_specialization_const);
770 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
771 if (CI->getId() != Id) {
772 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
773 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
778 HLSLVkConstantIdAttr *
Result =
785 llvm::Triple::EnvironmentType ShaderType) {
786 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
787 if (NT->getType() != ShaderType) {
788 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
789 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
793 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
796HLSLParamModifierAttr *
798 HLSLParamModifierAttr::Spelling Spelling) {
801 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
802 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
803 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
804 D->
dropAttr<HLSLParamModifierAttr>();
806 return HLSLParamModifierAttr::Create(
808 HLSLParamModifierAttr::Keyword_inout);
810 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
811 Diag(PA->getLocation(), diag::note_conflicting_attribute);
837 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
838 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
841 if (Shader->getType() != Env) {
842 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
854 case llvm::Triple::UnknownEnvironment:
855 case llvm::Triple::Library:
857 case llvm::Triple::RootSignature:
858 llvm_unreachable(
"rootsig environment has no functions");
860 llvm_unreachable(
"Unhandled environment in triple");
866 HLSLAppliedSemanticAttr *Semantic,
871 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
872 assert(ShaderAttr &&
"Entry point has no shader attribute");
873 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
874 auto SemanticName = Semantic->getSemanticName().upper();
879 if (SemanticName ==
"SV_POSITION") {
880 return (ST == llvm::Triple::Vertex && !IsInput) ||
881 (ST == llvm::Triple::Pixel && IsInput);
883 if (SemanticName ==
"SV_VERTEXID")
889bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
892 SemanticInfo &ActiveSemantic,
893 SemaHLSL::SemanticContext &SC) {
894 if (ActiveSemantic.Semantic ==
nullptr) {
895 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
896 if (ActiveSemantic.Semantic)
897 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
900 if (!ActiveSemantic.Semantic) {
906 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
907 ActiveSemantic.Semantic->getAttrName()->getName(),
908 ActiveSemantic.Index.value_or(0));
912 checkSemanticAnnotation(FD, D, A, SC);
913 OutputDecl->addAttr(A);
915 unsigned Location = ActiveSemantic.Index.value_or(0);
918 SC.CurrentIOType & IOType::In)) {
919 bool HasVkLocation =
false;
920 if (
auto *A = D->getAttr<HLSLVkLocationAttr>()) {
921 HasVkLocation = true;
922 Location = A->getLocation();
925 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
926 Diag(D->getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
929 SC.UsesExplicitVkLocations = HasVkLocation;
932 const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->getType());
933 unsigned ElementCount = AT ? AT->
getZExtSize() : 1;
934 ActiveSemantic.Index = Location + ElementCount;
936 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
937 for (
unsigned I = 0; I < ElementCount; ++I) {
938 Twine VariableName = BaseName.concat(Twine(Location + I));
940 auto [_, Inserted] = SC.ActiveSemantics.insert(VariableName.str());
942 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
943 << VariableName.str();
954 SemanticInfo &ActiveSemantic,
955 SemaHLSL::SemanticContext &SC) {
956 if (ActiveSemantic.Semantic ==
nullptr) {
957 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
958 if (ActiveSemantic.Semantic)
959 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
965 const RecordType *RT = dyn_cast<RecordType>(T);
967 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
970 const RecordDecl *RD = RT->getDecl();
971 for (FieldDecl *Field : RD->
fields()) {
972 SemanticInfo Info = ActiveSemantic;
973 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
974 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
977 if (ActiveSemantic.Semantic)
978 ActiveSemantic = Info;
985 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
986 assert(ShaderAttr &&
"Entry point has no shader attribute");
987 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
991 case llvm::Triple::Pixel:
992 case llvm::Triple::Vertex:
993 case llvm::Triple::Geometry:
994 case llvm::Triple::Hull:
995 case llvm::Triple::Domain:
996 case llvm::Triple::RayGeneration:
997 case llvm::Triple::Intersection:
998 case llvm::Triple::AnyHit:
999 case llvm::Triple::ClosestHit:
1000 case llvm::Triple::Miss:
1001 case llvm::Triple::Callable:
1002 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1003 diagnoseAttrStageMismatch(NT, ST,
1004 {llvm::Triple::Compute,
1005 llvm::Triple::Amplification,
1006 llvm::Triple::Mesh});
1009 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1010 diagnoseAttrStageMismatch(WS, ST,
1011 {llvm::Triple::Compute,
1012 llvm::Triple::Amplification,
1013 llvm::Triple::Mesh});
1018 case llvm::Triple::Compute:
1019 case llvm::Triple::Amplification:
1020 case llvm::Triple::Mesh:
1021 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1023 << llvm::Triple::getEnvironmentTypeName(ST);
1026 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1027 if (Ver < VersionTuple(6, 6)) {
1028 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1031 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1034 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1035 << WS << WS->getSpelledArgsCount() <<
"6.8";
1040 case llvm::Triple::RootSignature:
1041 llvm_unreachable(
"rootsig environment has no function entry point");
1043 llvm_unreachable(
"Unhandled environment in triple");
1046 SemaHLSL::SemanticContext InputSC = {};
1047 InputSC.CurrentIOType = IOType::In;
1050 SemanticInfo ActiveSemantic;
1051 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1052 if (ActiveSemantic.Semantic)
1053 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1056 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, InputSC)) {
1057 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1062 SemanticInfo ActiveSemantic;
1063 SemaHLSL::SemanticContext OutputSC = {};
1064 OutputSC.CurrentIOType = IOType::Out;
1065 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1066 if (ActiveSemantic.Semantic)
1067 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1069 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1072void SemaHLSL::checkSemanticAnnotation(
1074 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC) {
1075 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1076 assert(ShaderAttr &&
"Entry point has no shader attribute");
1077 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1079 auto SemanticName = SemanticAttr->getSemanticName().upper();
1080 if (SemanticName ==
"SV_DISPATCHTHREADID" ||
1081 SemanticName ==
"SV_GROUPINDEX" || SemanticName ==
"SV_GROUPTHREADID" ||
1082 SemanticName ==
"SV_GROUPID") {
1084 if (ST != llvm::Triple::Compute)
1085 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1086 {{llvm::Triple::Compute, IOType::In}});
1088 if (SemanticAttr->getSemanticIndex() != 0) {
1089 std::string PrettyName =
1090 "'" + SemanticAttr->getSemanticName().str() +
"'";
1091 Diag(SemanticAttr->getLoc(),
1092 diag::err_hlsl_semantic_indexing_not_supported)
1098 if (SemanticName ==
"SV_POSITION") {
1101 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1102 {{llvm::Triple::Vertex, IOType::InOut},
1103 {llvm::Triple::Pixel, IOType::In}});
1106 if (SemanticName ==
"SV_VERTEXID") {
1107 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1108 {{llvm::Triple::Vertex, IOType::In}});
1112 if (SemanticName ==
"SV_TARGET") {
1113 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1114 {{llvm::Triple::Pixel, IOType::Out}});
1120 if (SemanticAttr->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1121 llvm_unreachable(
"Unknown SemanticAttr");
1124void SemaHLSL::diagnoseAttrStageMismatch(
1125 const Attr *A, llvm::Triple::EnvironmentType Stage,
1126 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1127 SmallVector<StringRef, 8> StageStrings;
1128 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1129 [](llvm::Triple::EnvironmentType ST) {
1131 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1133 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1134 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1135 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
1138void SemaHLSL::diagnoseSemanticStageMismatch(
1139 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1140 std::initializer_list<SemanticStageInfo> Allowed) {
1142 for (
auto &Case : Allowed) {
1143 if (Case.Stage != Stage)
1146 if (CurrentIOType & Case.AllowedIOTypesMask)
1149 SmallVector<std::string, 8> ValidCases;
1151 Allowed, std::back_inserter(ValidCases), [](SemanticStageInfo Case) {
1152 SmallVector<std::string, 2> ValidType;
1153 if (Case.AllowedIOTypesMask & IOType::In)
1154 ValidType.push_back(
"input");
1155 if (Case.AllowedIOTypesMask & IOType::Out)
1156 ValidType.push_back(
"output");
1158 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage)) +
1159 " " + join(ValidType,
"/");
1161 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1162 << A->
getAttrName() << (CurrentIOType & IOType::In ?
"input" :
"output")
1163 << llvm::Triple::getEnvironmentTypeName(Case.Stage)
1164 << join(ValidCases,
", ");
1168 SmallVector<StringRef, 8> StageStrings;
1170 Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {
1172 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
1175 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1176 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1177 << (Allowed.size() != 1) << join(StageStrings,
", ");
1180template <CastKind Kind>
1183 Ty = VTy->getElementType();
1188template <CastKind Kind>
1200 if (LHSFloat && RHSFloat) {
1228 if (LHSSigned == RHSSigned) {
1229 if (IsCompAssign || IntOrder >= 0)
1237 if (IntOrder != (LHSSigned ? 1 : -1)) {
1238 if (IsCompAssign || RHSSigned)
1246 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1247 if (IsCompAssign || LHSSigned)
1263 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1264 QualType NewTy = Ctx.getExtVectorType(
1274 return CK_FloatingCast;
1276 return CK_IntegralCast;
1278 return CK_IntegralToFloating;
1280 return CK_FloatingToIntegral;
1286 bool IsCompAssign) {
1293 if (!LVecTy && IsCompAssign) {
1295 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1297 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1299 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1304 unsigned EndSz = std::numeric_limits<unsigned>::max();
1307 LSz = EndSz = LVecTy->getNumElements();
1310 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1311 "one of the above should have had a value");
1315 if (IsCompAssign && LSz != EndSz) {
1317 diag::err_hlsl_vector_compound_assignment_truncation)
1318 << LHSType << RHSType;
1324 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1329 if (!IsCompAssign && !LVecTy)
1333 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1334 return Ctx.getCommonSugaredType(LHSType, RHSType);
1342 LElTy, RElTy, IsCompAssign);
1345 "HLSL Vectors can only contain integer or floating point types");
1347 LElTy, RElTy, IsCompAssign);
1352 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1353 "Called with non-logical operator");
1355 llvm::raw_svector_ostream OS(Buff);
1357 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1358 OS << NewFnName <<
"(";
1368std::pair<IdentifierInfo *, bool>
1371 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1378 return {DeclIdent,
Found};
1389 for (
auto &RootSigElement : RootElements)
1390 Elements.push_back(RootSigElement.getElement());
1394 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1396 SignatureDecl->setImplicit();
1402 if (RootSigOverrideIdent) {
1405 if (
SemaRef.LookupQualifiedName(R, DC))
1406 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1414struct PerVisibilityBindingChecker {
1417 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1421 llvm::dxbc::ShaderVisibility Vis;
1426 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1428 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1429 llvm::dxil::ResourceClass RC,
uint32_t Space,
1431 const hlsl::RootSignatureElement *Elem) {
1433 assert(BuilderIndex < Builders.size() &&
1434 "Not enough builders for visibility type");
1435 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1436 static_cast<const void *
>(Elem));
1438 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1439 "'All' visibility must come first");
1440 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1441 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1442 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1443 static_cast<const void *
>(Elem));
1445 ElemInfoMap.push_back({Elem,
Visibility,
false});
1448 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1449 auto It = llvm::lower_bound(
1451 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1452 assert(It->Elem == Elem &&
"Element not in map");
1456 bool checkOverlap() {
1457 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1458 return LHS.Elem < RHS.Elem;
1461 bool HadOverlap =
false;
1463 using llvm::hlsl::BindingInfoBuilder;
1464 auto ReportOverlap = [
this,
1465 &HadOverlap](
const BindingInfoBuilder &Builder,
1466 const llvm::hlsl::Binding &Reported) {
1470 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1471 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1472 const auto *PrevElem =
1473 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1475 ElemInfo &Info =
getInfo(Elem);
1480 Info.Diagnosed =
true;
1482 ElemInfo &PrevInfo =
getInfo(PrevElem);
1483 llvm::dxbc::ShaderVisibility CommonVis =
1484 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1487 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1488 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1489 << Reported.isUnbounded() << Reported.UpperBound
1494 this->S->
Diag(PrevElem->getLocation(),
1495 diag::note_hlsl_resource_range_here);
1498 for (BindingInfoBuilder &Builder : Builders)
1499 Builder.calculateBindingInfo(ReportOverlap);
1519 bool HadError =
false;
1520 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1521 uint32_t UpperBound) {
1523 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1524 << LowerBound << UpperBound;
1531 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1532 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1533 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1536 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1537 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1538 ReportError(Loc, 0, 0xfffffffe);
1541 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1542 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1543 ReportError(Loc, 0, 0xffffffef);
1546 const uint32_t Version =
1547 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1548 const uint32_t VersionEnum = Version - 1;
1549 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1551 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1558 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1559 if (
const auto *Descriptor =
1560 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1561 VerifyRegister(Loc, Descriptor->Reg.Number);
1562 VerifySpace(Loc, Descriptor->Space);
1564 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1566 ReportFlagError(Loc);
1567 }
else if (
const auto *Constants =
1568 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1569 VerifyRegister(Loc, Constants->Reg.Number);
1570 VerifySpace(Loc, Constants->Space);
1571 }
else if (
const auto *Sampler =
1572 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1573 VerifyRegister(Loc, Sampler->Reg.Number);
1574 VerifySpace(Loc, Sampler->Space);
1577 "By construction, parseFloatParam can't produce a NaN from a "
1578 "float_literal token");
1580 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1581 ReportError(Loc, 0, 16);
1582 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1583 ReportFloatError(Loc, -16.f, 15.99f);
1584 }
else if (
const auto *Clause =
1585 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1587 VerifyRegister(Loc, Clause->Reg.Number);
1588 VerifySpace(Loc, Clause->Space);
1590 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1594 ReportError(Loc, 1, 0xfffffffe);
1597 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1599 ReportFlagError(Loc);
1603 PerVisibilityBindingChecker BindingChecker(
this);
1604 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1609 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1610 if (
const auto *Descriptor =
1611 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1612 uint32_t LowerBound(Descriptor->Reg.Number);
1613 uint32_t UpperBound(LowerBound);
1615 BindingChecker.trackBinding(
1616 Descriptor->Visibility,
1617 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1618 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1619 }
else if (
const auto *Constants =
1620 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1621 uint32_t LowerBound(Constants->Reg.Number);
1622 uint32_t UpperBound(LowerBound);
1624 BindingChecker.trackBinding(
1625 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1626 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1627 }
else if (
const auto *Sampler =
1628 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1629 uint32_t LowerBound(Sampler->Reg.Number);
1630 uint32_t UpperBound(LowerBound);
1632 BindingChecker.trackBinding(
1633 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1634 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1635 }
else if (
const auto *Clause =
1636 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1639 UnboundClauses.emplace_back(Clause, &RootSigElem);
1640 }
else if (
const auto *Table =
1641 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1642 assert(UnboundClauses.size() == Table->NumClauses &&
1643 "Number of unbound elements must match the number of clauses");
1644 bool HasAnySampler =
false;
1645 bool HasAnyNonSampler =
false;
1646 uint64_t Offset = 0;
1647 bool IsPrevUnbound =
false;
1648 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1650 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1651 HasAnySampler =
true;
1653 HasAnyNonSampler =
true;
1655 if (HasAnySampler && HasAnyNonSampler)
1656 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1661 if (Clause->NumDescriptors == 0)
1665 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1667 Offset = Clause->Offset;
1669 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1670 Offset, Clause->NumDescriptors);
1672 if (IsPrevUnbound && IsAppending)
1673 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1674 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1675 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1678 Offset = RangeBound + 1;
1679 IsPrevUnbound = Clause->NumDescriptors ==
1680 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1683 uint32_t LowerBound(Clause->Reg.Number);
1684 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1685 LowerBound, Clause->NumDescriptors);
1687 BindingChecker.trackBinding(
1689 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1690 LowerBound, UpperBound, ClauseElem);
1692 UnboundClauses.clear();
1696 return BindingChecker.checkOverlap();
1701 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1706 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1707 if (RS->getSignatureIdent() != Ident) {
1708 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1712 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1718 if (
auto *SignatureDecl =
1719 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1726 llvm::VersionTuple SMVersion =
1731 uint32_t ZMax = 1024;
1732 uint32_t ThreadMax = 1024;
1733 if (IsDXIL && SMVersion.getMajor() <= 4) {
1736 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1746 diag::err_hlsl_numthreads_argument_oor)
1755 diag::err_hlsl_numthreads_argument_oor)
1764 diag::err_hlsl_numthreads_argument_oor)
1769 if (
X * Y * Z > ThreadMax) {
1770 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1787 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1795 if (SpelledArgsCount > 1 &&
1799 uint32_t Preferred = 0;
1800 if (SpelledArgsCount > 2 &&
1804 if (SpelledArgsCount > 2) {
1807 diag::err_attribute_power_of_two_in_range)
1808 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1813 if (Preferred < Min || Preferred >
Max) {
1815 diag::err_attribute_power_of_two_in_range)
1816 << AL <<
Min <<
Max << Preferred;
1819 }
else if (SpelledArgsCount > 1) {
1822 diag::err_attribute_power_of_two_in_range)
1823 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1827 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1830 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1835 diag::err_attribute_power_of_two_in_range)
1836 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1841 HLSLWaveSizeAttr *NewAttr =
1878 uint32_t Binding = 0;
1902 if (!T->hasUnsignedIntegerRepresentation() ||
1903 (VT && VT->getNumElements() > 3)) {
1904 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1905 << AL <<
"uint/uint2/uint3";
1914 if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1915 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1916 << AL <<
"float/float1/float2/float3/float4";
1924 std::optional<unsigned> Index) {
1928 QualType ValueType = VD->getType();
1929 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1932 bool IsOutput =
false;
1933 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1940 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1943 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1944 if (Index.has_value())
1945 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1950 if (SemanticName ==
"SV_GROUPINDEX") {
1952 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1953 if (Index.has_value())
1954 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1959 if (SemanticName ==
"SV_GROUPTHREADID") {
1962 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1963 if (Index.has_value())
1964 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1969 if (SemanticName ==
"SV_GROUPID") {
1972 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1973 if (Index.has_value())
1974 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1979 if (SemanticName ==
"SV_POSITION") {
1980 const auto *VT = ValueType->getAs<
VectorType>();
1981 if (!ValueType->hasFloatingRepresentation() ||
1982 (VT && VT->getNumElements() > 4))
1983 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1984 << AL <<
"float/float1/float2/float3/float4";
1989 if (SemanticName ==
"SV_VERTEXID") {
1990 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
1991 if (!ValueType->isUnsignedIntegerType() || SizeInBits != 32)
1992 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
1997 if (SemanticName ==
"SV_TARGET") {
1998 const auto *VT = ValueType->getAs<
VectorType>();
1999 if (!ValueType->hasFloatingRepresentation() ||
2000 (VT && VT->getNumElements() > 4))
2001 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
2002 << AL <<
"float/float1/float2/float3/float4";
2007 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2011 uint32_t IndexValue(0), ExplicitIndex(0);
2014 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2016 assert(IndexValue > 0 ? ExplicitIndex :
true);
2017 std::optional<unsigned> Index =
2018 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
2028 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2029 << AL <<
"shader constant in a constant buffer";
2033 uint32_t SubComponent;
2043 bool IsAggregateTy = (T->isArrayType() || T->isStructureType());
2048 if (IsAggregateTy) {
2049 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2053 if ((Component * 32 + Size) > 128) {
2054 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2059 EltTy = VT->getElementType();
2061 if (Align > 32 && Component == 1) {
2064 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2078 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2081 llvm::Triple::EnvironmentType ShaderType;
2082 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2083 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2084 << AL << Str << ArgLoc;
2098 assert(AttrList.size() &&
"expected list of resource attributes");
2105 HLSLAttributedResourceType::Attributes ResAttrs;
2107 bool HasResourceClass =
false;
2108 bool HasResourceDimension =
false;
2109 for (
const Attr *A : AttrList) {
2114 case attr::HLSLResourceClass: {
2116 if (HasResourceClass) {
2118 ? diag::warn_duplicate_attribute_exact
2119 : diag::warn_duplicate_attribute)
2123 ResAttrs.ResourceClass = RC;
2124 HasResourceClass =
true;
2127 case attr::HLSLResourceDimension: {
2128 llvm::dxil::ResourceDimension RD =
2130 if (HasResourceDimension) {
2132 ? diag::warn_duplicate_attribute_exact
2133 : diag::warn_duplicate_attribute)
2137 ResAttrs.ResourceDimension = RD;
2138 HasResourceDimension =
true;
2142 if (ResAttrs.IsROV) {
2146 ResAttrs.IsROV =
true;
2148 case attr::HLSLRawBuffer:
2149 if (ResAttrs.RawBuffer) {
2153 ResAttrs.RawBuffer =
true;
2155 case attr::HLSLIsCounter:
2156 if (ResAttrs.IsCounter) {
2160 ResAttrs.IsCounter =
true;
2162 case attr::HLSLContainedType: {
2165 if (!ContainedTy.
isNull()) {
2167 ? diag::warn_duplicate_attribute_exact
2168 : diag::warn_duplicate_attribute)
2177 llvm_unreachable(
"unhandled resource attribute type");
2181 if (!HasResourceClass) {
2182 S.
Diag(AttrList.back()->getRange().getEnd(),
2183 diag::err_hlsl_missing_resource_class);
2188 Wrapped, ContainedTy, ResAttrs);
2190 if (LocInfo && ContainedTyInfo) {
2203 if (!T->isHLSLResourceType()) {
2204 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2219 AttributeCommonInfo::AS_CXX11, 0, false ,
2224 case ParsedAttr::AT_HLSLResourceClass: {
2226 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2237 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2238 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2239 <<
"ResourceClass" << Identifier;
2242 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2246 case ParsedAttr::AT_HLSLResourceDimension: {
2247 StringRef Identifier;
2249 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2253 llvm::dxil::ResourceDimension RD;
2254 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2256 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2257 <<
"ResourceDimension" << Identifier;
2260 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2264 case ParsedAttr::AT_HLSLROV:
2268 case ParsedAttr::AT_HLSLRawBuffer:
2272 case ParsedAttr::AT_HLSLIsCounter:
2276 case ParsedAttr::AT_HLSLContainedType: {
2278 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2284 assert(TSI &&
"no type source info for attribute argument");
2286 diag::err_incomplete_type))
2288 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2293 llvm_unreachable(
"unhandled HLSL attribute");
2296 HLSLResourcesTypeAttrs.emplace_back(A);
2302 if (!HLSLResourcesTypeAttrs.size())
2308 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2309 const HLSLAttributedResourceType *RT =
2316 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2318 HLSLResourcesTypeAttrs.clear();
2326 auto I = LocsForHLSLAttributedResources.find(RT);
2327 if (I != LocsForHLSLAttributedResources.end()) {
2328 LocInfo = I->second;
2329 LocsForHLSLAttributedResources.erase(I);
2338void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2339 const RecordType *RT) {
2347 "incomplete arrays inside user defined types are not supported");
2356 if (
const HLSLAttributedResourceType *AttrResType =
2357 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2362 Bindings.addDeclBindingInfo(VD, RC);
2363 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2369 collectResourceBindingsOnUserRecordDecl(VD, RT);
2381 bool SpecifiedSpace) {
2382 int RegTypeNum =
static_cast<int>(RegType);
2385 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2386 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2391 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2392 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2393 : ResourceClass::SRV;
2403 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2407 if (
const HLSLAttributedResourceType *AttrResType =
2408 HLSLAttributedResourceType::findHandleTypeOnResource(
2425 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2426 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2431 if (RegType == RegisterType::CBuffer)
2432 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2433 else if (RegType != RegisterType::C)
2434 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2438 if (RegType == RegisterType::C)
2439 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2441 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2451 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2459 bool RegisterTypesDetected[5] = {
false};
2460 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2463 if (HLSLResourceBindingAttr *
attr =
2464 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2467 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2468 int otherRegTypeNum =
static_cast<int>(otherRegType);
2470 diag::err_hlsl_duplicate_register_annotation)
2474 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2482 bool SpecifiedSpace) {
2487 "expecting VarDecl or HLSLBufferDecl");
2499 const uint64_t &Limit,
2502 uint64_t ArrayCount = 1) {
2507 if (StartSlot > Limit)
2511 if (
const auto *AT = dyn_cast<ArrayType>(T)) {
2514 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2515 Count = CAT->
getSize().getZExtValue();
2519 ArrayCount * Count);
2523 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(T)) {
2526 if (ResTy->getAttrs().ResourceClass != ResClass)
2530 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2531 if (EndSlot > Limit)
2535 StartSlot = EndSlot + 1;
2540 if (
const auto *RT = dyn_cast<RecordType>(T)) {
2543 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2546 ResClass, Ctx, ArrayCount))
2553 ResClass, Ctx, ArrayCount))
2567 const uint64_t Limit = UINT32_MAX;
2568 if (SlotNum > Limit)
2573 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2576 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2577 uint64_t BaseSlot = SlotNum;
2585 return (BaseSlot > Limit);
2592 return (SlotNum > Limit);
2595 llvm_unreachable(
"unexpected decl type");
2599 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2601 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2602 Ty = IAT->getElementType();
2604 diag::err_incomplete_type))
2608 StringRef Slot =
"";
2609 StringRef Space =
"";
2613 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2623 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2629 SpaceLoc = Loc->
getLoc();
2632 if (Str.starts_with(
"space")) {
2634 SpaceLoc = Loc->
getLoc();
2643 std::optional<unsigned> SlotNum;
2644 unsigned SpaceNum = 0;
2647 if (!Slot.empty()) {
2649 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2652 if (RegType == RegisterType::I) {
2653 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2656 const StringRef SlotNumStr = Slot.substr(1);
2661 if (SlotNumStr.getAsInteger(10, N)) {
2662 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2670 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2679 if (!Space.starts_with(
"space")) {
2680 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2683 StringRef SpaceNumStr = Space.substr(5);
2684 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2685 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2690 if (SlotNum.has_value())
2695 HLSLResourceBindingAttr *NewAttr =
2696 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2698 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2724 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2726 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2730 Cur = AT->getModifiedType();
2741 ? attr::HLSLRowMajor
2742 : attr::HLSLColumnMajor;
2747 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2756 if (ExistingKind == AttrK) {
2757 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2759 Diag(AL.
getLoc(), diag::note_previous_attribute);
2763 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2764 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2766 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2771 if (AttrK == attr::HLSLRowMajor)
2772 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2773 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2784 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2786 if (T.isNull() || T->isDependentType())
2791 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2792 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2838 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2842 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2843 unsigned CurrentShaderStageBit;
2848 bool ReportOnlyShaderStageIssues;
2851 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2852 static_assert(
sizeof(
unsigned) >= 4);
2853 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2854 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2855 "ShaderType is too big for this bitmap");
2858 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2859 CurrentShaderEnvironment = ShaderType;
2860 CurrentShaderStageBit = (1 << bitmapIndex);
2863 void SetUnknownShaderStageContext() {
2864 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2865 CurrentShaderStageBit = (1 << 31);
2868 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2869 return CurrentShaderEnvironment;
2872 bool InUnknownShaderStageContext()
const {
2873 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2877 void AddToScannedFunctions(
const FunctionDecl *FD) {
2878 unsigned &ScannedStages = ScannedDecls[FD];
2879 ScannedStages |= CurrentShaderStageBit;
2882 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2884 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2885 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2888 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2889 return ScannerStages & CurrentShaderStageBit;
2892 static bool NeverBeenScanned(
unsigned ScannedStages) {
2893 return ScannedStages == 0;
2897 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2898 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2900 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2901 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2904 DiagnoseHLSLAvailability(Sema &SemaRef)
2906 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2907 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2910 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2911 void RunOnFunction(
const FunctionDecl *FD);
2913 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2914 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2916 HandleFunctionOrMethodRef(FD, DRE);
2920 bool VisitMemberExpr(MemberExpr *ME)
override {
2921 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2923 HandleFunctionOrMethodRef(FD, ME);
2928void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2931 "expected DeclRefExpr or MemberExpr");
2935 if (FD->
hasBody(FDWithBody)) {
2936 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2937 DeclsToScan.push_back(FDWithBody);
2942 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2944 CheckDeclAvailability(
2948void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2957 DeclContextsToScan.push_back(TU);
2959 while (!DeclContextsToScan.empty()) {
2960 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2961 for (
auto &D : DC->
decls()) {
2968 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2969 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2974 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2979 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2980 SetShaderStageContext(ShaderAttr->getType());
2989 for (
const auto *Redecl : FD->
redecls()) {
2990 if (Redecl->isInExportDeclContext()) {
2997 SetUnknownShaderStageContext();
3005void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3006 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3007 DeclsToScan.push_back(FD);
3009 while (!DeclsToScan.empty()) {
3017 const unsigned ScannedStages = GetScannedStages(FD);
3018 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3021 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3023 AddToScannedFunctions(FD);
3028bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3029 const AvailabilityAttr *AA) {
3034 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3035 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3038 llvm::Triple::EnvironmentType AttrEnv =
3039 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3041 return CurrentEnv == AttrEnv;
3044const AvailabilityAttr *
3045DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3046 AvailabilityAttr
const *PartialMatch =
nullptr;
3050 for (
const auto *A : D->
attrs()) {
3051 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3052 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3053 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3054 StringRef TargetPlatform =
3058 if (AttrPlatform == TargetPlatform) {
3060 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3062 PartialMatch = Avail;
3066 return PartialMatch;
3071void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3072 const AvailabilityAttr *AA,
3091 if (ReportOnlyShaderStageIssues)
3097 if (InUnknownShaderStageContext())
3102 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3103 VersionTuple Introduced = AA->getIntroduced();
3112 llvm::StringRef PlatformName(
3115 llvm::StringRef CurrentEnvStr =
3116 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3118 llvm::StringRef AttrEnvStr =
3119 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3120 bool UseEnvironment = !AttrEnvStr.empty();
3122 if (EnvironmentMatches) {
3123 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3124 <<
Range << D << PlatformName << Introduced.getAsString()
3125 << UseEnvironment << CurrentEnvStr;
3127 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3131 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3132 << D << PlatformName << Introduced.getAsString()
3134 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3141 if (!DefaultCBufferDecls.empty()) {
3144 DefaultCBufferDecls);
3147 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3151 for (
const Decl *VD : DefaultCBufferDecls) {
3152 const HLSLResourceBindingAttr *RBA =
3153 VD->
getAttr<HLSLResourceBindingAttr>();
3154 if (RBA && RBA->hasRegisterSlot() &&
3155 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3162 SemaRef.Consumer.HandleTopLevelDecl(DG);
3164 diagnoseAvailabilityViolations(TU);
3173 "expected member expr to have resource record type or array of them");
3179 const Expr *NonConstIndexExpr =
nullptr;
3182 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3183 if (!NonConstIndexExpr)
3191 diag::err_hlsl_resource_member_array_access_not_constant);
3195 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3196 const Expr *IdxExpr = ASE->getIdx();
3198 NonConstIndexExpr = IdxExpr;
3200 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3201 E = SubME->getBase();
3202 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3203 E = ICE->getSubExpr();
3205 llvm_unreachable(
"unexpected expr type in resource member access");
3214 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3217 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3220 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3224 [[maybe_unused]]
bool LookupSucceeded =
3225 SemaRef.LookupQualifiedName(ConvR, RD);
3226 assert(LookupSucceeded);
3235std::optional<ExprResult>
3238 const HLSLAttributedResourceType *ResTy =
3239 HLSLAttributedResourceType::findHandleTypeOnResource(
3240 BaseType.getTypePtr());
3242 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3243 return std::nullopt;
3245 QualType TemplateType = ResTy->getContainedType();
3249 assert(NamedConversionDecl &&
3250 "Could not find conversion function for ConstantBuffer.");
3251 auto *ConversionDecl =
3254 return SemaRef.BuildCXXMemberCallExpr(BaseExpr.
get(), NamedConversionDecl,
3266 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3269 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3276 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3279 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3304 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3319 if (!BaseType->isFloat32Type())
3320 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3321 << ArgOrdinal << 5 << 0
3331 BaseType = VT->getElementType();
3333 BaseType = MT->getElementType();
3335 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3336 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3337 << ArgOrdinal << 5 << 0
3351 if (!BaseType->isDoubleType()) {
3354 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3355 << ArgOrdinal << PassedType;
3362 unsigned ArgIndex) {
3363 auto *Arg = TheCall->
getArg(ArgIndex);
3365 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3368 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3382 << (ArgIndex + 1) << LValueTy;
3392 if (VecTy->getElementType()->isDoubleType())
3393 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3394 << ArgOrdinal << 1 << 0 << 1
3404 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3405 << ArgOrdinal << 5 << 1
3414 if (VecTy->getElementType()->isUnsignedIntegerType())
3417 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3418 << ArgOrdinal << 4 << 3 << 0
3427 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3428 << ArgOrdinal << 5 << 3
3434 unsigned ArgOrdinal,
unsigned Width) {
3437 ArgTy = VTy->getElementType();
3439 uint64_t ElementBitCount =
3441 if (ElementBitCount != Width) {
3443 diag::err_integer_incorrect_bit_count)
3444 << Width << ElementBitCount;
3461 unsigned ArgIndex) {
3470 diag::err_typecheck_expect_scalar_or_vector)
3471 << ArgType << Scalar;
3478 QualType Scalar,
unsigned ArgIndex) {
3489 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3502 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3503 << ArgType << Scalar;
3508 unsigned ArgIndex) {
3513 if (!(ArgType->isScalarType() ||
3514 (VTy && VTy->getElementType()->isScalarType()))) {
3516 diag::err_typecheck_expect_any_scalar_or_vector)
3526 unsigned ArgIndex) {
3528 assert(ArgIndex < TheCall->getNumArgs());
3536 diag::err_typecheck_expect_any_scalar_or_vector)
3561 diag::err_typecheck_call_different_arg_types)
3580 Arg1ScalarTy = VTy->getElementType();
3584 Arg2ScalarTy = VTy->getElementType();
3587 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3588 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3598 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3600 diag::err_typecheck_vector_lengths_not_equal)
3606 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3608 diag::err_typecheck_vector_lengths_not_equal)
3620 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3623 unsigned int ActualDim = 1;
3625 ActualDim = VTy->getNumElements();
3626 IndexTy = VTy->getElementType();
3630 diag::err_typecheck_expect_int)
3636 const HLSLAttributedResourceType *ResTy =
3638 assert(ResTy &&
"Resource argument must be a resource");
3639 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3641 unsigned int ExpectedDim = 1;
3642 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3645 if (ActualDim != ExpectedDim) {
3647 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3658 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3662 const HLSLAttributedResourceType *ResTy =
3666 diag::err_typecheck_expect_hlsl_resource)
3670 if (Check && Check(ResTy)) {
3672 diag::err_invalid_hlsl_resource_type)
3680 QualType BaseType,
unsigned ExpectedCount,
3682 unsigned PassedCount = 1;
3684 PassedCount = VecTy->getNumElements();
3686 if (PassedCount != ExpectedCount) {
3689 S->
Diag(Loc, diag::err_typecheck_convert_incompatible)
3701 [](
const HLSLAttributedResourceType *ResType) {
3702 return ResType->getAttrs().ResourceDimension ==
3703 llvm::dxil::ResourceDimension::Unknown;
3709 [](
const HLSLAttributedResourceType *ResType) {
3710 return ResType->getAttrs().ResourceClass !=
3711 llvm::hlsl::ResourceClass::Sampler;
3719 unsigned ExpectedDim =
3747 unsigned NextIdx = 3;
3753 diag::err_typecheck_convert_incompatible)
3761 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3765 diag::err_typecheck_convert_incompatible)
3772 std::optional<llvm::APSInt> ComponentOpt =
3775 int64_t ComponentVal = ComponentOpt->getSExtValue();
3776 if (ComponentVal != 0) {
3779 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3780 "The component is not in the expected range.");
3782 diag::err_hlsl_gathercmp_invalid_component)
3792 const HLSLAttributedResourceType *ResourceTy =
3795 unsigned ExpectedDim =
3804 assert(ResourceTy->hasContainedType() &&
3805 "Expecting a contained type for resource with a dimension "
3807 QualType ReturnType = ResourceTy->getContainedType();
3811 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3817 ReturnType = VecTy->getElementType();
3830 [](
const HLSLAttributedResourceType *ResType) {
3831 return ResType->getAttrs().ResourceDimension ==
3832 llvm::dxil::ResourceDimension::Unknown;
3840 unsigned ExpectedDim =
3849 EltTy = VTy->getElementType();
3864 TheCall->
setType(ResourceTy->getContainedType());
3869 unsigned MinArgs, MaxArgs;
3897 const HLSLAttributedResourceType *ResourceTy =
3899 unsigned ExpectedDim =
3902 unsigned NextIdx = 3;
3911 diag::err_typecheck_convert_incompatible)
3946 diag::err_typecheck_convert_incompatible)
3952 assert(ResourceTy->hasContainedType() &&
3953 "Expecting a contained type for resource with a dimension "
3955 QualType ReturnType = ResourceTy->getContainedType();
3958 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3971 switch (BuiltinID) {
3972 case Builtin::BI__builtin_hlsl_adduint64: {
3973 if (
SemaRef.checkArgCount(TheCall, 2))
3987 if (NumElementsArg != 2 && NumElementsArg != 4) {
3989 << 1 << 64 << NumElementsArg * 32;
4003 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4004 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4011 QualType ContainedTy = ResourceTy->getContainedType();
4012 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4015 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4020 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4021 if (
SemaRef.checkArgCount(TheCall, 3) ||
4028 "expected pointer type for second argument");
4035 diag::err_invalid_use_of_array_type);
4039 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4042 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4047 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4048 if (
SemaRef.checkArgCount(TheCall, 3) ||
4051 SemaRef.getASTContext().UnsignedIntTy) ||
4053 SemaRef.getASTContext().UnsignedIntTy) ||
4059 QualType ReturnType = ResourceTy->getContainedType();
4064 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4065 if (
SemaRef.checkArgCount(TheCall, 4) ||
4068 SemaRef.getASTContext().UnsignedIntTy) ||
4070 SemaRef.getASTContext().UnsignedIntTy) ||
4076 "expected pointer type for second argument");
4083 diag::err_invalid_use_of_array_type);
4089 case Builtin::BI__builtin_hlsl_resource_load_level:
4091 case Builtin::BI__builtin_hlsl_resource_sample:
4093 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4095 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4097 case Builtin::BI__builtin_hlsl_resource_sample_level:
4099 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4101 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4103 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4104 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4106 case Builtin::BI__builtin_hlsl_resource_gather:
4108 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4110 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4111 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4117 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4118 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4124 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4125 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4131 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4132 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4135 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4136 auto MainAttrs = MainResType->getAttrs();
4137 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4138 MainAttrs.IsCounter =
true;
4140 MainResType->getWrappedType(), MainResType->getContainedType(),
4144 TheCall->
setType(CounterHandleTy);
4147 case Builtin::BI__builtin_hlsl_and:
4148 case Builtin::BI__builtin_hlsl_or: {
4149 if (
SemaRef.checkArgCount(TheCall, 2))
4163 case Builtin::BI__builtin_hlsl_all:
4164 case Builtin::BI__builtin_hlsl_any: {
4165 if (
SemaRef.checkArgCount(TheCall, 1))
4171 case Builtin::BI__builtin_hlsl_asdouble: {
4172 if (
SemaRef.checkArgCount(TheCall, 2))
4176 SemaRef.Context.UnsignedIntTy,
4181 SemaRef.Context.UnsignedIntTy,
4190 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4191 if (
SemaRef.BuiltinElementwiseTernaryMath(
4197 case Builtin::BI__builtin_hlsl_dot: {
4199 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4205 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4206 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4207 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4217 EltTy = VecTy->getElementType();
4218 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4231 case Builtin::BI__builtin_hlsl_select: {
4232 if (
SemaRef.checkArgCount(TheCall, 3))
4240 if (VTy && VTy->getElementType()->isBooleanType() &&
4245 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4246 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4247 if (
SemaRef.checkArgCount(TheCall, 1))
4253 diag::err_builtin_invalid_arg_type)
4256 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4260 case Builtin::BI__builtin_hlsl_elementwise_degrees:
4261 case Builtin::BI__builtin_hlsl_elementwise_radians:
4262 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4263 case Builtin::BI__builtin_hlsl_elementwise_frac:
4264 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4265 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4266 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4267 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4268 if (
SemaRef.checkArgCount(TheCall, 1))
4273 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4277 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4278 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4279 if (
SemaRef.checkArgCount(TheCall, 1))
4284 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4289 case Builtin::BI__builtin_hlsl_lerp: {
4290 if (
SemaRef.checkArgCount(TheCall, 3))
4297 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
4301 case Builtin::BI__builtin_hlsl_mad: {
4302 if (
SemaRef.BuiltinElementwiseTernaryMath(
4308 case Builtin::BI__builtin_hlsl_mul: {
4309 if (
SemaRef.checkArgCount(TheCall, 2))
4318 if (
const auto *VTy = T->getAs<
VectorType>())
4319 return VTy->getElementType();
4321 return MTy->getElementType();
4325 QualType EltTy0 = getElemType(Ty0);
4334 if (IsVec0 && IsMat1) {
4337 }
else if (IsMat0 && IsVec1) {
4341 assert(IsMat0 && IsMat1);
4351 case Builtin::BI__builtin_hlsl_normalize: {
4352 if (
SemaRef.checkArgCount(TheCall, 1))
4363 case Builtin::BI__builtin_elementwise_fma: {
4364 if (
SemaRef.checkArgCount(TheCall, 3) ||
4379 case Builtin::BI__builtin_hlsl_transpose: {
4380 if (
SemaRef.checkArgCount(TheCall, 1))
4389 << 1 << 3 << 0 << 0 << ArgTy;
4394 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4398 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4399 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4407 case Builtin::BI__builtin_hlsl_step: {
4408 if (
SemaRef.checkArgCount(TheCall, 2))
4420 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4421 if (
SemaRef.checkArgCount(TheCall, 1))
4435 unsigned NumElts = VecTy->getNumElements();
4445 case Builtin::BI__builtin_hlsl_wave_active_max:
4446 case Builtin::BI__builtin_hlsl_wave_active_min:
4447 case Builtin::BI__builtin_hlsl_wave_active_sum:
4448 case Builtin::BI__builtin_hlsl_wave_active_product: {
4449 if (
SemaRef.checkArgCount(TheCall, 1))
4462 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4463 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4464 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4465 if (
SemaRef.checkArgCount(TheCall, 1))
4480 (VTy && VTy->getElementType()->isIntegerType()))) {
4482 diag::err_builtin_invalid_arg_type)
4483 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4491 case Builtin::BI__builtin_hlsl_interlocked_add: {
4501 diag::err_typecheck_call_too_few_args_at_least)
4506 if (
SemaRef.checkArgCountAtMost(TheCall, 3))
4512 diag::err_builtin_invalid_arg_type)
4540 case Builtin::BI__builtin_elementwise_bitreverse: {
4548 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4549 if (
SemaRef.checkArgCount(TheCall, 1))
4554 if (!(
ArgType->isScalarType())) {
4556 diag::err_typecheck_expect_any_scalar_or_vector)
4561 if (!(
ArgType->isBooleanType())) {
4563 diag::err_typecheck_expect_any_scalar_or_vector)
4570 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4571 if (
SemaRef.checkArgCount(TheCall, 2))
4579 diag::err_typecheck_convert_incompatible)
4580 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4593 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4594 if (
SemaRef.checkArgCount(TheCall, 0))
4598 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4599 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4600 if (
SemaRef.checkArgCount(TheCall, 1))
4613 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4614 case Builtin::BI__builtin_hlsl_quad_read_across_y: {
4615 if (
SemaRef.checkArgCount(TheCall, 1))
4627 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4628 if (
SemaRef.checkArgCount(TheCall, 3))
4634 SemaRef.Context.UnsignedIntTy, 1) ||
4636 SemaRef.Context.UnsignedIntTy, 2))
4644 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4645 if (
SemaRef.checkArgCount(TheCall, 1))
4652 case Builtin::BI__builtin_elementwise_acos:
4653 case Builtin::BI__builtin_elementwise_asin:
4654 case Builtin::BI__builtin_elementwise_atan:
4655 case Builtin::BI__builtin_elementwise_atan2:
4656 case Builtin::BI__builtin_elementwise_ceil:
4657 case Builtin::BI__builtin_elementwise_cos:
4658 case Builtin::BI__builtin_elementwise_cosh:
4659 case Builtin::BI__builtin_elementwise_exp:
4660 case Builtin::BI__builtin_elementwise_exp2:
4661 case Builtin::BI__builtin_elementwise_exp10:
4662 case Builtin::BI__builtin_elementwise_floor:
4663 case Builtin::BI__builtin_elementwise_fmod:
4664 case Builtin::BI__builtin_elementwise_log:
4665 case Builtin::BI__builtin_elementwise_log2:
4666 case Builtin::BI__builtin_elementwise_log10:
4667 case Builtin::BI__builtin_elementwise_pow:
4668 case Builtin::BI__builtin_elementwise_roundeven:
4669 case Builtin::BI__builtin_elementwise_sin:
4670 case Builtin::BI__builtin_elementwise_sinh:
4671 case Builtin::BI__builtin_elementwise_sqrt:
4672 case Builtin::BI__builtin_elementwise_tan:
4673 case Builtin::BI__builtin_elementwise_tanh:
4674 case Builtin::BI__builtin_elementwise_trunc: {
4680 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4681 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4682 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4683 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4684 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4689 std::optional<llvm::APSInt> Offset =
4691 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4693 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4699 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4700 if (
SemaRef.checkArgCount(TheCall, 1))
4711 ArgTy = VTy->getElementType();
4714 diag::err_builtin_invalid_arg_type)
4723 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4724 if (
SemaRef.checkArgCount(TheCall, 1))
4739 WorkList.push_back(BaseTy);
4740 while (!WorkList.empty()) {
4741 QualType T = WorkList.pop_back_val();
4742 T = T.getCanonicalType().getUnqualifiedType();
4743 if (
const auto *AT = dyn_cast<ConstantArrayType>(T)) {
4751 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4752 llvm::append_range(List, ElementFields);
4757 if (
const auto *VT = dyn_cast<VectorType>(T)) {
4758 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
4761 if (
const auto *MT = dyn_cast<ConstantMatrixType>(T)) {
4762 List.insert(List.end(), MT->getNumElementsFlattened(),
4763 MT->getElementType());
4766 if (
const auto *RD = T->getAsCXXRecordDecl()) {
4767 if (RD->isStandardLayout())
4768 RD = RD->getStandardLayoutBaseWithFields();
4772 if (RD->
isUnion() || !RD->isAggregate()) {
4778 for (
const auto *FD : RD->
fields())
4779 if (!FD->isUnnamedBitField())
4780 FieldTypes.push_back(FD->
getType());
4782 std::reverse(FieldTypes.begin(), FieldTypes.end());
4783 llvm::append_range(WorkList, FieldTypes);
4787 if (!RD->isStandardLayout()) {
4789 for (
const auto &
Base : RD->bases())
4790 FieldTypes.push_back(
Base.getType());
4791 std::reverse(FieldTypes.begin(), FieldTypes.end());
4792 llvm::append_range(WorkList, FieldTypes);
4827 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
4833 int ArraySize = VT->getNumElements();
4838 QualType ElTy = VT->getElementType();
4842 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
4858 if (
SemaRef.getASTContext().hasSameType(T1, T2))
4867 return llvm::equal(T1Types, T2Types,
4869 return SemaRef.IsLayoutCompatible(LHS, RHS);
4878 bool HadError =
false;
4880 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
4888 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
4889 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
4890 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
4891 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
4893 if (NSpellingIdx != OSpellingIdx) {
4895 diag::err_hlsl_param_qualifier_mismatch)
4896 << NDAttr << NewParam;
4912 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
4927 llvm_unreachable(
"HLSL doesn't support pointers.");
4930 llvm_unreachable(
"HLSL doesn't support complex types.");
4932 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4934 llvm_unreachable(
"Should have returned before this");
4944 llvm_unreachable(
"HLSL doesn't support complex types.");
4946 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4951 llvm_unreachable(
"HLSL doesn't support pointers.");
4953 llvm_unreachable(
"Should have returned before this");
4959 llvm_unreachable(
"HLSL doesn't support pointers.");
4962 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4966 llvm_unreachable(
"HLSL doesn't support complex types.");
4969 llvm_unreachable(
"Unhandled scalar cast");
4990 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
4996 SrcTy = SrcMatTy->getElementType();
5001 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5002 if (DestTypes[I]->isUnionType())
5034 if (SrcTypes.size() < DestTypes.size())
5037 unsigned SrcSize = SrcTypes.size();
5038 unsigned DstSize = DestTypes.size();
5040 for (I = 0; I < DstSize && I < SrcSize; I++) {
5041 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5049 for (; I < SrcSize; I++) {
5050 if (SrcTypes[I]->isUnionType())
5057 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5058 "We should not get here without a parameter modifier expression");
5059 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5066 << Arg << (IsInOut ? 1 : 0);
5072 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5079 << Arg << (IsInOut ? 1 : 0);
5091 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5097 auto *OpV =
new (Ctx)
5102 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
5103 tok::equal, ArgOpV, OpV);
5119 "Pointer and reference types cannot be inout or out parameters");
5120 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5136 for (
const auto *FD : RD->
fields()) {
5140 assert(RD->getNumBases() <= 1 &&
5141 "HLSL doesn't support multiple inheritance");
5142 return RD->getNumBases()
5147 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5148 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5160 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5165 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5171 if (
Decl->getType().hasAddressSpace())
5174 if (
Decl->getType()->isDependentType())
5186 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5200 llvm::Triple::Vulkan;
5201 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5202 if (HasDeclaredAPushConstant)
5208 HasDeclaredAPushConstant =
true;
5235class StructBindingContext {
5238 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5239 unsigned RegBindingOffset[4];
5242 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5243 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5244 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5245 static_cast<unsigned>(RegisterType::Sampler) == 3,
5246 "unexpected register type values");
5249 HLSLVkBindingAttr *VkBindingAttr;
5250 unsigned VkBindingOffset;
5255 StructBindingContext(
VarDecl *VD) {
5256 for (
unsigned i = 0; i < 4; ++i) {
5257 RegBindingsAttrs[i] =
nullptr;
5258 RegBindingOffset[i] = 0;
5260 VkBindingAttr =
nullptr;
5261 VkBindingOffset = 0;
5267 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5269 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5272 RegBindingsAttrs[RegTypeIdx] = RBA;
5277 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5278 VkBindingAttr = VBA;
5285 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5286 unsigned Range,
bool HasCounter) {
5287 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5289 if (VkBindingAttr) {
5290 unsigned Offset = VkBindingOffset;
5291 VkBindingOffset +=
Range;
5292 return HLSLVkBindingAttr::CreateImplicit(
5293 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5294 VkBindingAttr->getRange());
5297 HLSLResourceBindingAttr *RBA =
5298 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5299 HLSLResourceBindingAttr *NewAttr =
nullptr;
5301 if (RBA && RBA->hasRegisterSlot()) {
5304 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5305 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5307 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5308 StringRef NewSlotNumberStr =
5310 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5311 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5312 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5316 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5317 NewAttr->setBinding(RegType, std::nullopt,
5318 RBA ? RBA->getSpaceNumber() : 0);
5322 NewAttr->setImplicitCounterBindingOrderID(
5331static void createGlobalResourceDeclForStruct(
5333 QualType ResTy, StructBindingContext &BindingCtx) {
5335 "expected resource type or array of resources");
5346 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5347 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5352 const HLSLAttributedResourceType *ResHandleTy =
5353 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5357 Attr *BindingAttr = BindingCtx.createBindingAttr(
5359 ResDecl->
addAttr(BindingAttr);
5360 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5369 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5376static void handleArrayOfStructWithResources(
5378 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5383static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5385 EmbeddedResourceNameBuilder &NameBuilder,
5386 StructBindingContext &BindingCtx) {
5389 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5396 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5410 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5413 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5415 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5417 "resource arrays should have been already handled");
5418 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5427handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5429 EmbeddedResourceNameBuilder &NameBuilder,
5430 StructBindingContext &BindingCtx) {
5438 if (!SubCAT && !ElementRD)
5441 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5444 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5447 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5460void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5461 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5462 StructBindingContext BindingCtx(VD);
5466 "Expected non-resource struct or array type");
5469 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5473 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5474 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5482 if (
SemaRef.RequireCompleteType(
5485 diag::err_typecheck_decl_incomplete_type)) {
5499 DefaultCBufferDecls.push_back(VD);
5504 collectResourceBindingsOnVarDecl(VD);
5506 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5518 processExplicitBindingsOnDecl(VD);
5556 handleGlobalStructOrArrayOfWithResources(VD);
5560 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5569 "expected resource record type");
5585 const char *CreateMethodName;
5587 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5588 :
"__createFromBinding";
5590 CreateMethodName = HasCounter
5591 ?
"__createFromImplicitBindingWithImplicitCounter"
5592 :
"__createFromImplicitBinding";
5597 if (!CreateMethod) {
5602 "create method lookup should always succeed for built-in resource "
5611 Args.push_back(RegSlot);
5619 Args.push_back(OrderId);
5625 Args.push_back(Space);
5629 Args.push_back(RangeSize);
5633 Args.push_back(Index);
5635 StringRef VarName = VD->
getName();
5643 Args.push_back(NameCast);
5651 Args.push_back(CounterId);
5674 SemaRef.CheckCompleteVariableDeclaration(VD);
5680 "expected array of resource records");
5701 lookupMethod(
SemaRef, ResourceDecl,
5702 HasCounter ?
"__createFromBindingWithImplicitCounter"
5703 :
"__createFromBinding",
5707 CreateMethod = lookupMethod(
5709 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5710 :
"__createFromImplicitBinding",
5742std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5743 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5744 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5745 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5746 if (!TrueInfo || !FalseInfo)
5747 return std::nullopt;
5748 if (*TrueInfo != *FalseInfo)
5749 return std::nullopt;
5753 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5762 if (
const auto *AttrResType =
5763 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5765 return Bindings.getDeclBindingInfo(VD, RC);
5772void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
5773 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
5776 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5781 if (*ExprBinding ==
nullptr)
5784 auto PrevBinding = Assigns.find(VD);
5785 if (PrevBinding == Assigns.end()) {
5787 Assigns.insert({VD, *ExprBinding});
5792 if (*ExprBinding != PrevBinding->second) {
5794 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5796 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
5807 "expected LHS to be a resource record or array of resource records");
5808 if (Opc != BO_Assign)
5813 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5821 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
5826 trackLocalResource(VD, RHSExpr);
5834void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
5836 "expected global variable that contains HLSL resource");
5839 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
5840 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
5841 ? ResourceClass::CBuffer
5842 : ResourceClass::SRV);
5855 if (
const HLSLAttributedResourceType *AttrResType =
5856 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5857 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
5862 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
5863 collectResourceBindingsOnUserRecordDecl(VD, RT);
5869void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
5872 bool HasBinding =
false;
5873 for (Attr *A : VD->
attrs()) {
5876 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
5877 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
5880 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
5881 if (!RBA || !RBA->hasRegisterSlot())
5886 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
5887 "never have an attribute created");
5889 if (RT == RegisterType::C) {
5890 if (Bindings.hasBindingInfoForDecl(VD))
5892 diag::warn_hlsl_user_defined_type_missing_member)
5893 <<
static_cast<int>(RT);
5901 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
5906 diag::warn_hlsl_user_defined_type_missing_member)
5907 <<
static_cast<int>(RT);
5915class InitListTransformer {
5919 QualType *DstIt =
nullptr;
5920 Expr **ArgIt =
nullptr;
5926 bool castInitializer(Expr *E) {
5927 assert(DstIt &&
"This should always be something!");
5928 if (DstIt == DestTypes.end()) {
5930 ArgExprs.push_back(E);
5935 DstIt = DestTypes.begin();
5938 Ctx, *DstIt,
false);
5943 ArgExprs.push_back(
Init);
5948 bool buildInitializerListImpl(Expr *E) {
5950 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
5951 for (
auto *SubInit :
Init->inits())
5952 if (!buildInitializerListImpl(SubInit))
5962 return castInitializer(E);
5976 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
5981 for (uint64_t I = 0; I <
Size; ++I) {
5983 SizeTy, SourceLocation());
5989 if (!castInitializer(ElExpr.
get()))
5994 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
5995 unsigned Rows = MTy->getNumRows();
5996 unsigned Cols = MTy->getNumColumns();
5997 QualType ElemTy = MTy->getElementType();
5999 for (
unsigned R = 0;
R < Rows; ++
R) {
6000 for (
unsigned C = 0;
C < Cols; ++
C) {
6013 if (!castInitializer(ElExpr.
get()))
6021 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6025 for (uint64_t I = 0; I <
Size; ++I) {
6027 SizeTy, SourceLocation());
6032 if (!buildInitializerListImpl(ElExpr.
get()))
6039 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6040 RecordDecls.push_back(RD);
6041 while (RecordDecls.back()->getNumBases()) {
6042 CXXRecordDecl *D = RecordDecls.back();
6044 "HLSL doesn't support multiple inheritance");
6045 RecordDecls.push_back(
6048 while (!RecordDecls.empty()) {
6049 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6050 for (
auto *FD : RD->
fields()) {
6051 if (FD->isUnnamedBitField())
6059 if (!buildInitializerListImpl(Res.
get()))
6067 Expr *generateInitListsImpl(QualType Ty) {
6069 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6074 llvm::SmallVector<Expr *>
Inits;
6079 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6080 ElTy = ATy->getElementType();
6081 Size = ATy->getNumElements();
6082 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6083 ElTy = CMTy->getElementType();
6084 Size = CMTy->getNumElementsFlattened();
6087 ElTy = VTy->getElementType();
6088 Size = VTy->getZExtSize();
6090 for (uint64_t I = 0; I <
Size; ++I)
6091 Inits.push_back(generateInitListsImpl(ElTy));
6094 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6095 RecordDecls.push_back(RD);
6096 while (RecordDecls.back()->getNumBases()) {
6097 CXXRecordDecl *D = RecordDecls.back();
6099 "HLSL doesn't support multiple inheritance");
6100 RecordDecls.push_back(
6103 while (!RecordDecls.empty()) {
6104 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6105 for (
auto *FD : RD->
fields())
6106 if (!FD->isUnnamedBitField())
6111 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6112 Inits.back()->getEndLoc(),
false);
6113 NewInit->setType(Ty);
6118 llvm::SmallVector<QualType, 16> DestTypes;
6119 llvm::SmallVector<Expr *, 16> ArgExprs;
6120 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6121 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6122 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6123 InitTy = Entity.
getType().getNonReferenceType();
6133 DstIt = DestTypes.begin();
6136 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6138 Expr *generateInitLists() {
6139 assert(!ArgExprs.empty() &&
6140 "Call buildInitializerList to generate argument expressions.");
6141 ArgIt = ArgExprs.begin();
6143 return generateInitListsImpl(InitTy);
6144 llvm::SmallVector<Expr *>
Inits;
6145 while (ArgIt != ArgExprs.end())
6146 Inits.push_back(generateInitListsImpl(InitTy));
6149 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6150 Inits.back()->getEndLoc(),
false);
6151 llvm::APInt ArySize(64,
Inits.size());
6153 ArraySizeModifier::Normal, 0));
6165 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6172 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6176 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6196 if (
Init->getType()->isScalarType())
6199 InitListTransformer ILT(
SemaRef, Entity);
6201 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6209 Init->setInit(I, E);
6211 if (!ILT.buildInitializerList(E))
6214 size_t ExpectedSize = ILT.DestTypes.size();
6215 size_t ActualSize = ILT.ArgExprs.size();
6216 if (ExpectedSize == 0 && ActualSize == 0)
6223 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6225 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6226 << (int)(ExpectedSize < ActualSize) << InitTy
6227 << ExpectedSize << ActualSize;
6237 assert(ExpectedSize > 0 &&
6238 "The expected size of an incomplete array type must be at least 1.");
6240 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6248 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6249 if (ExpectedSize != ActualSize) {
6250 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6251 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6252 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6259 Init->resizeInits(Ctx, NewInit->getNumInits());
6260 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6261 Init->updateInit(Ctx, I, NewInit->getInit(I));
6269 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6279 StringRef AccessorName = CompName->
getName();
6280 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6282 unsigned Rows = MT->getNumRows();
6283 unsigned Cols = MT->getNumColumns();
6284 bool IsZeroBasedAccessor =
false;
6285 unsigned ChunkLen = 0;
6286 if (AccessorName.size() < 2)
6288 "length 4 for zero based: \'_mRC\' or "
6289 "length 3 for one-based: \'_RC\' accessor",
6292 if (AccessorName[0] ==
'_') {
6293 if (AccessorName[1] ==
'm') {
6294 IsZeroBasedAccessor =
true;
6301 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6304 if (AccessorName.size() % ChunkLen != 0) {
6305 const llvm::StringRef
Expected = IsZeroBasedAccessor
6306 ?
"zero based: '_mRC' accessor"
6307 :
"one-based: '_RC' accessor";
6312 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6313 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6314 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6316 bool HasRepeated =
false;
6318 unsigned NumComponents = 0;
6319 const char *Begin = AccessorName.data();
6321 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6322 const char *Chunk = Begin + I;
6323 char RowChar = 0, ColChar = 0;
6324 if (IsZeroBasedAccessor) {
6326 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6327 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6329 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6336 if (Chunk[0] !=
'_')
6338 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6345 bool IsDigitsError =
false;
6347 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6351 IsDigitsError =
true;
6355 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6359 IsDigitsError =
true;
6364 unsigned Row = RowChar -
'0';
6365 unsigned Col = ColChar -
'0';
6367 bool HasIndexingError =
false;
6368 if (IsZeroBasedAccessor) {
6370 if (!isZeroBasedIndex(Row)) {
6371 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6373 HasIndexingError =
true;
6375 if (!isZeroBasedIndex(Col)) {
6376 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6378 HasIndexingError =
true;
6382 if (!isOneBasedIndex(Row)) {
6383 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6385 HasIndexingError =
true;
6387 if (!isOneBasedIndex(Col)) {
6388 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6390 HasIndexingError =
true;
6397 if (HasIndexingError)
6403 bool HasBoundsError =
false;
6405 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6407 HasBoundsError =
true;
6410 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6412 HasBoundsError =
true;
6417 unsigned FlatIndex = Row * Cols + Col;
6418 if (Seen[FlatIndex])
6420 Seen[FlatIndex] =
true;
6423 if (NumComponents == 0 || NumComponents > 4) {
6424 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6429 QualType ElemTy = MT->getElementType();
6430 if (NumComponents == 1)
6436 for (Sema::ExtVectorDeclsType::iterator
6440 if ((*I)->getUnderlyingType() == VT)
6451 trackLocalResource(VDecl,
Init);
6453 const HLSLVkConstantIdAttr *ConstIdAttr =
6454 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6461 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
6471 int ConstantID = ConstIdAttr->getId();
6472 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6474 ConstIdAttr->getLocation());
6478 if (
C->getType()->getCanonicalTypeUnqualified() !=
6482 Context.getTrivialTypeSourceInfo(
6483 Init->getType(),
Init->getExprLoc()),
6502 if (!Params || Params->
size() != 1)
6515 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6516 if (TTP->hasDefaultArgument()) {
6517 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6520 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6521 if (NTTP->hasDefaultArgument()) {
6522 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6525 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6526 if (TTPD->hasDefaultArgument()) {
6527 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6534 return SemaRef.CheckTemplateIdType(
6536 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 isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool hasConstantBufferLayout(QualType QT)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
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 Builtin::ID getSpecConstBuiltinId(const Type *Type)
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 const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
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 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 CheckVectorElementCount(Sema *S, QualType PassedType, QualType BaseType, unsigned ExpectedCount, SourceLocation Loc)
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 bool isMatrixOrArrayOfMatrix(const ASTContext &Ctx, QualType QT)
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 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)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
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 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 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 CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall)
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
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.
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns) const
Return the unique reference to the matrix type of the specified element type and size.
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.
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
getQuantity - 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.
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.
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.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
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...
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 ...
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(Source *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 * 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 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)
std::optional< ExprResult > tryPerformConstantBufferConversion(ExprResult &BaseExpr)
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool ActOnResourceMemberAccessExpr(MemberExpr *ME)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
QualType ActOnTemplateShorthand(TemplateDecl *Template, SourceLocation NameLoc)
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, std::optional< unsigned > Index)
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)
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)
QualType getInoutParameterType(QualType Ty)
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
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)
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.
ExtVectorDeclsType ExtVectorDecls
ExtVectorDecls - This is a list all the extended vector types.
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.
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 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 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
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 hasCounterHandle(const CXXRecordDecl *RD)
The JSON file list parser is used to communicate input to InstallAPI.
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.
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)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
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.
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)
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
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