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;
2849 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2853 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2854 unsigned CurrentShaderStageBit;
2859 bool ReportOnlyShaderStageIssues;
2862 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2863 static_assert(
sizeof(
unsigned) >= 4);
2864 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2865 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2866 "ShaderType is too big for this bitmap");
2869 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2870 CurrentShaderEnvironment = ShaderType;
2871 CurrentShaderStageBit = (1 << bitmapIndex);
2874 void SetUnknownShaderStageContext() {
2875 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2876 CurrentShaderStageBit = (1 << 31);
2879 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2880 return CurrentShaderEnvironment;
2883 bool InUnknownShaderStageContext()
const {
2884 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2888 void AddToScannedFunctions(
const FunctionDecl *FD) {
2889 unsigned &ScannedStages = ScannedDecls[FD];
2890 ScannedStages |= CurrentShaderStageBit;
2893 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2895 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2896 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2899 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2900 return ScannerStages & CurrentShaderStageBit;
2903 static bool NeverBeenScanned(
unsigned ScannedStages) {
2904 return ScannedStages == 0;
2908 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2909 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2911 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2912 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2915 DiagnoseHLSLAvailability(Sema &SemaRef)
2917 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2918 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2921 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2922 void RunOnFunction(
const FunctionDecl *FD);
2924 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2925 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2927 HandleFunctionOrMethodRef(FD, DRE);
2931 bool VisitMemberExpr(MemberExpr *ME)
override {
2932 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2934 HandleFunctionOrMethodRef(FD, ME);
2939void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2942 "expected DeclRefExpr or MemberExpr");
2946 if (FD->
hasBody(FDWithBody)) {
2947 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2948 DeclsToScan.push_back(FDWithBody);
2953 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2955 CheckDeclAvailability(
2959void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2968 DeclContextsToScan.push_back(TU);
2970 while (!DeclContextsToScan.empty()) {
2971 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2972 for (
auto &D : DC->
decls()) {
2979 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2980 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2985 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2990 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2991 SetShaderStageContext(ShaderAttr->getType());
3000 for (
const auto *Redecl : FD->
redecls()) {
3001 if (Redecl->isInExportDeclContext()) {
3008 SetUnknownShaderStageContext();
3016void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3017 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3018 DeclsToScan.push_back(FD);
3020 while (!DeclsToScan.empty()) {
3028 const unsigned ScannedStages = GetScannedStages(FD);
3029 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3032 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3034 AddToScannedFunctions(FD);
3039bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3040 const AvailabilityAttr *AA) {
3045 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3046 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3049 llvm::Triple::EnvironmentType AttrEnv =
3050 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3052 return CurrentEnv == AttrEnv;
3055const AvailabilityAttr *
3056DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3057 AvailabilityAttr
const *PartialMatch =
nullptr;
3061 for (
const auto *A : D->
attrs()) {
3062 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3063 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3064 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3065 StringRef TargetPlatform =
3069 if (AttrPlatform == TargetPlatform) {
3071 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3073 PartialMatch = Avail;
3077 return PartialMatch;
3082void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3083 const AvailabilityAttr *AA,
3102 if (ReportOnlyShaderStageIssues)
3108 if (InUnknownShaderStageContext())
3113 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3114 VersionTuple Introduced = AA->getIntroduced();
3123 llvm::StringRef PlatformName(
3126 llvm::StringRef CurrentEnvStr =
3127 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3129 llvm::StringRef AttrEnvStr =
3130 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3131 bool UseEnvironment = !AttrEnvStr.empty();
3133 if (EnvironmentMatches) {
3134 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3135 <<
Range << D << PlatformName << Introduced.getAsString()
3136 << UseEnvironment << CurrentEnvStr;
3138 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3142 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3143 << D << PlatformName << Introduced.getAsString()
3145 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3152 if (!DefaultCBufferDecls.empty()) {
3155 DefaultCBufferDecls);
3158 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3162 for (
const Decl *VD : DefaultCBufferDecls) {
3163 const HLSLResourceBindingAttr *RBA =
3164 VD->
getAttr<HLSLResourceBindingAttr>();
3165 if (RBA && RBA->hasRegisterSlot() &&
3166 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3173 SemaRef.Consumer.HandleTopLevelDecl(DG);
3175 diagnoseAvailabilityViolations(TU);
3184 "expected member expr to have resource record type or array of them");
3190 const Expr *NonConstIndexExpr =
nullptr;
3193 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3194 if (!NonConstIndexExpr)
3202 diag::err_hlsl_resource_member_array_access_not_constant);
3206 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3207 const Expr *IdxExpr = ASE->getIdx();
3209 NonConstIndexExpr = IdxExpr;
3211 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3212 E = SubME->getBase();
3213 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3214 E = ICE->getSubExpr();
3216 llvm_unreachable(
"unexpected expr type in resource member access");
3225 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3228 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3231 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3235 [[maybe_unused]]
bool LookupSucceeded =
3236 SemaRef.LookupQualifiedName(ConvR, RD);
3237 assert(LookupSucceeded);
3246std::optional<ExprResult>
3249 const HLSLAttributedResourceType *ResTy =
3250 HLSLAttributedResourceType::findHandleTypeOnResource(
3251 BaseType.getTypePtr());
3253 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3254 return std::nullopt;
3256 QualType TemplateType = ResTy->getContainedType();
3260 assert(NamedConversionDecl &&
3261 "Could not find conversion function for ConstantBuffer.");
3262 auto *ConversionDecl =
3265 return SemaRef.BuildCXXMemberCallExpr(BaseExpr.
get(), NamedConversionDecl,
3277 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3280 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3287 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3290 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3315 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3330 if (!BaseType->isFloat32Type())
3331 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3332 << ArgOrdinal << 5 << 0
3342 BaseType = VT->getElementType();
3344 BaseType = MT->getElementType();
3346 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3347 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3348 << ArgOrdinal << 5 << 0
3362 if (!BaseType->isDoubleType()) {
3365 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3366 << ArgOrdinal << PassedType;
3373 unsigned ArgIndex) {
3374 auto *Arg = TheCall->
getArg(ArgIndex);
3376 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3379 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3393 << (ArgIndex + 1) << LValueTy;
3403 if (VecTy->getElementType()->isDoubleType())
3404 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3405 << ArgOrdinal << 1 << 0 << 1
3415 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3416 << ArgOrdinal << 5 << 1
3425 if (VecTy->getElementType()->isUnsignedIntegerType())
3428 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3429 << ArgOrdinal << 4 << 3 << 0
3438 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3439 << ArgOrdinal << 5 << 3
3445 unsigned ArgOrdinal,
unsigned Width) {
3448 ArgTy = VTy->getElementType();
3450 uint64_t ElementBitCount =
3452 if (ElementBitCount != Width) {
3454 diag::err_integer_incorrect_bit_count)
3455 << Width << ElementBitCount;
3472 unsigned ArgIndex) {
3481 diag::err_typecheck_expect_scalar_or_vector)
3482 << ArgType << Scalar;
3489 QualType Scalar,
unsigned ArgIndex) {
3500 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3513 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3514 << ArgType << Scalar;
3519 unsigned ArgIndex) {
3524 if (!(ArgType->isScalarType() ||
3525 (VTy && VTy->getElementType()->isScalarType()))) {
3527 diag::err_typecheck_expect_any_scalar_or_vector)
3537 unsigned ArgIndex) {
3539 assert(ArgIndex < TheCall->getNumArgs());
3547 diag::err_typecheck_expect_any_scalar_or_vector)
3572 diag::err_typecheck_call_different_arg_types)
3591 Arg1ScalarTy = VTy->getElementType();
3595 Arg2ScalarTy = VTy->getElementType();
3598 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3599 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3609 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3611 diag::err_typecheck_vector_lengths_not_equal)
3617 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3619 diag::err_typecheck_vector_lengths_not_equal)
3631 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3634 unsigned int ActualDim = 1;
3636 ActualDim = VTy->getNumElements();
3637 IndexTy = VTy->getElementType();
3641 diag::err_typecheck_expect_int)
3647 const HLSLAttributedResourceType *ResTy =
3649 assert(ResTy &&
"Resource argument must be a resource");
3650 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3652 unsigned int ExpectedDim = 1;
3653 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3656 if (ActualDim != ExpectedDim) {
3658 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3669 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3673 const HLSLAttributedResourceType *ResTy =
3677 diag::err_typecheck_expect_hlsl_resource)
3681 if (Check && Check(ResTy)) {
3683 diag::err_invalid_hlsl_resource_type)
3691 QualType BaseType,
unsigned ExpectedCount,
3693 unsigned PassedCount = 1;
3695 PassedCount = VecTy->getNumElements();
3697 if (PassedCount != ExpectedCount) {
3700 S->
Diag(Loc, diag::err_typecheck_convert_incompatible)
3712 [](
const HLSLAttributedResourceType *ResType) {
3713 return ResType->getAttrs().ResourceDimension ==
3714 llvm::dxil::ResourceDimension::Unknown;
3720 [](
const HLSLAttributedResourceType *ResType) {
3721 return ResType->getAttrs().ResourceClass !=
3722 llvm::hlsl::ResourceClass::Sampler;
3730 unsigned ExpectedDim =
3758 unsigned NextIdx = 3;
3764 diag::err_typecheck_convert_incompatible)
3772 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3776 diag::err_typecheck_convert_incompatible)
3783 std::optional<llvm::APSInt> ComponentOpt =
3786 int64_t ComponentVal = ComponentOpt->getSExtValue();
3787 if (ComponentVal != 0) {
3790 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3791 "The component is not in the expected range.");
3793 diag::err_hlsl_gathercmp_invalid_component)
3803 const HLSLAttributedResourceType *ResourceTy =
3806 unsigned ExpectedDim =
3815 assert(ResourceTy->hasContainedType() &&
3816 "Expecting a contained type for resource with a dimension "
3818 QualType ReturnType = ResourceTy->getContainedType();
3822 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3828 ReturnType = VecTy->getElementType();
3841 [](
const HLSLAttributedResourceType *ResType) {
3842 return ResType->getAttrs().ResourceDimension ==
3843 llvm::dxil::ResourceDimension::Unknown;
3851 unsigned ExpectedDim =
3860 EltTy = VTy->getElementType();
3875 TheCall->
setType(ResourceTy->getContainedType());
3880 unsigned MinArgs, MaxArgs;
3908 const HLSLAttributedResourceType *ResourceTy =
3910 unsigned ExpectedDim =
3913 unsigned NextIdx = 3;
3922 diag::err_typecheck_convert_incompatible)
3957 diag::err_typecheck_convert_incompatible)
3963 assert(ResourceTy->hasContainedType() &&
3964 "Expecting a contained type for resource with a dimension "
3966 QualType ReturnType = ResourceTy->getContainedType();
3969 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3982 switch (BuiltinID) {
3983 case Builtin::BI__builtin_hlsl_adduint64: {
3984 if (
SemaRef.checkArgCount(TheCall, 2))
3998 if (NumElementsArg != 2 && NumElementsArg != 4) {
4000 << 1 << 64 << NumElementsArg * 32;
4014 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4015 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4022 QualType ContainedTy = ResourceTy->getContainedType();
4023 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4026 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4031 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4032 if (
SemaRef.checkArgCount(TheCall, 3) ||
4039 "expected pointer type for second argument");
4046 diag::err_invalid_use_of_array_type);
4050 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4053 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4058 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4059 if (
SemaRef.checkArgCount(TheCall, 3) ||
4062 SemaRef.getASTContext().UnsignedIntTy) ||
4064 SemaRef.getASTContext().UnsignedIntTy) ||
4070 QualType ReturnType = ResourceTy->getContainedType();
4075 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4076 if (
SemaRef.checkArgCount(TheCall, 4) ||
4079 SemaRef.getASTContext().UnsignedIntTy) ||
4081 SemaRef.getASTContext().UnsignedIntTy) ||
4087 "expected pointer type for second argument");
4094 diag::err_invalid_use_of_array_type);
4100 case Builtin::BI__builtin_hlsl_resource_load_level:
4102 case Builtin::BI__builtin_hlsl_resource_sample:
4104 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4106 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4108 case Builtin::BI__builtin_hlsl_resource_sample_level:
4110 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4112 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4114 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4115 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4117 case Builtin::BI__builtin_hlsl_resource_gather:
4119 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4121 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4122 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4128 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4129 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4135 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4136 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4142 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4143 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4146 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4147 auto MainAttrs = MainResType->getAttrs();
4148 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4149 MainAttrs.IsCounter =
true;
4151 MainResType->getWrappedType(), MainResType->getContainedType(),
4155 TheCall->
setType(CounterHandleTy);
4158 case Builtin::BI__builtin_hlsl_and:
4159 case Builtin::BI__builtin_hlsl_or: {
4160 if (
SemaRef.checkArgCount(TheCall, 2))
4174 case Builtin::BI__builtin_hlsl_all:
4175 case Builtin::BI__builtin_hlsl_any: {
4176 if (
SemaRef.checkArgCount(TheCall, 1))
4182 case Builtin::BI__builtin_hlsl_asdouble: {
4183 if (
SemaRef.checkArgCount(TheCall, 2))
4187 SemaRef.Context.UnsignedIntTy,
4192 SemaRef.Context.UnsignedIntTy,
4201 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4202 if (
SemaRef.BuiltinElementwiseTernaryMath(
4208 case Builtin::BI__builtin_hlsl_dot: {
4210 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4216 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4217 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4218 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4228 EltTy = VecTy->getElementType();
4229 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4242 case Builtin::BI__builtin_hlsl_select: {
4243 if (
SemaRef.checkArgCount(TheCall, 3))
4251 if (VTy && VTy->getElementType()->isBooleanType() &&
4256 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4257 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4258 if (
SemaRef.checkArgCount(TheCall, 1))
4264 diag::err_builtin_invalid_arg_type)
4267 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4271 case Builtin::BI__builtin_hlsl_elementwise_degrees:
4272 case Builtin::BI__builtin_hlsl_elementwise_radians:
4273 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4274 case Builtin::BI__builtin_hlsl_elementwise_frac:
4275 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4276 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4277 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4278 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4279 if (
SemaRef.checkArgCount(TheCall, 1))
4284 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4288 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4289 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4290 if (
SemaRef.checkArgCount(TheCall, 1))
4295 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4300 case Builtin::BI__builtin_hlsl_lerp: {
4301 if (
SemaRef.checkArgCount(TheCall, 3))
4308 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
4312 case Builtin::BI__builtin_hlsl_mad: {
4313 if (
SemaRef.BuiltinElementwiseTernaryMath(
4319 case Builtin::BI__builtin_hlsl_mul: {
4320 if (
SemaRef.checkArgCount(TheCall, 2))
4329 if (
const auto *VTy = T->getAs<
VectorType>())
4330 return VTy->getElementType();
4332 return MTy->getElementType();
4336 QualType EltTy0 = getElemType(Ty0);
4345 if (IsVec0 && IsMat1) {
4348 }
else if (IsMat0 && IsVec1) {
4352 assert(IsMat0 && IsMat1);
4362 case Builtin::BI__builtin_hlsl_normalize: {
4363 if (
SemaRef.checkArgCount(TheCall, 1))
4374 case Builtin::BI__builtin_elementwise_fma: {
4375 if (
SemaRef.checkArgCount(TheCall, 3) ||
4390 case Builtin::BI__builtin_hlsl_transpose: {
4391 if (
SemaRef.checkArgCount(TheCall, 1))
4400 << 1 << 3 << 0 << 0 << ArgTy;
4405 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4409 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4410 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4418 case Builtin::BI__builtin_hlsl_step: {
4419 if (
SemaRef.checkArgCount(TheCall, 2))
4431 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4432 if (
SemaRef.checkArgCount(TheCall, 1))
4446 unsigned NumElts = VecTy->getNumElements();
4456 case Builtin::BI__builtin_hlsl_wave_active_max:
4457 case Builtin::BI__builtin_hlsl_wave_active_min:
4458 case Builtin::BI__builtin_hlsl_wave_active_sum:
4459 case Builtin::BI__builtin_hlsl_wave_active_product: {
4460 if (
SemaRef.checkArgCount(TheCall, 1))
4473 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4474 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4475 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4476 if (
SemaRef.checkArgCount(TheCall, 1))
4491 (VTy && VTy->getElementType()->isIntegerType()))) {
4493 diag::err_builtin_invalid_arg_type)
4494 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4502 case Builtin::BI__builtin_hlsl_interlocked_add: {
4512 diag::err_typecheck_call_too_few_args_at_least)
4517 if (
SemaRef.checkArgCountAtMost(TheCall, 3))
4523 diag::err_builtin_invalid_arg_type)
4551 case Builtin::BI__builtin_elementwise_bitreverse: {
4559 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4560 if (
SemaRef.checkArgCount(TheCall, 1))
4565 if (!(
ArgType->isScalarType())) {
4567 diag::err_typecheck_expect_any_scalar_or_vector)
4572 if (!(
ArgType->isBooleanType())) {
4574 diag::err_typecheck_expect_any_scalar_or_vector)
4581 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4582 if (
SemaRef.checkArgCount(TheCall, 2))
4590 diag::err_typecheck_convert_incompatible)
4591 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4604 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4605 if (
SemaRef.checkArgCount(TheCall, 0))
4609 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4610 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4611 if (
SemaRef.checkArgCount(TheCall, 1))
4624 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4625 case Builtin::BI__builtin_hlsl_quad_read_across_y: {
4626 if (
SemaRef.checkArgCount(TheCall, 1))
4638 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4639 if (
SemaRef.checkArgCount(TheCall, 3))
4645 SemaRef.Context.UnsignedIntTy, 1) ||
4647 SemaRef.Context.UnsignedIntTy, 2))
4655 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4656 if (
SemaRef.checkArgCount(TheCall, 1))
4663 case Builtin::BI__builtin_elementwise_acos:
4664 case Builtin::BI__builtin_elementwise_asin:
4665 case Builtin::BI__builtin_elementwise_atan:
4666 case Builtin::BI__builtin_elementwise_atan2:
4667 case Builtin::BI__builtin_elementwise_ceil:
4668 case Builtin::BI__builtin_elementwise_cos:
4669 case Builtin::BI__builtin_elementwise_cosh:
4670 case Builtin::BI__builtin_elementwise_exp:
4671 case Builtin::BI__builtin_elementwise_exp2:
4672 case Builtin::BI__builtin_elementwise_exp10:
4673 case Builtin::BI__builtin_elementwise_floor:
4674 case Builtin::BI__builtin_elementwise_fmod:
4675 case Builtin::BI__builtin_elementwise_log:
4676 case Builtin::BI__builtin_elementwise_log2:
4677 case Builtin::BI__builtin_elementwise_log10:
4678 case Builtin::BI__builtin_elementwise_pow:
4679 case Builtin::BI__builtin_elementwise_roundeven:
4680 case Builtin::BI__builtin_elementwise_sin:
4681 case Builtin::BI__builtin_elementwise_sinh:
4682 case Builtin::BI__builtin_elementwise_sqrt:
4683 case Builtin::BI__builtin_elementwise_tan:
4684 case Builtin::BI__builtin_elementwise_tanh:
4685 case Builtin::BI__builtin_elementwise_trunc: {
4691 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4692 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4693 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4694 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4695 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4700 std::optional<llvm::APSInt> Offset =
4702 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4704 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4710 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4711 if (
SemaRef.checkArgCount(TheCall, 1))
4722 ArgTy = VTy->getElementType();
4725 diag::err_builtin_invalid_arg_type)
4734 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4735 if (
SemaRef.checkArgCount(TheCall, 1))
4750 WorkList.push_back(BaseTy);
4751 while (!WorkList.empty()) {
4752 QualType T = WorkList.pop_back_val();
4753 T = T.getCanonicalType().getUnqualifiedType();
4754 if (
const auto *AT = dyn_cast<ConstantArrayType>(T)) {
4762 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4763 llvm::append_range(List, ElementFields);
4768 if (
const auto *VT = dyn_cast<VectorType>(T)) {
4769 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
4772 if (
const auto *MT = dyn_cast<ConstantMatrixType>(T)) {
4773 List.insert(List.end(), MT->getNumElementsFlattened(),
4774 MT->getElementType());
4777 if (
const auto *RD = T->getAsCXXRecordDecl()) {
4778 if (RD->isStandardLayout())
4779 RD = RD->getStandardLayoutBaseWithFields();
4783 if (RD->
isUnion() || !RD->isAggregate()) {
4789 for (
const auto *FD : RD->
fields())
4790 if (!FD->isUnnamedBitField())
4791 FieldTypes.push_back(FD->
getType());
4793 std::reverse(FieldTypes.begin(), FieldTypes.end());
4794 llvm::append_range(WorkList, FieldTypes);
4798 if (!RD->isStandardLayout()) {
4800 for (
const auto &
Base : RD->bases())
4801 FieldTypes.push_back(
Base.getType());
4802 std::reverse(FieldTypes.begin(), FieldTypes.end());
4803 llvm::append_range(WorkList, FieldTypes);
4838 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
4844 int ArraySize = VT->getNumElements();
4849 QualType ElTy = VT->getElementType();
4853 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
4869 if (
SemaRef.getASTContext().hasSameType(T1, T2))
4878 return llvm::equal(T1Types, T2Types,
4880 return SemaRef.IsLayoutCompatible(LHS, RHS);
4889 bool HadError =
false;
4891 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
4899 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
4900 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
4901 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
4902 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
4904 if (NSpellingIdx != OSpellingIdx) {
4906 diag::err_hlsl_param_qualifier_mismatch)
4907 << NDAttr << NewParam;
4923 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
4938 llvm_unreachable(
"HLSL doesn't support pointers.");
4941 llvm_unreachable(
"HLSL doesn't support complex types.");
4943 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4945 llvm_unreachable(
"Should have returned before this");
4955 llvm_unreachable(
"HLSL doesn't support complex types.");
4957 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4962 llvm_unreachable(
"HLSL doesn't support pointers.");
4964 llvm_unreachable(
"Should have returned before this");
4970 llvm_unreachable(
"HLSL doesn't support pointers.");
4973 llvm_unreachable(
"HLSL doesn't support fixed point types.");
4977 llvm_unreachable(
"HLSL doesn't support complex types.");
4980 llvm_unreachable(
"Unhandled scalar cast");
5001 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5007 SrcTy = SrcMatTy->getElementType();
5012 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5013 if (DestTypes[I]->isUnionType())
5045 if (SrcTypes.size() < DestTypes.size())
5048 unsigned SrcSize = SrcTypes.size();
5049 unsigned DstSize = DestTypes.size();
5051 for (I = 0; I < DstSize && I < SrcSize; I++) {
5052 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5060 for (; I < SrcSize; I++) {
5061 if (SrcTypes[I]->isUnionType())
5068 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5069 "We should not get here without a parameter modifier expression");
5070 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5077 << Arg << (IsInOut ? 1 : 0);
5083 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5090 << Arg << (IsInOut ? 1 : 0);
5102 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5108 auto *OpV =
new (Ctx)
5113 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
5114 tok::equal, ArgOpV, OpV);
5130 "Pointer and reference types cannot be inout or out parameters");
5131 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5147 for (
const auto *FD : RD->
fields()) {
5151 assert(RD->getNumBases() <= 1 &&
5152 "HLSL doesn't support multiple inheritance");
5153 return RD->getNumBases()
5158 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5159 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5171 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5176 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5182 if (
Decl->getType().hasAddressSpace())
5185 if (
Decl->getType()->isDependentType())
5197 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5211 llvm::Triple::Vulkan;
5212 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5213 if (HasDeclaredAPushConstant)
5219 HasDeclaredAPushConstant =
true;
5246class StructBindingContext {
5249 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5250 unsigned RegBindingOffset[4];
5253 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5254 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5255 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5256 static_cast<unsigned>(RegisterType::Sampler) == 3,
5257 "unexpected register type values");
5260 HLSLVkBindingAttr *VkBindingAttr;
5261 unsigned VkBindingOffset;
5266 StructBindingContext(
VarDecl *VD) {
5267 for (
unsigned i = 0; i < 4; ++i) {
5268 RegBindingsAttrs[i] =
nullptr;
5269 RegBindingOffset[i] = 0;
5271 VkBindingAttr =
nullptr;
5272 VkBindingOffset = 0;
5278 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5280 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5283 RegBindingsAttrs[RegTypeIdx] = RBA;
5288 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5289 VkBindingAttr = VBA;
5296 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5297 unsigned Range,
bool HasCounter) {
5298 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5300 if (VkBindingAttr) {
5301 unsigned Offset = VkBindingOffset;
5302 VkBindingOffset +=
Range;
5303 return HLSLVkBindingAttr::CreateImplicit(
5304 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5305 VkBindingAttr->getRange());
5308 HLSLResourceBindingAttr *RBA =
5309 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5310 HLSLResourceBindingAttr *NewAttr =
nullptr;
5312 if (RBA && RBA->hasRegisterSlot()) {
5315 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5316 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5318 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5319 StringRef NewSlotNumberStr =
5321 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5322 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5323 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5327 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5328 NewAttr->setBinding(RegType, std::nullopt,
5329 RBA ? RBA->getSpaceNumber() : 0);
5333 NewAttr->setImplicitCounterBindingOrderID(
5342static void createGlobalResourceDeclForStruct(
5344 QualType ResTy, StructBindingContext &BindingCtx) {
5346 "expected resource type or array of resources");
5357 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5358 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5363 const HLSLAttributedResourceType *ResHandleTy =
5364 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5368 Attr *BindingAttr = BindingCtx.createBindingAttr(
5370 ResDecl->
addAttr(BindingAttr);
5371 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5380 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5387static void handleArrayOfStructWithResources(
5389 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5394static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5396 EmbeddedResourceNameBuilder &NameBuilder,
5397 StructBindingContext &BindingCtx) {
5400 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5407 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5421 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5424 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5426 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5428 "resource arrays should have been already handled");
5429 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5438handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5440 EmbeddedResourceNameBuilder &NameBuilder,
5441 StructBindingContext &BindingCtx) {
5449 if (!SubCAT && !ElementRD)
5452 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5455 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5458 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5471void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5472 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5473 StructBindingContext BindingCtx(VD);
5477 "Expected non-resource struct or array type");
5480 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5484 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5485 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5493 if (
SemaRef.RequireCompleteType(
5496 diag::err_typecheck_decl_incomplete_type)) {
5510 DefaultCBufferDecls.push_back(VD);
5515 collectResourceBindingsOnVarDecl(VD);
5517 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5529 processExplicitBindingsOnDecl(VD);
5567 handleGlobalStructOrArrayOfWithResources(VD);
5571 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5580 "expected resource record type");
5596 const char *CreateMethodName;
5598 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5599 :
"__createFromBinding";
5601 CreateMethodName = HasCounter
5602 ?
"__createFromImplicitBindingWithImplicitCounter"
5603 :
"__createFromImplicitBinding";
5608 if (!CreateMethod) {
5613 "create method lookup should always succeed for built-in resource "
5622 Args.push_back(RegSlot);
5630 Args.push_back(OrderId);
5636 Args.push_back(Space);
5640 Args.push_back(RangeSize);
5644 Args.push_back(Index);
5646 StringRef VarName = VD->
getName();
5654 Args.push_back(NameCast);
5662 Args.push_back(CounterId);
5685 SemaRef.CheckCompleteVariableDeclaration(VD);
5691 "expected array of resource records");
5712 lookupMethod(
SemaRef, ResourceDecl,
5713 HasCounter ?
"__createFromBindingWithImplicitCounter"
5714 :
"__createFromBinding",
5718 CreateMethod = lookupMethod(
5720 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5721 :
"__createFromImplicitBinding",
5764std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5765 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5766 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5767 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5768 if (!TrueInfo || !FalseInfo)
5769 return std::nullopt;
5770 if (*TrueInfo != *FalseInfo)
5771 return std::nullopt;
5775 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5784 if (
const auto *AttrResType =
5785 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5787 return Bindings.getDeclBindingInfo(VD, RC);
5794void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
5795 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
5798 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5803 if (*ExprBinding ==
nullptr)
5806 auto PrevBinding = Assigns.find(VD);
5807 if (PrevBinding == Assigns.end()) {
5809 Assigns.insert({VD, *ExprBinding});
5814 if (*ExprBinding != PrevBinding->second) {
5816 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5818 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
5829 "expected LHS to be a resource record or array of resource records");
5830 if (Opc != BO_Assign)
5835 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5843 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
5848 trackLocalResource(VD, RHSExpr);
5865void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
5867 "expected global variable that contains HLSL resource");
5870 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
5871 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
5872 ? ResourceClass::CBuffer
5873 : ResourceClass::SRV);
5886 if (
const HLSLAttributedResourceType *AttrResType =
5887 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5888 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
5893 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
5894 collectResourceBindingsOnUserRecordDecl(VD, RT);
5900void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
5903 bool HasBinding =
false;
5904 for (Attr *A : VD->
attrs()) {
5907 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
5908 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
5911 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
5912 if (!RBA || !RBA->hasRegisterSlot())
5917 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
5918 "never have an attribute created");
5920 if (RT == RegisterType::C) {
5921 if (Bindings.hasBindingInfoForDecl(VD))
5923 diag::warn_hlsl_user_defined_type_missing_member)
5924 <<
static_cast<int>(RT);
5932 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
5937 diag::warn_hlsl_user_defined_type_missing_member)
5938 <<
static_cast<int>(RT);
5946class InitListTransformer {
5950 QualType *DstIt =
nullptr;
5951 Expr **ArgIt =
nullptr;
5957 bool castInitializer(Expr *E) {
5958 assert(DstIt &&
"This should always be something!");
5959 if (DstIt == DestTypes.end()) {
5961 ArgExprs.push_back(E);
5966 DstIt = DestTypes.begin();
5969 Ctx, *DstIt,
false);
5974 ArgExprs.push_back(
Init);
5979 bool buildInitializerListImpl(Expr *E) {
5981 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
5982 for (
auto *SubInit :
Init->inits())
5983 if (!buildInitializerListImpl(SubInit))
5993 return castInitializer(E);
6007 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6012 for (uint64_t I = 0; I <
Size; ++I) {
6014 SizeTy, SourceLocation());
6020 if (!castInitializer(ElExpr.
get()))
6025 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6026 unsigned Rows = MTy->getNumRows();
6027 unsigned Cols = MTy->getNumColumns();
6028 QualType ElemTy = MTy->getElementType();
6030 for (
unsigned R = 0;
R < Rows; ++
R) {
6031 for (
unsigned C = 0;
C < Cols; ++
C) {
6044 if (!castInitializer(ElExpr.
get()))
6052 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6056 for (uint64_t I = 0; I <
Size; ++I) {
6058 SizeTy, SourceLocation());
6063 if (!buildInitializerListImpl(ElExpr.
get()))
6070 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6071 RecordDecls.push_back(RD);
6072 while (RecordDecls.back()->getNumBases()) {
6073 CXXRecordDecl *D = RecordDecls.back();
6075 "HLSL doesn't support multiple inheritance");
6076 RecordDecls.push_back(
6079 while (!RecordDecls.empty()) {
6080 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6081 for (
auto *FD : RD->
fields()) {
6082 if (FD->isUnnamedBitField())
6090 if (!buildInitializerListImpl(Res.
get()))
6098 Expr *generateInitListsImpl(QualType Ty) {
6100 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6105 llvm::SmallVector<Expr *>
Inits;
6110 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6111 ElTy = ATy->getElementType();
6112 Size = ATy->getNumElements();
6113 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6114 ElTy = CMTy->getElementType();
6115 Size = CMTy->getNumElementsFlattened();
6118 ElTy = VTy->getElementType();
6119 Size = VTy->getZExtSize();
6121 for (uint64_t I = 0; I <
Size; ++I)
6122 Inits.push_back(generateInitListsImpl(ElTy));
6125 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6126 RecordDecls.push_back(RD);
6127 while (RecordDecls.back()->getNumBases()) {
6128 CXXRecordDecl *D = RecordDecls.back();
6130 "HLSL doesn't support multiple inheritance");
6131 RecordDecls.push_back(
6134 while (!RecordDecls.empty()) {
6135 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6136 for (
auto *FD : RD->
fields())
6137 if (!FD->isUnnamedBitField())
6142 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6143 Inits.back()->getEndLoc(),
false);
6144 NewInit->setType(Ty);
6149 llvm::SmallVector<QualType, 16> DestTypes;
6150 llvm::SmallVector<Expr *, 16> ArgExprs;
6151 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6152 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6153 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6154 InitTy = Entity.
getType().getNonReferenceType();
6164 DstIt = DestTypes.begin();
6167 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6169 Expr *generateInitLists() {
6170 assert(!ArgExprs.empty() &&
6171 "Call buildInitializerList to generate argument expressions.");
6172 ArgIt = ArgExprs.begin();
6174 return generateInitListsImpl(InitTy);
6175 llvm::SmallVector<Expr *>
Inits;
6176 while (ArgIt != ArgExprs.end())
6177 Inits.push_back(generateInitListsImpl(InitTy));
6180 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6181 Inits.back()->getEndLoc(),
false);
6182 llvm::APInt ArySize(64,
Inits.size());
6184 ArraySizeModifier::Normal, 0));
6196 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6203 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6207 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6227 if (
Init->getType()->isScalarType())
6230 InitListTransformer ILT(
SemaRef, Entity);
6232 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6240 Init->setInit(I, E);
6242 if (!ILT.buildInitializerList(E))
6245 size_t ExpectedSize = ILT.DestTypes.size();
6246 size_t ActualSize = ILT.ArgExprs.size();
6247 if (ExpectedSize == 0 && ActualSize == 0)
6254 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6256 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6257 << (int)(ExpectedSize < ActualSize) << InitTy
6258 << ExpectedSize << ActualSize;
6268 assert(ExpectedSize > 0 &&
6269 "The expected size of an incomplete array type must be at least 1.");
6271 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6279 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6280 if (ExpectedSize != ActualSize) {
6281 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6282 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6283 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6290 Init->resizeInits(Ctx, NewInit->getNumInits());
6291 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6292 Init->updateInit(Ctx, I, NewInit->getInit(I));
6300 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6310 StringRef AccessorName = CompName->
getName();
6311 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6313 unsigned Rows = MT->getNumRows();
6314 unsigned Cols = MT->getNumColumns();
6315 bool IsZeroBasedAccessor =
false;
6316 unsigned ChunkLen = 0;
6317 if (AccessorName.size() < 2)
6319 "length 4 for zero based: \'_mRC\' or "
6320 "length 3 for one-based: \'_RC\' accessor",
6323 if (AccessorName[0] ==
'_') {
6324 if (AccessorName[1] ==
'm') {
6325 IsZeroBasedAccessor =
true;
6332 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6335 if (AccessorName.size() % ChunkLen != 0) {
6336 const llvm::StringRef
Expected = IsZeroBasedAccessor
6337 ?
"zero based: '_mRC' accessor"
6338 :
"one-based: '_RC' accessor";
6343 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6344 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6345 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6347 bool HasRepeated =
false;
6349 unsigned NumComponents = 0;
6350 const char *Begin = AccessorName.data();
6352 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6353 const char *Chunk = Begin + I;
6354 char RowChar = 0, ColChar = 0;
6355 if (IsZeroBasedAccessor) {
6357 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6358 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6360 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6367 if (Chunk[0] !=
'_')
6369 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6376 bool IsDigitsError =
false;
6378 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6382 IsDigitsError =
true;
6386 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6390 IsDigitsError =
true;
6395 unsigned Row = RowChar -
'0';
6396 unsigned Col = ColChar -
'0';
6398 bool HasIndexingError =
false;
6399 if (IsZeroBasedAccessor) {
6401 if (!isZeroBasedIndex(Row)) {
6402 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6404 HasIndexingError =
true;
6406 if (!isZeroBasedIndex(Col)) {
6407 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6409 HasIndexingError =
true;
6413 if (!isOneBasedIndex(Row)) {
6414 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6416 HasIndexingError =
true;
6418 if (!isOneBasedIndex(Col)) {
6419 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6421 HasIndexingError =
true;
6428 if (HasIndexingError)
6434 bool HasBoundsError =
false;
6436 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6438 HasBoundsError =
true;
6441 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6443 HasBoundsError =
true;
6448 unsigned FlatIndex = Row * Cols + Col;
6449 if (Seen[FlatIndex])
6451 Seen[FlatIndex] =
true;
6454 if (NumComponents == 0 || NumComponents > 4) {
6455 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6460 QualType ElemTy = MT->getElementType();
6461 if (NumComponents == 1)
6467 for (Sema::ExtVectorDeclsType::iterator
6471 if ((*I)->getUnderlyingType() == VT)
6482 trackLocalResource(VDecl,
Init);
6484 const HLSLVkConstantIdAttr *ConstIdAttr =
6485 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6492 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
6502 int ConstantID = ConstIdAttr->getId();
6503 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6505 ConstIdAttr->getLocation());
6509 if (
C->getType()->getCanonicalTypeUnqualified() !=
6513 Context.getTrivialTypeSourceInfo(
6514 Init->getType(),
Init->getExprLoc()),
6533 if (!Params || Params->
size() != 1)
6546 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6547 if (TTP->hasDefaultArgument()) {
6548 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6551 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6552 if (NTTP->hasDefaultArgument()) {
6553 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6556 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6557 if (TTPD->hasDefaultArgument()) {
6558 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6565 return SemaRef.CheckTemplateIdType(
6567 TemplateArgs,
nullptr,
false);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool containsIncompleteArrayType(QualType Ty)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static StringRef createRegisterString(ASTContext &AST, RegisterType RegType, unsigned N)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static QualType ReportMatrixInvalidMember(Sema &S, StringRef Name, StringRef Expected, SourceLocation OpLoc, SourceLocation CompLoc)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool hasConstantBufferLayout(QualType QT)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckCalculateLodBuiltin(Sema &S, CallExpr *TheCall)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static const Type * createHostLayoutType(Sema &S, const Type *Ty)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static bool CheckArgAddrSpaceOneOf(Sema *S, CallExpr *TheCall, unsigned ArgIndex, ArrayRef< LangAS > AllowedSpaces)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall)
static RegisterType getRegisterType(ResourceClass RC)
static bool ValidateRegisterNumber(uint64_t SlotNum, Decl *TheDecl, ASTContext &Ctx, RegisterType RegTy)
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
static bool CheckVectorElementCount(Sema *S, QualType PassedType, QualType BaseType, unsigned ExpectedCount, SourceLocation Loc)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static char getRegisterTypeChar(RegisterType RT)
static bool CheckNotBoolScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool isMatrixOrArrayOfMatrix(const ASTContext &Ctx, QualType QT)
static bool findExistingMatrixLayoutMarker(QualType T, attr::Kind &ExistingKind)
Walks the existing AttributedType sugar of T looking for a previously applied HLSLRowMajor/HLSLColumn...
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckWavePrefix(Sema *S, CallExpr *TheCall)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static LangAS getLangASFromResourceClass(ResourceClass RC)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static const Type * getHostLayoutFieldType(QualType QT)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind)
static bool CheckScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckFloatRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyDoubleRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
static bool IsDefaultBufferConstantDecl(const ASTContext &Ctx, VarDecl *VD)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool CheckGatherBuiltin(Sema &S, CallExpr *TheCall, bool IsCmp)
static bool isValidWaveSizeValue(unsigned Value)
static bool isResourceRecordTypeOrArrayOf(QualType Ty)
static bool AccumulateHLSLResourceSlots(QualType Ty, uint64_t &StartSlot, const uint64_t &Limit, const ResourceClass ResClass, ASTContext &Ctx, uint64_t ArrayCount=1)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
llvm::StringRef backupStr(llvm::StringRef S) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns) const
Return the unique reference to the matrix type of the specified element type and size.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getLocation() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
base_class_iterator bases_end()
void completeDefinition() override
Indicates that the definition of this class is now complete.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
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)
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