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::HLSLIsArray:
2156 if (ResAttrs.IsArray) {
2160 ResAttrs.IsArray =
true;
2162 case attr::HLSLIsCounter:
2163 if (ResAttrs.IsCounter) {
2167 ResAttrs.IsCounter =
true;
2169 case attr::HLSLContainedType: {
2172 if (!ContainedTy.
isNull()) {
2174 ? diag::warn_duplicate_attribute_exact
2175 : diag::warn_duplicate_attribute)
2184 llvm_unreachable(
"unhandled resource attribute type");
2188 if (!HasResourceClass) {
2189 S.
Diag(AttrList.back()->getRange().getEnd(),
2190 diag::err_hlsl_missing_resource_class);
2195 Wrapped, ContainedTy, ResAttrs);
2197 if (LocInfo && ContainedTyInfo) {
2210 if (!T->isHLSLResourceType()) {
2211 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2226 AttributeCommonInfo::AS_CXX11, 0, false ,
2231 case ParsedAttr::AT_HLSLResourceClass: {
2233 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2244 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2245 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2246 <<
"ResourceClass" << Identifier;
2249 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2253 case ParsedAttr::AT_HLSLResourceDimension: {
2254 StringRef Identifier;
2256 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2260 llvm::dxil::ResourceDimension RD;
2261 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2263 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2264 <<
"ResourceDimension" << Identifier;
2267 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2271 case ParsedAttr::AT_HLSLROV:
2275 case ParsedAttr::AT_HLSLRawBuffer:
2279 case ParsedAttr::AT_HLSLIsCounter:
2283 case ParsedAttr::AT_HLSLIsArray:
2287 case ParsedAttr::AT_HLSLContainedType: {
2289 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2295 assert(TSI &&
"no type source info for attribute argument");
2297 diag::err_incomplete_type))
2299 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2304 llvm_unreachable(
"unhandled HLSL attribute");
2307 HLSLResourcesTypeAttrs.emplace_back(A);
2313 if (!HLSLResourcesTypeAttrs.size())
2319 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2320 const HLSLAttributedResourceType *RT =
2327 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2329 HLSLResourcesTypeAttrs.clear();
2337 auto I = LocsForHLSLAttributedResources.find(RT);
2338 if (I != LocsForHLSLAttributedResources.end()) {
2339 LocInfo = I->second;
2340 LocsForHLSLAttributedResources.erase(I);
2349void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2350 const RecordType *RT) {
2358 "incomplete arrays inside user defined types are not supported");
2367 if (
const HLSLAttributedResourceType *AttrResType =
2368 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2373 Bindings.addDeclBindingInfo(VD, RC);
2374 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2380 collectResourceBindingsOnUserRecordDecl(VD, RT);
2392 bool SpecifiedSpace) {
2393 int RegTypeNum =
static_cast<int>(RegType);
2396 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2397 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2402 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2403 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2404 : ResourceClass::SRV;
2414 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2418 if (
const HLSLAttributedResourceType *AttrResType =
2419 HLSLAttributedResourceType::findHandleTypeOnResource(
2436 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2437 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2442 if (RegType == RegisterType::CBuffer)
2443 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2444 else if (RegType != RegisterType::C)
2445 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2449 if (RegType == RegisterType::C)
2450 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2452 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2462 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2470 bool RegisterTypesDetected[5] = {
false};
2471 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2474 if (HLSLResourceBindingAttr *
attr =
2475 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2478 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2479 int otherRegTypeNum =
static_cast<int>(otherRegType);
2481 diag::err_hlsl_duplicate_register_annotation)
2485 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2493 bool SpecifiedSpace) {
2498 "expecting VarDecl or HLSLBufferDecl");
2510 const uint64_t &Limit,
2513 uint64_t ArrayCount = 1) {
2518 if (StartSlot > Limit)
2522 if (
const auto *AT = dyn_cast<ArrayType>(T)) {
2525 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2526 Count = CAT->
getSize().getZExtValue();
2530 ArrayCount * Count);
2534 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(T)) {
2537 if (ResTy->getAttrs().ResourceClass != ResClass)
2541 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2542 if (EndSlot > Limit)
2546 StartSlot = EndSlot + 1;
2551 if (
const auto *RT = dyn_cast<RecordType>(T)) {
2554 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2557 ResClass, Ctx, ArrayCount))
2564 ResClass, Ctx, ArrayCount))
2578 const uint64_t Limit = UINT32_MAX;
2579 if (SlotNum > Limit)
2584 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2587 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2588 uint64_t BaseSlot = SlotNum;
2596 return (BaseSlot > Limit);
2603 return (SlotNum > Limit);
2606 llvm_unreachable(
"unexpected decl type");
2610 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2612 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2613 Ty = IAT->getElementType();
2615 diag::err_incomplete_type))
2619 StringRef Slot =
"";
2620 StringRef Space =
"";
2624 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2634 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2640 SpaceLoc = Loc->
getLoc();
2643 if (Str.starts_with(
"space")) {
2645 SpaceLoc = Loc->
getLoc();
2654 std::optional<unsigned> SlotNum;
2655 unsigned SpaceNum = 0;
2658 if (!Slot.empty()) {
2660 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2663 if (RegType == RegisterType::I) {
2664 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2667 const StringRef SlotNumStr = Slot.substr(1);
2672 if (SlotNumStr.getAsInteger(10, N)) {
2673 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2681 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2690 if (!Space.starts_with(
"space")) {
2691 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2694 StringRef SpaceNumStr = Space.substr(5);
2695 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2696 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2701 if (SlotNum.has_value())
2706 HLSLResourceBindingAttr *NewAttr =
2707 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2709 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2735 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2737 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2741 Cur = AT->getModifiedType();
2752 ? attr::HLSLRowMajor
2753 : attr::HLSLColumnMajor;
2758 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2767 if (ExistingKind == AttrK) {
2768 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2770 Diag(AL.
getLoc(), diag::note_previous_attribute);
2774 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2775 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2777 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2782 if (AttrK == attr::HLSLRowMajor)
2783 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2784 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2795 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2797 if (T.isNull() || T->isDependentType())
2802 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2803 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2810 switch (BuiltinID) {
2811 case Builtin::BI__builtin_hlsl_mul:
2812 case Builtin::BI__builtin_hlsl_transpose:
2820 if (!E || DestType.
isNull())
2832 if (!CallMat || CallMat->getNumRows() != DestMat->getNumRows() ||
2833 CallMat->getNumColumns() != DestMat->getNumColumns())
2882 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2886 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2887 unsigned CurrentShaderStageBit;
2892 bool ReportOnlyShaderStageIssues;
2895 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2896 static_assert(
sizeof(
unsigned) >= 4);
2897 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2898 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2899 "ShaderType is too big for this bitmap");
2902 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2903 CurrentShaderEnvironment = ShaderType;
2904 CurrentShaderStageBit = (1 << bitmapIndex);
2907 void SetUnknownShaderStageContext() {
2908 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2909 CurrentShaderStageBit = (1 << 31);
2912 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2913 return CurrentShaderEnvironment;
2916 bool InUnknownShaderStageContext()
const {
2917 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2921 void AddToScannedFunctions(
const FunctionDecl *FD) {
2922 unsigned &ScannedStages = ScannedDecls[FD];
2923 ScannedStages |= CurrentShaderStageBit;
2926 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2928 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2929 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2932 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2933 return ScannerStages & CurrentShaderStageBit;
2936 static bool NeverBeenScanned(
unsigned ScannedStages) {
2937 return ScannedStages == 0;
2941 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2942 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2944 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2945 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2948 DiagnoseHLSLAvailability(Sema &SemaRef)
2950 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2951 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2954 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2955 void RunOnFunction(
const FunctionDecl *FD);
2957 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2958 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2960 HandleFunctionOrMethodRef(FD, DRE);
2964 bool VisitMemberExpr(MemberExpr *ME)
override {
2965 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2967 HandleFunctionOrMethodRef(FD, ME);
2972void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2975 "expected DeclRefExpr or MemberExpr");
2979 if (FD->
hasBody(FDWithBody)) {
2980 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2981 DeclsToScan.push_back(FDWithBody);
2986 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2988 CheckDeclAvailability(
2992void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3001 DeclContextsToScan.push_back(TU);
3003 while (!DeclContextsToScan.empty()) {
3004 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3005 for (
auto &D : DC->
decls()) {
3012 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3013 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3018 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3023 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3024 SetShaderStageContext(ShaderAttr->getType());
3033 for (
const auto *Redecl : FD->
redecls()) {
3034 if (Redecl->isInExportDeclContext()) {
3041 SetUnknownShaderStageContext();
3049void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3050 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3051 DeclsToScan.push_back(FD);
3053 while (!DeclsToScan.empty()) {
3061 const unsigned ScannedStages = GetScannedStages(FD);
3062 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3065 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3067 AddToScannedFunctions(FD);
3072bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3073 const AvailabilityAttr *AA) {
3078 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3079 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3082 llvm::Triple::EnvironmentType AttrEnv =
3083 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3085 return CurrentEnv == AttrEnv;
3088const AvailabilityAttr *
3089DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3090 AvailabilityAttr
const *PartialMatch =
nullptr;
3094 for (
const auto *A : D->
attrs()) {
3095 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3096 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3097 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3098 StringRef TargetPlatform =
3102 if (AttrPlatform == TargetPlatform) {
3104 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3106 PartialMatch = Avail;
3110 return PartialMatch;
3115void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3116 const AvailabilityAttr *AA,
3135 if (ReportOnlyShaderStageIssues)
3141 if (InUnknownShaderStageContext())
3146 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3147 VersionTuple Introduced = AA->getIntroduced();
3156 llvm::StringRef PlatformName(
3159 llvm::StringRef CurrentEnvStr =
3160 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3162 llvm::StringRef AttrEnvStr =
3163 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3164 bool UseEnvironment = !AttrEnvStr.empty();
3166 if (EnvironmentMatches) {
3167 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3168 <<
Range << D << PlatformName << Introduced.getAsString()
3169 << UseEnvironment << CurrentEnvStr;
3171 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3175 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3176 << D << PlatformName << Introduced.getAsString()
3178 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3185 if (!DefaultCBufferDecls.empty()) {
3188 DefaultCBufferDecls);
3191 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3195 for (
const Decl *VD : DefaultCBufferDecls) {
3196 const HLSLResourceBindingAttr *RBA =
3197 VD->
getAttr<HLSLResourceBindingAttr>();
3198 if (RBA && RBA->hasRegisterSlot() &&
3199 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3206 SemaRef.Consumer.HandleTopLevelDecl(DG);
3208 diagnoseAvailabilityViolations(TU);
3217 "expected member expr to have resource record type or array of them");
3223 const Expr *NonConstIndexExpr =
nullptr;
3226 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3227 if (!NonConstIndexExpr)
3235 diag::err_hlsl_resource_member_array_access_not_constant);
3239 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3240 const Expr *IdxExpr = ASE->getIdx();
3242 NonConstIndexExpr = IdxExpr;
3244 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3245 E = SubME->getBase();
3246 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3247 E = ICE->getSubExpr();
3249 llvm_unreachable(
"unexpected expr type in resource member access");
3258 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3261 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3264 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3268 [[maybe_unused]]
bool LookupSucceeded =
3269 SemaRef.LookupQualifiedName(ConvR, RD);
3270 assert(LookupSucceeded);
3279std::optional<ExprResult>
3282 const HLSLAttributedResourceType *ResTy =
3283 HLSLAttributedResourceType::findHandleTypeOnResource(
3284 BaseType.getTypePtr());
3286 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3287 return std::nullopt;
3289 QualType TemplateType = ResTy->getContainedType();
3293 assert(NamedConversionDecl &&
3294 "Could not find conversion function for ConstantBuffer.");
3295 auto *ConversionDecl =
3298 return SemaRef.BuildCXXMemberCallExpr(BaseExpr.
get(), NamedConversionDecl,
3310 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3313 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3320 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3323 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3348 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3363 if (!BaseType->isFloat32Type())
3364 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3365 << ArgOrdinal << 5 << 0
3375 BaseType = VT->getElementType();
3377 BaseType = MT->getElementType();
3379 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3380 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3381 << ArgOrdinal << 5 << 0
3395 if (!BaseType->isDoubleType()) {
3398 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3399 << ArgOrdinal << PassedType;
3406 unsigned ArgIndex) {
3407 auto *Arg = TheCall->
getArg(ArgIndex);
3409 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3412 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3426 << (ArgIndex + 1) << LValueTy;
3436 if (VecTy->getElementType()->isDoubleType())
3437 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3438 << ArgOrdinal << 1 << 0 << 1
3448 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3449 << ArgOrdinal << 5 << 1
3458 if (VecTy->getElementType()->isUnsignedIntegerType())
3461 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3462 << ArgOrdinal << 4 << 3 << 0
3471 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3472 << ArgOrdinal << 5 << 3
3478 unsigned ArgOrdinal,
unsigned Width) {
3481 ArgTy = VTy->getElementType();
3483 uint64_t ElementBitCount =
3485 if (ElementBitCount != Width) {
3487 diag::err_integer_incorrect_bit_count)
3488 << Width << ElementBitCount;
3505 unsigned ArgIndex) {
3514 diag::err_typecheck_expect_scalar_or_vector)
3515 << ArgType << Scalar;
3522 QualType Scalar,
unsigned ArgIndex) {
3533 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3546 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3547 << ArgType << Scalar;
3552 unsigned ArgIndex) {
3557 if (!(ArgType->isScalarType() ||
3558 (VTy && VTy->getElementType()->isScalarType()))) {
3560 diag::err_typecheck_expect_any_scalar_or_vector)
3570 unsigned ArgIndex) {
3572 assert(ArgIndex < TheCall->getNumArgs());
3580 diag::err_typecheck_expect_any_scalar_or_vector)
3605 diag::err_typecheck_call_different_arg_types)
3624 Arg1ScalarTy = VTy->getElementType();
3628 Arg2ScalarTy = VTy->getElementType();
3631 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3632 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3642 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3644 diag::err_typecheck_vector_lengths_not_equal)
3650 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3652 diag::err_typecheck_vector_lengths_not_equal)
3664 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3667 unsigned int ActualDim = 1;
3669 ActualDim = VTy->getNumElements();
3670 IndexTy = VTy->getElementType();
3674 diag::err_typecheck_expect_int)
3680 const HLSLAttributedResourceType *ResTy =
3682 assert(ResTy &&
"Resource argument must be a resource");
3683 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3685 unsigned int ExpectedDim = 1;
3686 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3689 if (ActualDim != ExpectedDim) {
3691 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3702 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3706 const HLSLAttributedResourceType *ResTy =
3710 diag::err_typecheck_expect_hlsl_resource)
3714 if (Check && Check(ResTy)) {
3716 diag::err_invalid_hlsl_resource_type)
3724 QualType BaseType,
unsigned ExpectedCount,
3726 unsigned PassedCount = 1;
3728 PassedCount = VecTy->getNumElements();
3730 if (PassedCount != ExpectedCount) {
3733 S->
Diag(Loc, diag::err_typecheck_convert_incompatible)
3745 [](
const HLSLAttributedResourceType *ResType) {
3746 return ResType->getAttrs().ResourceDimension ==
3747 llvm::dxil::ResourceDimension::Unknown;
3753 [](
const HLSLAttributedResourceType *ResType) {
3754 return ResType->getAttrs().ResourceClass !=
3755 llvm::hlsl::ResourceClass::Sampler;
3763 unsigned ExpectedDim =
3791 unsigned NextIdx = 3;
3797 diag::err_typecheck_convert_incompatible)
3805 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3809 diag::err_typecheck_convert_incompatible)
3816 std::optional<llvm::APSInt> ComponentOpt =
3819 int64_t ComponentVal = ComponentOpt->getSExtValue();
3820 if (ComponentVal != 0) {
3823 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3824 "The component is not in the expected range.");
3826 diag::err_hlsl_gathercmp_invalid_component)
3836 const HLSLAttributedResourceType *ResourceTy =
3839 unsigned ExpectedDim =
3848 assert(ResourceTy->hasContainedType() &&
3849 "Expecting a contained type for resource with a dimension "
3851 QualType ReturnType = ResourceTy->getContainedType();
3855 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3861 ReturnType = VecTy->getElementType();
3874 [](
const HLSLAttributedResourceType *ResType) {
3875 return ResType->getAttrs().ResourceDimension ==
3876 llvm::dxil::ResourceDimension::Unknown;
3884 unsigned ExpectedDim =
3893 EltTy = VTy->getElementType();
3908 TheCall->
setType(ResourceTy->getContainedType());
3913 unsigned MinArgs, MaxArgs;
3941 const HLSLAttributedResourceType *ResourceTy =
3943 unsigned ExpectedDim =
3946 unsigned NextIdx = 3;
3955 diag::err_typecheck_convert_incompatible)
3990 diag::err_typecheck_convert_incompatible)
3996 assert(ResourceTy->hasContainedType() &&
3997 "Expecting a contained type for resource with a dimension "
3999 QualType ReturnType = ResourceTy->getContainedType();
4002 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4015 switch (BuiltinID) {
4016 case Builtin::BI__builtin_hlsl_adduint64: {
4017 if (
SemaRef.checkArgCount(TheCall, 2))
4031 if (NumElementsArg != 2 && NumElementsArg != 4) {
4033 << 1 << 64 << NumElementsArg * 32;
4047 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4048 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4055 QualType ContainedTy = ResourceTy->getContainedType();
4056 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4059 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4064 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4065 if (
SemaRef.checkArgCount(TheCall, 3) ||
4072 "expected pointer type for second argument");
4079 diag::err_invalid_use_of_array_type);
4083 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4086 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4091 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4092 if (
SemaRef.checkArgCount(TheCall, 3) ||
4095 SemaRef.getASTContext().UnsignedIntTy) ||
4097 SemaRef.getASTContext().UnsignedIntTy) ||
4103 QualType ReturnType = ResourceTy->getContainedType();
4108 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4109 if (
SemaRef.checkArgCount(TheCall, 4) ||
4112 SemaRef.getASTContext().UnsignedIntTy) ||
4114 SemaRef.getASTContext().UnsignedIntTy) ||
4120 "expected pointer type for second argument");
4127 diag::err_invalid_use_of_array_type);
4133 case Builtin::BI__builtin_hlsl_resource_load_level:
4135 case Builtin::BI__builtin_hlsl_resource_sample:
4137 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4139 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4141 case Builtin::BI__builtin_hlsl_resource_sample_level:
4143 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4145 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4147 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4148 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4150 case Builtin::BI__builtin_hlsl_resource_gather:
4152 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4154 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4155 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4161 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4162 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4168 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4169 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4175 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4176 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4179 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4180 auto MainAttrs = MainResType->getAttrs();
4181 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4182 MainAttrs.IsCounter =
true;
4184 MainResType->getWrappedType(), MainResType->getContainedType(),
4188 TheCall->
setType(CounterHandleTy);
4191 case Builtin::BI__builtin_hlsl_and:
4192 case Builtin::BI__builtin_hlsl_or: {
4193 if (
SemaRef.checkArgCount(TheCall, 2))
4207 case Builtin::BI__builtin_hlsl_all:
4208 case Builtin::BI__builtin_hlsl_any: {
4209 if (
SemaRef.checkArgCount(TheCall, 1))
4215 case Builtin::BI__builtin_hlsl_asdouble: {
4216 if (
SemaRef.checkArgCount(TheCall, 2))
4220 SemaRef.Context.UnsignedIntTy,
4225 SemaRef.Context.UnsignedIntTy,
4234 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4235 if (
SemaRef.BuiltinElementwiseTernaryMath(
4241 case Builtin::BI__builtin_hlsl_dot: {
4243 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4249 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4250 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4251 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4261 EltTy = VecTy->getElementType();
4262 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4275 case Builtin::BI__builtin_hlsl_select: {
4276 if (
SemaRef.checkArgCount(TheCall, 3))
4284 if (VTy && VTy->getElementType()->isBooleanType() &&
4289 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4290 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4291 if (
SemaRef.checkArgCount(TheCall, 1))
4297 diag::err_builtin_invalid_arg_type)
4300 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4304 case Builtin::BI__builtin_hlsl_elementwise_degrees:
4305 case Builtin::BI__builtin_hlsl_elementwise_radians:
4306 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4307 case Builtin::BI__builtin_hlsl_elementwise_frac:
4308 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4309 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4310 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4311 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4312 if (
SemaRef.checkArgCount(TheCall, 1))
4317 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4321 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4322 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4323 if (
SemaRef.checkArgCount(TheCall, 1))
4328 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4333 case Builtin::BI__builtin_hlsl_lerp: {
4334 if (
SemaRef.checkArgCount(TheCall, 3))
4341 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
4345 case Builtin::BI__builtin_hlsl_mad: {
4346 if (
SemaRef.BuiltinElementwiseTernaryMath(
4352 case Builtin::BI__builtin_hlsl_mul: {
4353 if (
SemaRef.checkArgCount(TheCall, 2))
4362 if (
const auto *VTy = T->getAs<
VectorType>())
4363 return VTy->getElementType();
4365 return MTy->getElementType();
4369 QualType EltTy0 = getElemType(Ty0);
4378 if (IsVec0 && IsMat1) {
4381 }
else if (IsMat0 && IsVec1) {
4385 assert(IsMat0 && IsMat1);
4395 case Builtin::BI__builtin_hlsl_normalize: {
4396 if (
SemaRef.checkArgCount(TheCall, 1))
4407 case Builtin::BI__builtin_elementwise_fma: {
4408 if (
SemaRef.checkArgCount(TheCall, 3) ||
4423 case Builtin::BI__builtin_hlsl_transpose: {
4424 if (
SemaRef.checkArgCount(TheCall, 1))
4433 << 1 << 3 << 0 << 0 << ArgTy;
4438 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4442 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4443 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4451 case Builtin::BI__builtin_hlsl_step: {
4452 if (
SemaRef.checkArgCount(TheCall, 2))
4464 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4465 if (
SemaRef.checkArgCount(TheCall, 1))
4479 unsigned NumElts = VecTy->getNumElements();
4489 case Builtin::BI__builtin_hlsl_wave_active_max:
4490 case Builtin::BI__builtin_hlsl_wave_active_min:
4491 case Builtin::BI__builtin_hlsl_wave_active_sum:
4492 case Builtin::BI__builtin_hlsl_wave_active_product: {
4493 if (
SemaRef.checkArgCount(TheCall, 1))
4506 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4507 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4508 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4509 if (
SemaRef.checkArgCount(TheCall, 1))
4524 (VTy && VTy->getElementType()->isIntegerType()))) {
4526 diag::err_builtin_invalid_arg_type)
4527 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4535 case Builtin::BI__builtin_hlsl_interlocked_add: {
4545 diag::err_typecheck_call_too_few_args_at_least)
4550 if (
SemaRef.checkArgCountAtMost(TheCall, 3))
4556 diag::err_builtin_invalid_arg_type)
4584 case Builtin::BI__builtin_elementwise_bitreverse: {
4592 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4593 if (
SemaRef.checkArgCount(TheCall, 1))
4598 if (!(
ArgType->isScalarType())) {
4600 diag::err_typecheck_expect_any_scalar_or_vector)
4605 if (!(
ArgType->isBooleanType())) {
4607 diag::err_typecheck_expect_any_scalar_or_vector)
4614 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4615 if (
SemaRef.checkArgCount(TheCall, 2))
4623 diag::err_typecheck_convert_incompatible)
4624 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4637 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4638 if (
SemaRef.checkArgCount(TheCall, 0))
4642 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4643 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4644 if (
SemaRef.checkArgCount(TheCall, 1))
4657 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4658 case Builtin::BI__builtin_hlsl_quad_read_across_y:
4659 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
4660 if (
SemaRef.checkArgCount(TheCall, 1))
4672 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4673 if (
SemaRef.checkArgCount(TheCall, 3))
4679 SemaRef.Context.UnsignedIntTy, 1) ||
4681 SemaRef.Context.UnsignedIntTy, 2))
4689 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4690 if (
SemaRef.checkArgCount(TheCall, 1))
4697 case Builtin::BI__builtin_elementwise_acos:
4698 case Builtin::BI__builtin_elementwise_asin:
4699 case Builtin::BI__builtin_elementwise_atan:
4700 case Builtin::BI__builtin_elementwise_atan2:
4701 case Builtin::BI__builtin_elementwise_ceil:
4702 case Builtin::BI__builtin_elementwise_cos:
4703 case Builtin::BI__builtin_elementwise_cosh:
4704 case Builtin::BI__builtin_elementwise_exp:
4705 case Builtin::BI__builtin_elementwise_exp2:
4706 case Builtin::BI__builtin_elementwise_exp10:
4707 case Builtin::BI__builtin_elementwise_floor:
4708 case Builtin::BI__builtin_elementwise_fmod:
4709 case Builtin::BI__builtin_elementwise_log:
4710 case Builtin::BI__builtin_elementwise_log2:
4711 case Builtin::BI__builtin_elementwise_log10:
4712 case Builtin::BI__builtin_elementwise_pow:
4713 case Builtin::BI__builtin_elementwise_roundeven:
4714 case Builtin::BI__builtin_elementwise_sin:
4715 case Builtin::BI__builtin_elementwise_sinh:
4716 case Builtin::BI__builtin_elementwise_sqrt:
4717 case Builtin::BI__builtin_elementwise_tan:
4718 case Builtin::BI__builtin_elementwise_tanh:
4719 case Builtin::BI__builtin_elementwise_trunc: {
4725 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4726 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4727 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4728 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4729 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4734 std::optional<llvm::APSInt> Offset =
4736 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4738 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4744 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4745 if (
SemaRef.checkArgCount(TheCall, 1))
4756 ArgTy = VTy->getElementType();
4759 diag::err_builtin_invalid_arg_type)
4768 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4769 if (
SemaRef.checkArgCount(TheCall, 1))
4784 WorkList.push_back(BaseTy);
4785 while (!WorkList.empty()) {
4786 QualType T = WorkList.pop_back_val();
4787 T = T.getCanonicalType().getUnqualifiedType();
4788 if (
const auto *AT = dyn_cast<ConstantArrayType>(T)) {
4796 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4797 llvm::append_range(List, ElementFields);
4802 if (
const auto *VT = dyn_cast<VectorType>(T)) {
4803 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
4806 if (
const auto *MT = dyn_cast<ConstantMatrixType>(T)) {
4807 List.insert(List.end(), MT->getNumElementsFlattened(),
4808 MT->getElementType());
4811 if (
const auto *RD = T->getAsCXXRecordDecl()) {
4812 if (RD->isStandardLayout())
4813 RD = RD->getStandardLayoutBaseWithFields();
4817 if (RD->
isUnion() || !RD->isAggregate()) {
4823 for (
const auto *FD : RD->
fields())
4824 if (!FD->isUnnamedBitField())
4825 FieldTypes.push_back(FD->
getType());
4827 std::reverse(FieldTypes.begin(), FieldTypes.end());
4828 llvm::append_range(WorkList, FieldTypes);
4832 if (!RD->isStandardLayout()) {
4834 for (
const auto &
Base : RD->bases())
4835 FieldTypes.push_back(
Base.getType());
4836 std::reverse(FieldTypes.begin(), FieldTypes.end());
4837 llvm::append_range(WorkList, FieldTypes);
4872 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
4878 int ArraySize = VT->getNumElements();
4883 QualType ElTy = VT->getElementType();
4887 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
4903 if (
SemaRef.getASTContext().hasSameType(T1, T2))
4912 return llvm::equal(T1Types, T2Types,
4914 return SemaRef.IsLayoutCompatible(LHS, RHS);
4923 bool HadError =
false;
4925 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
4933 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
4934 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
4935 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
4936 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
4938 if (NSpellingIdx != OSpellingIdx) {
4940 diag::err_hlsl_param_qualifier_mismatch)
4941 << NDAttr << NewParam;
4957 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
4972 llvm_unreachable(
"HLSL doesn't support pointers.");
4975 llvm_unreachable(
"HLSL doesn't support complex types.");
4977 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4979 llvm_unreachable(
"Should have returned before this");
4989 llvm_unreachable(
"HLSL doesn't support complex types.");
4991 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4996 llvm_unreachable(
"HLSL doesn't support pointers.");
4998 llvm_unreachable(
"Should have returned before this");
5004 llvm_unreachable(
"HLSL doesn't support pointers.");
5007 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5011 llvm_unreachable(
"HLSL doesn't support complex types.");
5014 llvm_unreachable(
"Unhandled scalar cast");
5035 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5041 SrcTy = SrcMatTy->getElementType();
5046 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5047 if (DestTypes[I]->isUnionType())
5079 if (SrcTypes.size() < DestTypes.size())
5082 unsigned SrcSize = SrcTypes.size();
5083 unsigned DstSize = DestTypes.size();
5085 for (I = 0; I < DstSize && I < SrcSize; I++) {
5086 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5094 for (; I < SrcSize; I++) {
5095 if (SrcTypes[I]->isUnionType())
5102 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5103 "We should not get here without a parameter modifier expression");
5104 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5111 << Arg << (IsInOut ? 1 : 0);
5117 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5124 << Arg << (IsInOut ? 1 : 0);
5136 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5142 auto *OpV =
new (Ctx)
5147 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
5148 tok::equal, ArgOpV, OpV);
5164 "Pointer and reference types cannot be inout or out parameters");
5165 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5181 for (
const auto *FD : RD->
fields()) {
5185 assert(RD->getNumBases() <= 1 &&
5186 "HLSL doesn't support multiple inheritance");
5187 return RD->getNumBases()
5192 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5193 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5205 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5210 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5216 if (
Decl->getType().hasAddressSpace())
5219 if (
Decl->getType()->isDependentType())
5231 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5245 llvm::Triple::Vulkan;
5246 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5247 if (HasDeclaredAPushConstant)
5253 HasDeclaredAPushConstant =
true;
5280class StructBindingContext {
5283 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5284 unsigned RegBindingOffset[4];
5287 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5288 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5289 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5290 static_cast<unsigned>(RegisterType::Sampler) == 3,
5291 "unexpected register type values");
5294 HLSLVkBindingAttr *VkBindingAttr;
5295 unsigned VkBindingOffset;
5300 StructBindingContext(
VarDecl *VD) {
5301 for (
unsigned i = 0; i < 4; ++i) {
5302 RegBindingsAttrs[i] =
nullptr;
5303 RegBindingOffset[i] = 0;
5305 VkBindingAttr =
nullptr;
5306 VkBindingOffset = 0;
5312 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5314 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5317 RegBindingsAttrs[RegTypeIdx] = RBA;
5322 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5323 VkBindingAttr = VBA;
5330 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5331 unsigned Range,
bool HasCounter) {
5332 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5334 if (VkBindingAttr) {
5335 unsigned Offset = VkBindingOffset;
5336 VkBindingOffset +=
Range;
5337 return HLSLVkBindingAttr::CreateImplicit(
5338 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5339 VkBindingAttr->getRange());
5342 HLSLResourceBindingAttr *RBA =
5343 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5344 HLSLResourceBindingAttr *NewAttr =
nullptr;
5346 if (RBA && RBA->hasRegisterSlot()) {
5349 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5350 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5352 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5353 StringRef NewSlotNumberStr =
5355 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5356 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5357 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5361 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5362 NewAttr->setBinding(RegType, std::nullopt,
5363 RBA ? RBA->getSpaceNumber() : 0);
5367 NewAttr->setImplicitCounterBindingOrderID(
5376static void createGlobalResourceDeclForStruct(
5378 QualType ResTy, StructBindingContext &BindingCtx) {
5380 "expected resource type or array of resources");
5391 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5392 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5397 const HLSLAttributedResourceType *ResHandleTy =
5398 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5402 Attr *BindingAttr = BindingCtx.createBindingAttr(
5404 ResDecl->
addAttr(BindingAttr);
5405 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5414 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5421static void handleArrayOfStructWithResources(
5423 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5428static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5430 EmbeddedResourceNameBuilder &NameBuilder,
5431 StructBindingContext &BindingCtx) {
5434 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5441 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5455 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5458 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5460 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5462 "resource arrays should have been already handled");
5463 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5472handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5474 EmbeddedResourceNameBuilder &NameBuilder,
5475 StructBindingContext &BindingCtx) {
5483 if (!SubCAT && !ElementRD)
5486 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5489 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5492 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5505void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5506 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5507 StructBindingContext BindingCtx(VD);
5511 "Expected non-resource struct or array type");
5514 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5518 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5519 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5527 if (
SemaRef.RequireCompleteType(
5530 diag::err_typecheck_decl_incomplete_type)) {
5544 DefaultCBufferDecls.push_back(VD);
5549 collectResourceBindingsOnVarDecl(VD);
5551 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5563 processExplicitBindingsOnDecl(VD);
5601 handleGlobalStructOrArrayOfWithResources(VD);
5605 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5614 "expected resource record type");
5630 const char *CreateMethodName;
5632 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5633 :
"__createFromBinding";
5635 CreateMethodName = HasCounter
5636 ?
"__createFromImplicitBindingWithImplicitCounter"
5637 :
"__createFromImplicitBinding";
5642 if (!CreateMethod) {
5647 "create method lookup should always succeed for built-in resource "
5656 Args.push_back(RegSlot);
5664 Args.push_back(OrderId);
5670 Args.push_back(Space);
5674 Args.push_back(RangeSize);
5678 Args.push_back(Index);
5680 StringRef VarName = VD->
getName();
5688 Args.push_back(NameCast);
5696 Args.push_back(CounterId);
5719 SemaRef.CheckCompleteVariableDeclaration(VD);
5725 "expected array of resource records");
5746 lookupMethod(
SemaRef, ResourceDecl,
5747 HasCounter ?
"__createFromBindingWithImplicitCounter"
5748 :
"__createFromBinding",
5752 CreateMethod = lookupMethod(
5754 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5755 :
"__createFromImplicitBinding",
5798std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5799 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5800 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5801 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5802 if (!TrueInfo || !FalseInfo)
5803 return std::nullopt;
5804 if (*TrueInfo != *FalseInfo)
5805 return std::nullopt;
5809 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5818 if (
const auto *AttrResType =
5819 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5821 return Bindings.getDeclBindingInfo(VD, RC);
5828void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
5829 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
5832 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5837 if (*ExprBinding ==
nullptr)
5840 auto PrevBinding = Assigns.find(VD);
5841 if (PrevBinding == Assigns.end()) {
5843 Assigns.insert({VD, *ExprBinding});
5848 if (*ExprBinding != PrevBinding->second) {
5850 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5852 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
5863 "expected LHS to be a resource record or array of resource records");
5864 if (Opc != BO_Assign)
5869 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5877 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
5882 trackLocalResource(VD, RHSExpr);
5899void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
5901 "expected global variable that contains HLSL resource");
5904 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
5905 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
5906 ? ResourceClass::CBuffer
5907 : ResourceClass::SRV);
5920 if (
const HLSLAttributedResourceType *AttrResType =
5921 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5922 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
5927 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
5928 collectResourceBindingsOnUserRecordDecl(VD, RT);
5934void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
5937 bool HasBinding =
false;
5938 for (Attr *A : VD->
attrs()) {
5941 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
5942 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
5945 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
5946 if (!RBA || !RBA->hasRegisterSlot())
5951 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
5952 "never have an attribute created");
5954 if (RT == RegisterType::C) {
5955 if (Bindings.hasBindingInfoForDecl(VD))
5957 diag::warn_hlsl_user_defined_type_missing_member)
5958 <<
static_cast<int>(RT);
5966 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
5971 diag::warn_hlsl_user_defined_type_missing_member)
5972 <<
static_cast<int>(RT);
5980class InitListTransformer {
5984 QualType *DstIt =
nullptr;
5985 Expr **ArgIt =
nullptr;
5991 bool castInitializer(Expr *E) {
5992 assert(DstIt &&
"This should always be something!");
5993 if (DstIt == DestTypes.end()) {
5995 ArgExprs.push_back(E);
6000 DstIt = DestTypes.begin();
6003 Ctx, *DstIt,
false);
6008 ArgExprs.push_back(
Init);
6013 bool buildInitializerListImpl(Expr *E) {
6015 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6016 for (
auto *SubInit :
Init->inits())
6017 if (!buildInitializerListImpl(SubInit))
6027 return castInitializer(E);
6041 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6046 for (uint64_t I = 0; I <
Size; ++I) {
6048 SizeTy, SourceLocation());
6054 if (!castInitializer(ElExpr.
get()))
6059 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6060 unsigned Rows = MTy->getNumRows();
6061 unsigned Cols = MTy->getNumColumns();
6062 QualType ElemTy = MTy->getElementType();
6064 for (
unsigned R = 0;
R < Rows; ++
R) {
6065 for (
unsigned C = 0;
C < Cols; ++
C) {
6078 if (!castInitializer(ElExpr.
get()))
6086 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6090 for (uint64_t I = 0; I <
Size; ++I) {
6092 SizeTy, SourceLocation());
6097 if (!buildInitializerListImpl(ElExpr.
get()))
6104 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6105 RecordDecls.push_back(RD);
6106 while (RecordDecls.back()->getNumBases()) {
6107 CXXRecordDecl *D = RecordDecls.back();
6109 "HLSL doesn't support multiple inheritance");
6110 RecordDecls.push_back(
6113 while (!RecordDecls.empty()) {
6114 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6115 for (
auto *FD : RD->
fields()) {
6116 if (FD->isUnnamedBitField())
6124 if (!buildInitializerListImpl(Res.
get()))
6132 Expr *generateInitListsImpl(QualType Ty) {
6134 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6139 llvm::SmallVector<Expr *>
Inits;
6144 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6145 ElTy = ATy->getElementType();
6146 Size = ATy->getNumElements();
6147 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6148 ElTy = CMTy->getElementType();
6149 Size = CMTy->getNumElementsFlattened();
6152 ElTy = VTy->getElementType();
6153 Size = VTy->getZExtSize();
6155 for (uint64_t I = 0; I <
Size; ++I)
6156 Inits.push_back(generateInitListsImpl(ElTy));
6159 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6160 RecordDecls.push_back(RD);
6161 while (RecordDecls.back()->getNumBases()) {
6162 CXXRecordDecl *D = RecordDecls.back();
6164 "HLSL doesn't support multiple inheritance");
6165 RecordDecls.push_back(
6168 while (!RecordDecls.empty()) {
6169 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6170 for (
auto *FD : RD->
fields())
6171 if (!FD->isUnnamedBitField())
6176 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6177 Inits.back()->getEndLoc(),
false);
6178 NewInit->setType(Ty);
6183 llvm::SmallVector<QualType, 16> DestTypes;
6184 llvm::SmallVector<Expr *, 16> ArgExprs;
6185 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6186 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6187 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6188 InitTy = Entity.
getType().getNonReferenceType();
6198 DstIt = DestTypes.begin();
6201 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6203 Expr *generateInitLists() {
6204 assert(!ArgExprs.empty() &&
6205 "Call buildInitializerList to generate argument expressions.");
6206 ArgIt = ArgExprs.begin();
6208 return generateInitListsImpl(InitTy);
6209 llvm::SmallVector<Expr *>
Inits;
6210 while (ArgIt != ArgExprs.end())
6211 Inits.push_back(generateInitListsImpl(InitTy));
6214 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6215 Inits.back()->getEndLoc(),
false);
6216 llvm::APInt ArySize(64,
Inits.size());
6218 ArraySizeModifier::Normal, 0));
6230 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6237 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6241 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6261 if (
Init->getType()->isScalarType())
6264 InitListTransformer ILT(
SemaRef, Entity);
6266 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6274 Init->setInit(I, E);
6276 if (!ILT.buildInitializerList(E))
6279 size_t ExpectedSize = ILT.DestTypes.size();
6280 size_t ActualSize = ILT.ArgExprs.size();
6281 if (ExpectedSize == 0 && ActualSize == 0)
6288 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6290 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6291 << (int)(ExpectedSize < ActualSize) << InitTy
6292 << ExpectedSize << ActualSize;
6302 assert(ExpectedSize > 0 &&
6303 "The expected size of an incomplete array type must be at least 1.");
6305 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6313 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6314 if (ExpectedSize != ActualSize) {
6315 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6316 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6317 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6324 Init->resizeInits(Ctx, NewInit->getNumInits());
6325 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6326 Init->updateInit(Ctx, I, NewInit->getInit(I));
6334 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6344 StringRef AccessorName = CompName->
getName();
6345 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6347 unsigned Rows = MT->getNumRows();
6348 unsigned Cols = MT->getNumColumns();
6349 bool IsZeroBasedAccessor =
false;
6350 unsigned ChunkLen = 0;
6351 if (AccessorName.size() < 2)
6353 "length 4 for zero based: \'_mRC\' or "
6354 "length 3 for one-based: \'_RC\' accessor",
6357 if (AccessorName[0] ==
'_') {
6358 if (AccessorName[1] ==
'm') {
6359 IsZeroBasedAccessor =
true;
6366 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6369 if (AccessorName.size() % ChunkLen != 0) {
6370 const llvm::StringRef
Expected = IsZeroBasedAccessor
6371 ?
"zero based: '_mRC' accessor"
6372 :
"one-based: '_RC' accessor";
6377 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6378 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6379 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6381 bool HasRepeated =
false;
6383 unsigned NumComponents = 0;
6384 const char *Begin = AccessorName.data();
6386 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6387 const char *Chunk = Begin + I;
6388 char RowChar = 0, ColChar = 0;
6389 if (IsZeroBasedAccessor) {
6391 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6392 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6394 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6401 if (Chunk[0] !=
'_')
6403 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6410 bool IsDigitsError =
false;
6412 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6416 IsDigitsError =
true;
6420 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6424 IsDigitsError =
true;
6429 unsigned Row = RowChar -
'0';
6430 unsigned Col = ColChar -
'0';
6432 bool HasIndexingError =
false;
6433 if (IsZeroBasedAccessor) {
6435 if (!isZeroBasedIndex(Row)) {
6436 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6438 HasIndexingError =
true;
6440 if (!isZeroBasedIndex(Col)) {
6441 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6443 HasIndexingError =
true;
6447 if (!isOneBasedIndex(Row)) {
6448 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6450 HasIndexingError =
true;
6452 if (!isOneBasedIndex(Col)) {
6453 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6455 HasIndexingError =
true;
6462 if (HasIndexingError)
6468 bool HasBoundsError =
false;
6470 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6472 HasBoundsError =
true;
6475 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6477 HasBoundsError =
true;
6482 unsigned FlatIndex = Row * Cols + Col;
6483 if (Seen[FlatIndex])
6485 Seen[FlatIndex] =
true;
6488 if (NumComponents == 0 || NumComponents > 4) {
6489 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6494 QualType ElemTy = MT->getElementType();
6495 if (NumComponents == 1)
6501 for (Sema::ExtVectorDeclsType::iterator
6505 if ((*I)->getUnderlyingType() == VT)
6516 trackLocalResource(VDecl,
Init);
6518 const HLSLVkConstantIdAttr *ConstIdAttr =
6519 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6526 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
6536 int ConstantID = ConstIdAttr->getId();
6537 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6539 ConstIdAttr->getLocation());
6543 if (
C->getType()->getCanonicalTypeUnqualified() !=
6547 Context.getTrivialTypeSourceInfo(
6548 Init->getType(),
Init->getExprLoc()),
6567 if (!Params || Params->
size() != 1)
6580 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6581 if (TTP->hasDefaultArgument()) {
6582 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6585 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6586 if (NTTP->hasDefaultArgument()) {
6587 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6590 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6591 if (TTPD->hasDefaultArgument()) {
6592 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6599 return SemaRef.CheckTemplateIdType(
6601 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 isLayoutAdaptingMatrixBuiltin(unsigned BuiltinID)
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.
bool isHLSLBuiltinRecord() const
Returns true if the class is a built-in HLSL record.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceLocation getEndLoc() const
static CanQual< Type > CreateUnsafe(QualType Other)
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
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)
void propagateContextualMatrixLayout(Expr *E, QualType DestType)
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)
bool canHaveOverloadedBinOp(QualType Ty, BinaryOperatorKind Opc)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
void handleVkPushConstantAttr(Decl *D, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
NamedDecl * getConstantBufferConversionFunction(QualType Type, CXXRecordDecl *RD)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
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)
llvm::ImmutableSet< T > join(llvm::ImmutableSet< T > A, llvm::ImmutableSet< T > B, typename llvm::ImmutableSet< T >::Factory &F)
Computes the union of two ImmutableSets.
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