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>()) {
1028 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1029 }
else if (Ver < VersionTuple(6, 6)) {
1030 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1033 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1036 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1037 << WS << WS->getSpelledArgsCount() <<
"6.8";
1042 case llvm::Triple::RootSignature:
1043 llvm_unreachable(
"rootsig environment has no function entry point");
1045 llvm_unreachable(
"Unhandled environment in triple");
1048 SemaHLSL::SemanticContext InputSC = {};
1049 InputSC.CurrentIOType = IOType::In;
1052 SemanticInfo ActiveSemantic;
1053 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1054 if (ActiveSemantic.Semantic)
1055 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1058 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, InputSC)) {
1059 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1064 SemanticInfo ActiveSemantic;
1065 SemaHLSL::SemanticContext OutputSC = {};
1066 OutputSC.CurrentIOType = IOType::Out;
1067 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1068 if (ActiveSemantic.Semantic)
1069 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1071 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1074void SemaHLSL::checkSemanticAnnotation(
1076 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC) {
1077 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1078 assert(ShaderAttr &&
"Entry point has no shader attribute");
1079 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1081 auto SemanticName = SemanticAttr->getSemanticName().upper();
1082 if (SemanticName ==
"SV_DISPATCHTHREADID" ||
1083 SemanticName ==
"SV_GROUPINDEX" || SemanticName ==
"SV_GROUPTHREADID" ||
1084 SemanticName ==
"SV_GROUPID") {
1086 if (ST != llvm::Triple::Compute)
1087 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1088 {{llvm::Triple::Compute, IOType::In}});
1090 if (SemanticAttr->getSemanticIndex() != 0) {
1091 std::string PrettyName =
1092 "'" + SemanticAttr->getSemanticName().str() +
"'";
1093 Diag(SemanticAttr->getLoc(),
1094 diag::err_hlsl_semantic_indexing_not_supported)
1100 if (SemanticName ==
"SV_POSITION") {
1103 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1104 {{llvm::Triple::Vertex, IOType::InOut},
1105 {llvm::Triple::Pixel, IOType::In}});
1108 if (SemanticName ==
"SV_VERTEXID") {
1109 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1110 {{llvm::Triple::Vertex, IOType::In}});
1114 if (SemanticName ==
"SV_TARGET") {
1115 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1116 {{llvm::Triple::Pixel, IOType::Out}});
1122 if (SemanticAttr->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1123 llvm_unreachable(
"Unknown SemanticAttr");
1126void SemaHLSL::diagnoseAttrStageMismatch(
1127 const Attr *A, llvm::Triple::EnvironmentType Stage,
1128 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1129 SmallVector<StringRef, 8> StageStrings;
1130 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1131 [](llvm::Triple::EnvironmentType ST) {
1133 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1135 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1136 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1137 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1140void SemaHLSL::diagnoseSemanticStageMismatch(
1141 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1142 std::initializer_list<SemanticStageInfo> Allowed) {
1144 for (
auto &Case : Allowed) {
1145 if (Case.Stage != Stage)
1148 if (CurrentIOType & Case.AllowedIOTypesMask)
1151 SmallVector<std::string, 8> ValidCases;
1153 Allowed, std::back_inserter(ValidCases), [](SemanticStageInfo Case) {
1154 SmallVector<std::string, 2> ValidType;
1155 if (Case.AllowedIOTypesMask & IOType::In)
1156 ValidType.push_back(
"input");
1157 if (Case.AllowedIOTypesMask & IOType::Out)
1158 ValidType.push_back(
"output");
1160 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage)) +
1161 " " +
join(ValidType,
"/");
1163 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1164 << A->
getAttrName() << (CurrentIOType & IOType::In ?
"input" :
"output")
1165 << llvm::Triple::getEnvironmentTypeName(Case.Stage)
1166 <<
join(ValidCases,
", ");
1170 SmallVector<StringRef, 8> StageStrings;
1172 Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {
1174 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
1177 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1178 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1179 << (Allowed.size() != 1) <<
join(StageStrings,
", ");
1182template <CastKind Kind>
1185 Ty = VTy->getElementType();
1190template <CastKind Kind>
1202 if (LHSFloat && RHSFloat) {
1230 if (LHSSigned == RHSSigned) {
1231 if (IsCompAssign || IntOrder >= 0)
1239 if (IntOrder != (LHSSigned ? 1 : -1)) {
1240 if (IsCompAssign || RHSSigned)
1248 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1249 if (IsCompAssign || LHSSigned)
1265 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1266 QualType NewTy = Ctx.getExtVectorType(
1276 return CK_FloatingCast;
1278 return CK_IntegralCast;
1280 return CK_IntegralToFloating;
1282 return CK_FloatingToIntegral;
1288 bool IsCompAssign) {
1295 if (!LVecTy && IsCompAssign) {
1297 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1299 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1301 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1306 unsigned EndSz = std::numeric_limits<unsigned>::max();
1309 LSz = EndSz = LVecTy->getNumElements();
1312 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1313 "one of the above should have had a value");
1317 if (IsCompAssign && LSz != EndSz) {
1319 diag::err_hlsl_vector_compound_assignment_truncation)
1320 << LHSType << RHSType;
1326 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1331 if (!IsCompAssign && !LVecTy)
1335 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1336 return Ctx.getCommonSugaredType(LHSType, RHSType);
1344 LElTy, RElTy, IsCompAssign);
1347 "HLSL Vectors can only contain integer or floating point types");
1349 LElTy, RElTy, IsCompAssign);
1354 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1355 "Called with non-logical operator");
1357 llvm::raw_svector_ostream OS(Buff);
1359 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1360 OS << NewFnName <<
"(";
1370std::pair<IdentifierInfo *, bool>
1373 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1380 return {DeclIdent,
Found};
1391 for (
auto &RootSigElement : RootElements)
1392 Elements.push_back(RootSigElement.getElement());
1396 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1398 SignatureDecl->setImplicit();
1404 if (RootSigOverrideIdent) {
1407 if (
SemaRef.LookupQualifiedName(R, DC))
1408 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1416struct PerVisibilityBindingChecker {
1419 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1423 llvm::dxbc::ShaderVisibility Vis;
1428 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1430 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1431 llvm::dxil::ResourceClass RC,
uint32_t Space,
1433 const hlsl::RootSignatureElement *Elem) {
1435 assert(BuilderIndex < Builders.size() &&
1436 "Not enough builders for visibility type");
1437 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1438 static_cast<const void *
>(Elem));
1440 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1441 "'All' visibility must come first");
1442 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1443 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1444 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1445 static_cast<const void *
>(Elem));
1447 ElemInfoMap.push_back({Elem,
Visibility,
false});
1450 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1451 auto It = llvm::lower_bound(
1453 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1454 assert(It->Elem == Elem &&
"Element not in map");
1458 bool checkOverlap() {
1459 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1460 return LHS.Elem < RHS.Elem;
1463 bool HadOverlap =
false;
1465 using llvm::hlsl::BindingInfoBuilder;
1466 auto ReportOverlap = [
this,
1467 &HadOverlap](
const BindingInfoBuilder &Builder,
1468 const llvm::hlsl::Binding &Reported) {
1472 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1473 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1474 const auto *PrevElem =
1475 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1477 ElemInfo &Info =
getInfo(Elem);
1482 Info.Diagnosed =
true;
1484 ElemInfo &PrevInfo =
getInfo(PrevElem);
1485 llvm::dxbc::ShaderVisibility CommonVis =
1486 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1489 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1490 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1491 << Reported.isUnbounded() << Reported.UpperBound
1496 this->S->
Diag(PrevElem->getLocation(),
1497 diag::note_hlsl_resource_range_here);
1500 for (BindingInfoBuilder &Builder : Builders)
1501 Builder.calculateBindingInfo(ReportOverlap);
1521 bool HadError =
false;
1522 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1523 uint32_t UpperBound) {
1525 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1526 << LowerBound << UpperBound;
1533 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1534 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1535 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1538 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1539 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1540 ReportError(Loc, 0, 0xfffffffe);
1543 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1544 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1545 ReportError(Loc, 0, 0xffffffef);
1548 const uint32_t Version =
1549 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1550 const uint32_t VersionEnum = Version - 1;
1551 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1553 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1560 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1561 if (
const auto *Descriptor =
1562 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1563 VerifyRegister(Loc, Descriptor->Reg.Number);
1564 VerifySpace(Loc, Descriptor->Space);
1566 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1568 ReportFlagError(Loc);
1569 }
else if (
const auto *Constants =
1570 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1571 VerifyRegister(Loc, Constants->Reg.Number);
1572 VerifySpace(Loc, Constants->Space);
1573 }
else if (
const auto *Sampler =
1574 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1575 VerifyRegister(Loc, Sampler->Reg.Number);
1576 VerifySpace(Loc, Sampler->Space);
1579 "By construction, parseFloatParam can't produce a NaN from a "
1580 "float_literal token");
1582 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1583 ReportError(Loc, 0, 16);
1584 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1585 ReportFloatError(Loc, -16.f, 15.99f);
1586 }
else if (
const auto *Clause =
1587 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1589 VerifyRegister(Loc, Clause->Reg.Number);
1590 VerifySpace(Loc, Clause->Space);
1592 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1596 ReportError(Loc, 1, 0xfffffffe);
1599 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1601 ReportFlagError(Loc);
1605 PerVisibilityBindingChecker BindingChecker(
this);
1606 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1611 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1612 if (
const auto *Descriptor =
1613 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1614 uint32_t LowerBound(Descriptor->Reg.Number);
1615 uint32_t UpperBound(LowerBound);
1617 BindingChecker.trackBinding(
1618 Descriptor->Visibility,
1619 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1620 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1621 }
else if (
const auto *Constants =
1622 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1623 uint32_t LowerBound(Constants->Reg.Number);
1624 uint32_t UpperBound(LowerBound);
1626 BindingChecker.trackBinding(
1627 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1628 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1629 }
else if (
const auto *Sampler =
1630 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1631 uint32_t LowerBound(Sampler->Reg.Number);
1632 uint32_t UpperBound(LowerBound);
1634 BindingChecker.trackBinding(
1635 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1636 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1637 }
else if (
const auto *Clause =
1638 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1641 UnboundClauses.emplace_back(Clause, &RootSigElem);
1642 }
else if (
const auto *Table =
1643 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1644 assert(UnboundClauses.size() == Table->NumClauses &&
1645 "Number of unbound elements must match the number of clauses");
1646 bool HasAnySampler =
false;
1647 bool HasAnyNonSampler =
false;
1648 uint64_t Offset = 0;
1649 bool IsPrevUnbound =
false;
1650 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1652 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1653 HasAnySampler =
true;
1655 HasAnyNonSampler =
true;
1657 if (HasAnySampler && HasAnyNonSampler)
1658 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1663 if (Clause->NumDescriptors == 0)
1667 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1669 Offset = Clause->Offset;
1671 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1672 Offset, Clause->NumDescriptors);
1674 if (IsPrevUnbound && IsAppending)
1675 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1676 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1677 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1680 Offset = RangeBound + 1;
1681 IsPrevUnbound = Clause->NumDescriptors ==
1682 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1685 uint32_t LowerBound(Clause->Reg.Number);
1686 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1687 LowerBound, Clause->NumDescriptors);
1689 BindingChecker.trackBinding(
1691 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1692 LowerBound, UpperBound, ClauseElem);
1694 UnboundClauses.clear();
1698 return BindingChecker.checkOverlap();
1703 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1708 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1709 if (RS->getSignatureIdent() != Ident) {
1710 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1714 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1720 if (
auto *SignatureDecl =
1721 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1728 llvm::VersionTuple SMVersion =
1733 uint32_t ZMax = 1024;
1734 uint32_t ThreadMax = 1024;
1735 if (IsDXIL && SMVersion.getMajor() <= 4) {
1738 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1748 diag::err_hlsl_numthreads_argument_oor)
1757 diag::err_hlsl_numthreads_argument_oor)
1766 diag::err_hlsl_numthreads_argument_oor)
1771 if (
X * Y * Z > ThreadMax) {
1772 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1789 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1797 if (SpelledArgsCount > 1 &&
1801 uint32_t Preferred = 0;
1802 if (SpelledArgsCount > 2 &&
1806 if (SpelledArgsCount > 2) {
1809 diag::err_attribute_power_of_two_in_range)
1810 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1815 if (Preferred < Min || Preferred >
Max) {
1817 diag::err_attribute_power_of_two_in_range)
1818 << AL <<
Min <<
Max << Preferred;
1821 }
else if (SpelledArgsCount > 1) {
1824 diag::err_attribute_power_of_two_in_range)
1825 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1829 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1832 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1837 diag::err_attribute_power_of_two_in_range)
1838 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1843 HLSLWaveSizeAttr *NewAttr =
1880 uint32_t Binding = 0;
1904 if (!
T->hasUnsignedIntegerRepresentation() ||
1905 (VT && VT->getNumElements() > 3)) {
1906 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1907 << AL <<
"uint/uint2/uint3";
1916 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1917 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1918 << AL <<
"float/float1/float2/float3/float4";
1926 std::optional<unsigned> Index) {
1930 QualType ValueType = VD->getType();
1931 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1934 bool IsOutput =
false;
1935 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1942 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1945 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1946 if (Index.has_value())
1947 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1952 if (SemanticName ==
"SV_GROUPINDEX") {
1954 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1955 if (Index.has_value())
1956 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1961 if (SemanticName ==
"SV_GROUPTHREADID") {
1964 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1965 if (Index.has_value())
1966 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1971 if (SemanticName ==
"SV_GROUPID") {
1974 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1975 if (Index.has_value())
1976 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1981 if (SemanticName ==
"SV_POSITION") {
1982 const auto *VT = ValueType->getAs<
VectorType>();
1983 if (!ValueType->hasFloatingRepresentation() ||
1984 (VT && VT->getNumElements() > 4))
1985 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1986 << AL <<
"float/float1/float2/float3/float4";
1991 if (SemanticName ==
"SV_VERTEXID") {
1992 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
1993 if (!ValueType->isUnsignedIntegerType() || SizeInBits != 32)
1994 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
1999 if (SemanticName ==
"SV_TARGET") {
2000 const auto *VT = ValueType->getAs<
VectorType>();
2001 if (!ValueType->hasFloatingRepresentation() ||
2002 (VT && VT->getNumElements() > 4))
2003 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
2004 << AL <<
"float/float1/float2/float3/float4";
2009 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2013 uint32_t IndexValue(0), ExplicitIndex(0);
2016 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2018 assert(IndexValue > 0 ? ExplicitIndex :
true);
2019 std::optional<unsigned> Index =
2020 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
2030 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2031 << AL <<
"shader constant in a constant buffer";
2035 uint32_t SubComponent;
2045 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2050 if (IsAggregateTy) {
2051 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2055 if ((Component * 32 + Size) > 128) {
2056 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2061 EltTy = VT->getElementType();
2063 if (Align > 32 && Component == 1) {
2066 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2080 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2083 llvm::Triple::EnvironmentType ShaderType;
2084 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2085 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2086 << AL << Str << ArgLoc;
2100 Expr *SampleCountExpr) {
2101 assert(AttrList.size() &&
"expected list of resource attributes");
2108 HLSLAttributedResourceType::Attributes ResAttrs;
2110 bool HasResourceClass =
false;
2111 bool HasResourceDimension =
false;
2112 for (
const Attr *A : AttrList) {
2117 case attr::HLSLResourceClass: {
2119 if (HasResourceClass) {
2121 ? diag::warn_duplicate_attribute_exact
2122 : diag::warn_duplicate_attribute)
2126 ResAttrs.ResourceClass = RC;
2127 HasResourceClass =
true;
2130 case attr::HLSLResourceDimension: {
2131 llvm::dxil::ResourceDimension RD =
2133 if (HasResourceDimension) {
2135 ? diag::warn_duplicate_attribute_exact
2136 : diag::warn_duplicate_attribute)
2140 ResAttrs.ResourceDimension = RD;
2141 HasResourceDimension =
true;
2144 case attr::HLSLIsROV:
2145 if (ResAttrs.IsROV) {
2149 ResAttrs.IsROV =
true;
2151 case attr::HLSLRawBuffer:
2152 if (ResAttrs.RawBuffer) {
2156 ResAttrs.RawBuffer =
true;
2158 case attr::HLSLIsArray:
2159 if (ResAttrs.IsArray) {
2163 ResAttrs.IsArray =
true;
2165 case attr::HLSLIsMultiSampled:
2166 if (ResAttrs.SampleCountExpr) {
2172 ResAttrs.SampleCountExpr =
2178 case attr::HLSLIsCounter:
2179 if (ResAttrs.IsCounter) {
2183 ResAttrs.IsCounter =
true;
2185 case attr::HLSLContainedType: {
2188 if (!ContainedTy.
isNull()) {
2190 ? diag::warn_duplicate_attribute_exact
2191 : diag::warn_duplicate_attribute)
2200 llvm_unreachable(
"unhandled resource attribute type");
2204 if (!HasResourceClass) {
2205 S.
Diag(AttrList.back()->getRange().getEnd(),
2206 diag::err_hlsl_missing_resource_class);
2211 Wrapped, ContainedTy, ResAttrs);
2213 if (LocInfo && ContainedTyInfo) {
2226 if (!
T->isHLSLResourceType()) {
2227 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2242 AttributeCommonInfo::AS_CXX11, 0, false ,
2247 case ParsedAttr::AT_HLSLResourceClass: {
2248 StringRef Identifier;
2250 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2255 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2256 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2257 <<
"ResourceClass" << Identifier;
2260 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2264 case ParsedAttr::AT_HLSLResourceDimension: {
2265 StringRef Identifier;
2267 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2271 llvm::dxil::ResourceDimension RD;
2272 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2274 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2275 <<
"ResourceDimension" << Identifier;
2278 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2282 case ParsedAttr::AT_HLSLIsROV:
2286 case ParsedAttr::AT_HLSLRawBuffer:
2290 case ParsedAttr::AT_HLSLIsCounter:
2294 case ParsedAttr::AT_HLSLIsArray:
2298 case ParsedAttr::AT_HLSLIsMultiSampled:
2302 case ParsedAttr::AT_HLSLContainedType: {
2304 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2310 assert(TSI &&
"no type source info for attribute argument");
2312 diag::err_incomplete_type))
2314 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2319 llvm_unreachable(
"unhandled HLSL attribute");
2322 HLSLResourcesTypeAttrs.emplace_back(A);
2328 if (!HLSLResourcesTypeAttrs.size())
2334 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2335 const HLSLAttributedResourceType *RT =
2342 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2344 HLSLResourcesTypeAttrs.clear();
2352 auto I = LocsForHLSLAttributedResources.find(RT);
2353 if (I != LocsForHLSLAttributedResources.end()) {
2354 LocInfo = I->second;
2355 LocsForHLSLAttributedResources.erase(I);
2364void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2365 const RecordType *RT) {
2373 "incomplete arrays inside user defined types are not supported");
2382 if (
const HLSLAttributedResourceType *AttrResType =
2383 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2388 Bindings.addDeclBindingInfo(VD, RC);
2389 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2395 collectResourceBindingsOnUserRecordDecl(VD, RT);
2407 bool SpecifiedSpace) {
2408 int RegTypeNum =
static_cast<int>(RegType);
2411 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2412 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2417 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2418 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2419 : ResourceClass::SRV;
2429 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2433 if (
const HLSLAttributedResourceType *AttrResType =
2434 HLSLAttributedResourceType::findHandleTypeOnResource(
2451 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2452 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2457 if (RegType == RegisterType::CBuffer)
2458 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2459 else if (RegType != RegisterType::C)
2460 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2464 if (RegType == RegisterType::C)
2465 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2467 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2477 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2485 bool RegisterTypesDetected[5] = {
false};
2486 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2489 if (HLSLResourceBindingAttr *
attr =
2490 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2493 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2494 int otherRegTypeNum =
static_cast<int>(otherRegType);
2496 diag::err_hlsl_duplicate_register_annotation)
2500 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2508 bool SpecifiedSpace) {
2513 "expecting VarDecl or HLSLBufferDecl");
2525 const uint64_t &Limit,
2528 uint64_t ArrayCount = 1) {
2533 if (StartSlot > Limit)
2537 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2540 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2541 Count = CAT->
getSize().getZExtValue();
2545 ArrayCount * Count);
2549 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2552 if (ResTy->getAttrs().ResourceClass != ResClass)
2556 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2557 if (EndSlot > Limit)
2561 StartSlot = EndSlot + 1;
2566 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2569 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2572 ResClass, Ctx, ArrayCount))
2579 ResClass, Ctx, ArrayCount))
2593 const uint64_t Limit = UINT32_MAX;
2594 if (SlotNum > Limit)
2599 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2602 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2603 uint64_t BaseSlot = SlotNum;
2611 return (BaseSlot > Limit);
2618 return (SlotNum > Limit);
2621 llvm_unreachable(
"unexpected decl type");
2625 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2627 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2628 Ty = IAT->getElementType();
2630 diag::err_incomplete_type))
2634 StringRef Slot =
"";
2635 StringRef Space =
"";
2639 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2649 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2655 SpaceLoc = Loc->
getLoc();
2658 if (Str.starts_with(
"space")) {
2660 SpaceLoc = Loc->
getLoc();
2669 std::optional<unsigned> SlotNum;
2670 unsigned SpaceNum = 0;
2673 if (!Slot.empty()) {
2675 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2678 if (RegType == RegisterType::I) {
2679 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2682 const StringRef SlotNumStr = Slot.substr(1);
2687 if (SlotNumStr.getAsInteger(10, N)) {
2688 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2696 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2705 if (!Space.starts_with(
"space")) {
2706 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2709 StringRef SpaceNumStr = Space.substr(5);
2710 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2711 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2716 if (SlotNum.has_value())
2721 HLSLResourceBindingAttr *NewAttr =
2722 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2724 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2750 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2752 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2756 Cur = AT->getModifiedType();
2767 ? attr::HLSLRowMajor
2768 : attr::HLSLColumnMajor;
2773 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2782 if (ExistingKind == AttrK) {
2783 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2785 Diag(AL.
getLoc(), diag::note_previous_attribute);
2789 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2790 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2792 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2797 if (AttrK == attr::HLSLRowMajor)
2798 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2799 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2810 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2812 if (
T.isNull() ||
T->isDependentType())
2817 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2818 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2825 switch (BuiltinID) {
2826 case Builtin::BI__builtin_hlsl_mul:
2827 case Builtin::BI__builtin_hlsl_transpose:
2835 if (!E || DestType.
isNull())
2847 if (!CallMat || CallMat->getNumRows() != DestMat->getNumRows() ||
2848 CallMat->getNumColumns() != DestMat->getNumColumns())
2897 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2901 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2902 unsigned CurrentShaderStageBit;
2907 bool ReportOnlyShaderStageIssues;
2910 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2911 static_assert(
sizeof(
unsigned) >= 4);
2912 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2913 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2914 "ShaderType is too big for this bitmap");
2917 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2918 CurrentShaderEnvironment = ShaderType;
2919 CurrentShaderStageBit = (1 << bitmapIndex);
2922 void SetUnknownShaderStageContext() {
2923 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2924 CurrentShaderStageBit = (1 << 31);
2927 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2928 return CurrentShaderEnvironment;
2931 bool InUnknownShaderStageContext()
const {
2932 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2936 void AddToScannedFunctions(
const FunctionDecl *FD) {
2937 unsigned &ScannedStages = ScannedDecls[FD];
2938 ScannedStages |= CurrentShaderStageBit;
2941 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2943 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2944 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2947 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2948 return ScannerStages & CurrentShaderStageBit;
2951 static bool NeverBeenScanned(
unsigned ScannedStages) {
2952 return ScannedStages == 0;
2956 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2957 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2959 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2960 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2963 DiagnoseHLSLAvailability(Sema &SemaRef)
2965 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2966 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2969 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2970 void RunOnFunction(
const FunctionDecl *FD);
2972 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2973 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2975 HandleFunctionOrMethodRef(FD, DRE);
2979 bool VisitMemberExpr(MemberExpr *ME)
override {
2980 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2982 HandleFunctionOrMethodRef(FD, ME);
2987void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2990 "expected DeclRefExpr or MemberExpr");
2992 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
2993 CheckDeclAvailability(
2998 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
2999 DeclsToScan.push_back(FDWithBody);
3002void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3007 llvm::Triple::EnvironmentType::Library;
3016 DeclContextsToScan.push_back(TU);
3018 while (!DeclContextsToScan.empty()) {
3019 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3020 for (
auto &D : DC->
decls()) {
3027 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3028 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3033 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3038 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3039 if (!IsLibraryShader && FD->
getName() == EntryName) {
3042 diag::err_hlsl_ambiguous_entry_point)
3044 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3050 SetShaderStageContext(ShaderAttr->getType());
3059 for (
const auto *Redecl : FD->
redecls()) {
3060 if (Redecl->isInExportDeclContext()) {
3067 SetUnknownShaderStageContext();
3074 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3081void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3082 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3083 DeclsToScan.push_back(FD);
3085 while (!DeclsToScan.empty()) {
3093 const unsigned ScannedStages = GetScannedStages(FD);
3094 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3097 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3099 AddToScannedFunctions(FD);
3104bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3105 const AvailabilityAttr *AA) {
3110 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3111 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3114 llvm::Triple::EnvironmentType AttrEnv =
3115 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3117 return CurrentEnv == AttrEnv;
3120const AvailabilityAttr *
3121DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3122 AvailabilityAttr
const *PartialMatch =
nullptr;
3126 for (
const auto *A : D->
attrs()) {
3127 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3128 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3129 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3130 StringRef TargetPlatform =
3134 if (AttrPlatform == TargetPlatform) {
3136 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3138 PartialMatch = Avail;
3142 return PartialMatch;
3147void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3148 const AvailabilityAttr *AA,
3167 if (ReportOnlyShaderStageIssues)
3173 if (InUnknownShaderStageContext())
3178 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3179 VersionTuple Introduced = AA->getIntroduced();
3188 llvm::StringRef PlatformName(
3191 llvm::StringRef CurrentEnvStr =
3192 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3194 llvm::StringRef AttrEnvStr =
3195 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3196 bool UseEnvironment = !AttrEnvStr.empty();
3198 if (EnvironmentMatches) {
3199 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3200 <<
Range << D << PlatformName << Introduced.getAsString()
3201 << UseEnvironment << CurrentEnvStr;
3203 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3207 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3208 << D << PlatformName << Introduced.getAsString()
3210 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3217 if (!DefaultCBufferDecls.empty()) {
3220 DefaultCBufferDecls);
3223 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3227 for (
const Decl *VD : DefaultCBufferDecls) {
3228 const HLSLResourceBindingAttr *RBA =
3229 VD->
getAttr<HLSLResourceBindingAttr>();
3230 if (RBA && RBA->hasRegisterSlot() &&
3231 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3238 SemaRef.Consumer.HandleTopLevelDecl(DG);
3240 diagnoseAvailabilityViolations(TU);
3249 "expected member expr to have resource record type or array of them");
3255 const Expr *NonConstIndexExpr =
nullptr;
3258 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3259 if (!NonConstIndexExpr)
3267 diag::err_hlsl_resource_member_array_access_not_constant);
3271 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3272 const Expr *IdxExpr = ASE->getIdx();
3274 NonConstIndexExpr = IdxExpr;
3276 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3277 E = SubME->getBase();
3278 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3279 E = ICE->getSubExpr();
3281 llvm_unreachable(
"unexpected expr type in resource member access");
3290 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3293 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3296 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3300 [[maybe_unused]]
bool LookupSucceeded =
3301 SemaRef.LookupQualifiedName(ConvR, RD);
3302 assert(LookupSucceeded);
3311std::optional<ExprResult>
3314 const HLSLAttributedResourceType *ResTy =
3315 HLSLAttributedResourceType::findHandleTypeOnResource(
3316 BaseType.getTypePtr());
3318 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3319 return std::nullopt;
3321 QualType TemplateType = ResTy->getContainedType();
3325 assert(NamedConversionDecl &&
3326 "Could not find conversion function for ConstantBuffer.");
3327 auto *ConversionDecl =
3330 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3342 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3345 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3352 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3355 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3380 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3395 if (!BaseType->isFloat32Type())
3396 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3397 << ArgOrdinal << 5 << 0
3407 BaseType = VT->getElementType();
3409 BaseType = MT->getElementType();
3411 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3412 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3413 << ArgOrdinal << 5 << 0
3427 if (!BaseType->isDoubleType()) {
3430 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3431 << ArgOrdinal << PassedType;
3438 unsigned ArgIndex) {
3439 auto *Arg = TheCall->
getArg(ArgIndex);
3441 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3444 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3458 << (ArgIndex + 1) << LValueTy;
3468 if (VecTy->getElementType()->isDoubleType())
3469 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3470 << ArgOrdinal << 1 << 0 << 1
3480 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3481 << ArgOrdinal << 5 << 1
3490 if (VecTy->getElementType()->isUnsignedIntegerType())
3493 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3494 << ArgOrdinal << 4 << 3 << 0
3503 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3504 << ArgOrdinal << 5 << 3
3510 unsigned ArgOrdinal,
unsigned Width) {
3513 ArgTy = VTy->getElementType();
3515 uint64_t ElementBitCount =
3517 if (ElementBitCount != Width) {
3519 diag::err_integer_incorrect_bit_count)
3520 << Width << ElementBitCount;
3531 else if (
auto *MatTyA =
3534 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3540 unsigned ArgIndex) {
3549 diag::err_typecheck_expect_scalar_or_vector)
3550 << ArgType << Scalar;
3557 QualType Scalar,
unsigned ArgIndex) {
3568 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3581 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3582 << ArgType << Scalar;
3587 unsigned ArgIndex) {
3592 if (!(ArgType->isScalarType() ||
3593 (VTy && VTy->getElementType()->isScalarType()))) {
3595 diag::err_typecheck_expect_any_scalar_or_vector)
3605 unsigned ArgIndex) {
3607 assert(ArgIndex < TheCall->getNumArgs());
3615 diag::err_typecheck_expect_any_scalar_or_vector)
3640 diag::err_typecheck_call_different_arg_types)
3659 Arg1ScalarTy = VTy->getElementType();
3663 Arg2ScalarTy = VTy->getElementType();
3666 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3667 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3677 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3679 diag::err_typecheck_vector_lengths_not_equal)
3685 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3687 diag::err_typecheck_vector_lengths_not_equal)
3699 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3702 unsigned int ActualDim = 1;
3704 ActualDim = VTy->getNumElements();
3705 IndexTy = VTy->getElementType();
3709 diag::err_typecheck_expect_int)
3715 const HLSLAttributedResourceType *ResTy =
3717 assert(ResTy &&
"Resource argument must be a resource");
3718 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3720 unsigned int ExpectedDim = 1;
3721 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3723 (ResAttrs.IsArray ? 1 : 0);
3725 if (ActualDim != ExpectedDim) {
3727 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3738 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3742 const HLSLAttributedResourceType *ResTy =
3746 diag::err_typecheck_expect_hlsl_resource)
3750 if (Check && Check(ResTy)) {
3752 diag::err_invalid_hlsl_resource_type)
3762 "expected resource handle type");
3763 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3764 auto MainAttrs = MainResType->getAttrs();
3765 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3766 MainAttrs.IsCounter =
true;
3768 MainResType->getContainedType(),
3773 QualType BaseType,
unsigned ExpectedCount,
3775 unsigned PassedCount = 1;
3777 PassedCount = VecTy->getNumElements();
3779 if (PassedCount != ExpectedCount) {
3782 S->
Diag(Loc, diag::err_typecheck_convert_incompatible)
3796 return "SampleBias";
3798 return "SampleGrad";
3800 return "SampleLevel";
3804 return "SampleCmpLevelZero";
3806 llvm_unreachable(
"Invalid SampleKind");
3816 if (!MD || !MD->getDeclName().isIdentifier())
3823 return MD->getName();
3831 return VecTy->getElementType();
3832 return ContainedType;
3840 StringRef DefaultName) {
3845 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
3872 if (SMVersion >= VersionTuple(6, 7))
3875 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
3877 << ContainedType << SMVersion.getAsString();
3882 bool IncludeArraySlice =
true) {
3885 [](
const HLSLAttributedResourceType *ResType) {
3886 return ResType->getAttrs().ResourceDimension ==
3887 llvm::dxil::ResourceDimension::Unknown;
3893 [](
const HLSLAttributedResourceType *ResType) {
3894 return ResType->getAttrs().ResourceClass !=
3895 llvm::hlsl::ResourceClass::Sampler;
3903 unsigned ExpectedDim =
3905 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
3934 unsigned NextIdx = 3;
3940 diag::err_typecheck_convert_incompatible)
3948 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3952 diag::err_typecheck_convert_incompatible)
3959 std::optional<llvm::APSInt> ComponentOpt =
3962 int64_t ComponentVal = ComponentOpt->getSExtValue();
3963 if (ComponentVal != 0) {
3966 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3967 "The component is not in the expected range.");
3969 diag::err_hlsl_gathercmp_invalid_component)
3979 const HLSLAttributedResourceType *ResourceTy =
3982 unsigned ExpectedDim =
3991 assert(ResourceTy->hasContainedType() &&
3992 "Expecting a contained type for resource with a dimension "
3994 QualType ReturnType = ResourceTy->getContainedType();
3997 IsCmp ?
"GatherCmp" :
"Gather"))
4002 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4008 ReturnType = VecTy->getElementType();
4021 [](
const HLSLAttributedResourceType *ResType) {
4022 return ResType->getAttrs().ResourceDimension ==
4023 llvm::dxil::ResourceDimension::Unknown;
4033 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4040 unsigned ResourceDim =
4042 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4052 EltTy = VTy->getElementType();
4067 TheCall->
setType(ResourceTy->getContainedType());
4077 [](
const HLSLAttributedResourceType *ResType) {
4078 return !ResType->isMultiSampled();
4087 unsigned ResourceDim =
4089 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4110 TheCall->
setType(ResourceTy->getContainedType());
4115 unsigned MinArgs, MaxArgs;
4143 const HLSLAttributedResourceType *ResourceTy =
4145 unsigned ExpectedDim =
4148 unsigned NextIdx = 3;
4157 diag::err_typecheck_convert_incompatible)
4193 diag::err_typecheck_convert_incompatible)
4199 assert(ResourceTy->hasContainedType() &&
4200 "Expecting a contained type for resource with a dimension "
4202 QualType ReturnType = ResourceTy->getContainedType();
4213 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4226 switch (BuiltinID) {
4227 case Builtin::BI__builtin_hlsl_adduint64: {
4228 if (
SemaRef.checkArgCount(TheCall, 2))
4242 if (NumElementsArg != 2 && NumElementsArg != 4) {
4244 << 1 << 64 << NumElementsArg * 32;
4258 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4259 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4266 QualType ContainedTy = ResourceTy->getContainedType();
4267 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4270 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4275 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4276 if (
SemaRef.checkArgCount(TheCall, 3) ||
4283 "expected pointer type for second argument");
4290 diag::err_invalid_use_of_array_type);
4294 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4297 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4302 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4303 if (
SemaRef.checkArgCount(TheCall, 2) ||
4305 SemaRef.getASTContext().IntTy))
4312 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4313 if (
SemaRef.checkArgCount(TheCall, 3) ||
4316 SemaRef.getASTContext().UnsignedIntTy) ||
4318 SemaRef.getASTContext().UnsignedIntTy) ||
4324 QualType ReturnType = ResourceTy->getContainedType();
4329 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4330 if (
SemaRef.checkArgCount(TheCall, 4) ||
4333 SemaRef.getASTContext().UnsignedIntTy) ||
4335 SemaRef.getASTContext().UnsignedIntTy) ||
4341 "expected pointer type for second argument");
4348 diag::err_invalid_use_of_array_type);
4354 case Builtin::BI__builtin_hlsl_resource_load_level:
4356 case Builtin::BI__builtin_hlsl_resource_load_ms:
4358 case Builtin::BI__builtin_hlsl_resource_sample:
4360 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4362 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4364 case Builtin::BI__builtin_hlsl_resource_sample_level:
4366 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4368 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4370 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4371 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4373 case Builtin::BI__builtin_hlsl_resource_gather:
4375 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4377 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4378 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4384 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4385 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4391 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4392 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4398 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4399 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4405 TheCall->
setType(CounterHandleTy);
4408 case Builtin::BI__builtin_hlsl_and:
4409 case Builtin::BI__builtin_hlsl_or: {
4410 if (
SemaRef.checkArgCount(TheCall, 2))
4424 case Builtin::BI__builtin_hlsl_all:
4425 case Builtin::BI__builtin_hlsl_any: {
4426 if (
SemaRef.checkArgCount(TheCall, 1))
4432 case Builtin::BI__builtin_hlsl_asdouble: {
4433 if (
SemaRef.checkArgCount(TheCall, 2))
4437 SemaRef.Context.UnsignedIntTy,
4442 SemaRef.Context.UnsignedIntTy,
4451 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4452 if (
SemaRef.BuiltinElementwiseTernaryMath(
4458 case Builtin::BI__builtin_hlsl_dot: {
4460 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4466 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4467 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4468 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4478 EltTy = VecTy->getElementType();
4479 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4492 case Builtin::BI__builtin_hlsl_select: {
4493 if (
SemaRef.checkArgCount(TheCall, 3))
4501 if (VTy && VTy->getElementType()->isBooleanType() &&
4506 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4507 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4508 if (
SemaRef.checkArgCount(TheCall, 1))
4514 diag::err_builtin_invalid_arg_type)
4517 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4521 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4522 case Builtin::BI__builtin_hlsl_elementwise_frac:
4523 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4524 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4525 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4526 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4527 if (
SemaRef.checkArgCount(TheCall, 1))
4532 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4536 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4537 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4538 if (
SemaRef.checkArgCount(TheCall, 1))
4543 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4548 case Builtin::BI__builtin_hlsl_mad: {
4549 if (
SemaRef.BuiltinElementwiseTernaryMath(
4555 case Builtin::BI__builtin_hlsl_mul: {
4556 if (
SemaRef.checkArgCount(TheCall, 2))
4566 return VTy->getElementType();
4568 return MTy->getElementType();
4572 QualType EltTy0 = getElemType(Ty0);
4581 if (IsVec0 && IsMat1) {
4584 }
else if (IsMat0 && IsVec1) {
4588 assert(IsMat0 && IsMat1);
4598 case Builtin::BI__builtin_elementwise_fma: {
4599 if (
SemaRef.checkArgCount(TheCall, 3) ||
4614 case Builtin::BI__builtin_hlsl_transpose: {
4615 if (
SemaRef.checkArgCount(TheCall, 1))
4624 << 1 << 3 << 0 << 0 << ArgTy;
4629 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4633 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4634 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4642 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4643 if (
SemaRef.checkArgCount(TheCall, 1))
4657 unsigned NumElts = VecTy->getNumElements();
4667 case Builtin::BI__builtin_hlsl_wave_active_max:
4668 case Builtin::BI__builtin_hlsl_wave_active_min:
4669 case Builtin::BI__builtin_hlsl_wave_active_sum:
4670 case Builtin::BI__builtin_hlsl_wave_active_product: {
4671 if (
SemaRef.checkArgCount(TheCall, 1))
4684 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4685 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4686 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4687 if (
SemaRef.checkArgCount(TheCall, 1))
4702 (VTy && VTy->getElementType()->isIntegerType()))) {
4704 diag::err_builtin_invalid_arg_type)
4705 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4713 case Builtin::BI__builtin_hlsl_interlocked_add:
4714 case Builtin::BI__builtin_hlsl_interlocked_and:
4715 case Builtin::BI__builtin_hlsl_interlocked_min:
4716 case Builtin::BI__builtin_hlsl_interlocked_or:
4717 case Builtin::BI__builtin_hlsl_interlocked_xor: {
4727 diag::err_typecheck_call_too_few_args_at_least)
4732 if (
SemaRef.checkArgCountAtMost(TheCall, 3))
4738 diag::err_builtin_invalid_arg_type)
4750 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4751 SemaRef.Context.getTypeSize(DestTy) == 64 &&
4780 case Builtin::BI__builtin_elementwise_bitreverse: {
4788 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4789 if (
SemaRef.checkArgCount(TheCall, 1))
4794 if (!(
ArgType->isScalarType())) {
4796 diag::err_typecheck_expect_any_scalar_or_vector)
4801 if (!(
ArgType->isBooleanType())) {
4803 diag::err_typecheck_expect_any_scalar_or_vector)
4810 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4811 if (
SemaRef.checkArgCount(TheCall, 2))
4819 diag::err_typecheck_convert_incompatible)
4820 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4833 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4834 if (
SemaRef.checkArgCount(TheCall, 0))
4838 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4839 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4840 if (
SemaRef.checkArgCount(TheCall, 1))
4853 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4854 case Builtin::BI__builtin_hlsl_quad_read_across_y:
4855 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
4856 if (
SemaRef.checkArgCount(TheCall, 1))
4868 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4869 if (
SemaRef.checkArgCount(TheCall, 3))
4875 SemaRef.Context.UnsignedIntTy, 1) ||
4877 SemaRef.Context.UnsignedIntTy, 2))
4885 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4886 if (
SemaRef.checkArgCount(TheCall, 1))
4893 case Builtin::BI__builtin_elementwise_acos:
4894 case Builtin::BI__builtin_elementwise_asin:
4895 case Builtin::BI__builtin_elementwise_atan:
4896 case Builtin::BI__builtin_elementwise_atan2:
4897 case Builtin::BI__builtin_elementwise_ceil:
4898 case Builtin::BI__builtin_elementwise_cos:
4899 case Builtin::BI__builtin_elementwise_cosh:
4900 case Builtin::BI__builtin_elementwise_exp:
4901 case Builtin::BI__builtin_elementwise_exp2:
4902 case Builtin::BI__builtin_elementwise_exp10:
4903 case Builtin::BI__builtin_elementwise_floor:
4904 case Builtin::BI__builtin_elementwise_fmod:
4905 case Builtin::BI__builtin_elementwise_log:
4906 case Builtin::BI__builtin_elementwise_log2:
4907 case Builtin::BI__builtin_elementwise_log10:
4908 case Builtin::BI__builtin_elementwise_pow:
4909 case Builtin::BI__builtin_elementwise_roundeven:
4910 case Builtin::BI__builtin_elementwise_sin:
4911 case Builtin::BI__builtin_elementwise_sinh:
4912 case Builtin::BI__builtin_elementwise_sqrt:
4913 case Builtin::BI__builtin_elementwise_tan:
4914 case Builtin::BI__builtin_elementwise_tanh:
4915 case Builtin::BI__builtin_elementwise_trunc: {
4921 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4922 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4923 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4924 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4925 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4930 std::optional<llvm::APSInt> Offset =
4932 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4934 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4940 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4941 if (
SemaRef.checkArgCount(TheCall, 1))
4952 ArgTy = VTy->getElementType();
4955 diag::err_builtin_invalid_arg_type)
4964 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4965 if (
SemaRef.checkArgCount(TheCall, 1))
4980 WorkList.push_back(BaseTy);
4981 while (!WorkList.empty()) {
4983 T =
T.getCanonicalType().getUnqualifiedType();
4984 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
4992 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4993 llvm::append_range(List, ElementFields);
4998 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
4999 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5002 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5003 List.insert(List.end(), MT->getNumElementsFlattened(),
5004 MT->getElementType());
5007 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5008 if (RD->isStandardLayout())
5009 RD = RD->getStandardLayoutBaseWithFields();
5013 if (RD->
isUnion() || !RD->isAggregate()) {
5019 for (
const auto *FD : RD->
fields())
5020 if (!FD->isUnnamedBitField())
5021 FieldTypes.push_back(FD->
getType());
5023 std::reverse(FieldTypes.begin(), FieldTypes.end());
5024 llvm::append_range(WorkList, FieldTypes);
5028 if (!RD->isStandardLayout()) {
5030 for (
const auto &
Base : RD->bases())
5031 FieldTypes.push_back(
Base.getType());
5032 std::reverse(FieldTypes.begin(), FieldTypes.end());
5033 llvm::append_range(WorkList, FieldTypes);
5068 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5074 int ArraySize = VT->getNumElements();
5079 QualType ElTy = VT->getElementType();
5083 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5099 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5108 return llvm::equal(T1Types, T2Types,
5110 return SemaRef.IsLayoutCompatible(LHS, RHS);
5119 bool HadError =
false;
5121 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5129 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5130 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5131 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5132 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5134 if (NSpellingIdx != OSpellingIdx) {
5136 diag::err_hlsl_param_qualifier_mismatch)
5137 << NDAttr << NewParam;
5153 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5168 llvm_unreachable(
"HLSL doesn't support pointers.");
5171 llvm_unreachable(
"HLSL doesn't support complex types.");
5173 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5175 llvm_unreachable(
"Should have returned before this");
5185 llvm_unreachable(
"HLSL doesn't support complex types.");
5187 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5192 llvm_unreachable(
"HLSL doesn't support pointers.");
5194 llvm_unreachable(
"Should have returned before this");
5200 llvm_unreachable(
"HLSL doesn't support pointers.");
5203 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5207 llvm_unreachable(
"HLSL doesn't support complex types.");
5210 llvm_unreachable(
"Unhandled scalar cast");
5231 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5237 SrcTy = SrcMatTy->getElementType();
5242 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5243 if (DestTypes[I]->isUnionType())
5275 if (SrcTypes.size() < DestTypes.size())
5278 unsigned SrcSize = SrcTypes.size();
5279 unsigned DstSize = DestTypes.size();
5281 for (I = 0; I < DstSize && I < SrcSize; I++) {
5282 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5290 for (; I < SrcSize; I++) {
5291 if (SrcTypes[I]->isUnionType())
5298 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5299 "We should not get here without a parameter modifier expression");
5300 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5307 << Arg << (IsInOut ? 1 : 0);
5313 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5320 << Arg << (IsInOut ? 1 : 0);
5332 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5338 auto *OpV =
new (Ctx)
5344 tok::equal, ArgOpV, OpV);
5360 "Pointer and reference types cannot be inout or out parameters");
5361 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5377 for (
const auto *FD : RD->
fields()) {
5381 assert(RD->getNumBases() <= 1 &&
5382 "HLSL doesn't support multiple inheritance");
5383 return RD->getNumBases()
5388 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5389 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5401 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5406 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5412 if (
Decl->getType().hasAddressSpace())
5415 if (
Decl->getType()->isDependentType())
5427 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5441 llvm::Triple::Vulkan;
5442 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5443 if (HasDeclaredAPushConstant)
5449 HasDeclaredAPushConstant =
true;
5476class StructBindingContext {
5479 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5480 unsigned RegBindingOffset[4];
5483 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5484 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5485 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5486 static_cast<unsigned>(RegisterType::Sampler) == 3,
5487 "unexpected register type values");
5490 HLSLVkBindingAttr *VkBindingAttr;
5491 unsigned VkBindingOffset;
5496 StructBindingContext(
VarDecl *VD) {
5497 for (
unsigned i = 0; i < 4; ++i) {
5498 RegBindingsAttrs[i] =
nullptr;
5499 RegBindingOffset[i] = 0;
5501 VkBindingAttr =
nullptr;
5502 VkBindingOffset = 0;
5508 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5510 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5513 RegBindingsAttrs[RegTypeIdx] = RBA;
5518 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5519 VkBindingAttr = VBA;
5526 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5527 unsigned Range,
bool HasCounter) {
5528 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5530 if (VkBindingAttr) {
5531 unsigned Offset = VkBindingOffset;
5532 VkBindingOffset +=
Range;
5533 return HLSLVkBindingAttr::CreateImplicit(
5534 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5535 VkBindingAttr->getRange());
5538 HLSLResourceBindingAttr *RBA =
5539 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5540 HLSLResourceBindingAttr *NewAttr =
nullptr;
5542 if (RBA && RBA->hasRegisterSlot()) {
5545 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5546 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5548 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5549 StringRef NewSlotNumberStr =
5551 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5552 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5553 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5557 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5558 NewAttr->setBinding(RegType, std::nullopt,
5559 RBA ? RBA->getSpaceNumber() : 0);
5563 NewAttr->setImplicitCounterBindingOrderID(
5572static void createGlobalResourceDeclForStruct(
5574 QualType ResTy, StructBindingContext &BindingCtx) {
5576 "expected resource type or array of resources");
5587 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5588 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5593 const HLSLAttributedResourceType *ResHandleTy =
5594 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5598 Attr *BindingAttr = BindingCtx.createBindingAttr(
5600 ResDecl->
addAttr(BindingAttr);
5601 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5610 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5617static void handleArrayOfStructWithResources(
5619 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5624static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5626 EmbeddedResourceNameBuilder &NameBuilder,
5627 StructBindingContext &BindingCtx) {
5630 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5637 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5651 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5654 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5656 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5658 "resource arrays should have been already handled");
5659 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5668handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5670 EmbeddedResourceNameBuilder &NameBuilder,
5671 StructBindingContext &BindingCtx) {
5679 if (!SubCAT && !ElementRD)
5682 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5685 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5688 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5701void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5702 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5703 StructBindingContext BindingCtx(VD);
5707 "Expected non-resource struct or array type");
5710 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5714 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5715 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5723 if (
SemaRef.RequireCompleteType(
5726 diag::err_typecheck_decl_incomplete_type)) {
5740 DefaultCBufferDecls.push_back(VD);
5745 collectResourceBindingsOnVarDecl(VD);
5747 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5759 processExplicitBindingsOnDecl(VD);
5797 handleGlobalStructOrArrayOfWithResources(VD);
5801 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5810 "expected resource record type");
5826 const char *CreateMethodName;
5828 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5829 :
"__createFromBinding";
5831 CreateMethodName = HasCounter
5832 ?
"__createFromImplicitBindingWithImplicitCounter"
5833 :
"__createFromImplicitBinding";
5838 if (!CreateMethod) {
5843 "create method lookup should always succeed for built-in resource "
5852 Args.push_back(RegSlot);
5860 Args.push_back(OrderId);
5866 Args.push_back(Space);
5870 Args.push_back(RangeSize);
5874 Args.push_back(Index);
5876 StringRef VarName = VD->
getName();
5884 Args.push_back(NameCast);
5892 Args.push_back(CounterId);
5915 SemaRef.CheckCompleteVariableDeclaration(VD);
5921 "expected array of resource records");
5942 lookupMethod(
SemaRef, ResourceDecl,
5943 HasCounter ?
"__createFromBindingWithImplicitCounter"
5944 :
"__createFromBinding",
5948 CreateMethod = lookupMethod(
5950 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5951 :
"__createFromImplicitBinding",
5994std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5995 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5996 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5997 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5998 if (!TrueInfo || !FalseInfo)
5999 return std::nullopt;
6000 if (*TrueInfo != *FalseInfo)
6001 return std::nullopt;
6005 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6014 if (
const auto *AttrResType =
6015 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6017 return Bindings.getDeclBindingInfo(VD, RC);
6024void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6025 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6028 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6033 if (*ExprBinding ==
nullptr)
6036 auto PrevBinding = Assigns.find(VD);
6037 if (PrevBinding == Assigns.end()) {
6039 Assigns.insert({VD, *ExprBinding});
6044 if (*ExprBinding != PrevBinding->second) {
6046 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6048 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6059 "expected LHS to be a resource record or array of resource records");
6060 if (Opc != BO_Assign)
6065 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6073 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6078 trackLocalResource(VD, RHSExpr);
6095void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6097 "expected global variable that contains HLSL resource");
6100 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6101 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6102 ? ResourceClass::CBuffer
6103 : ResourceClass::SRV);
6116 if (
const HLSLAttributedResourceType *AttrResType =
6117 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6118 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6123 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6124 collectResourceBindingsOnUserRecordDecl(VD, RT);
6130void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6133 bool HasBinding =
false;
6134 for (Attr *A : VD->
attrs()) {
6137 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6138 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6141 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6142 if (!RBA || !RBA->hasRegisterSlot())
6147 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6148 "never have an attribute created");
6150 if (RT == RegisterType::C) {
6151 if (Bindings.hasBindingInfoForDecl(VD))
6153 diag::warn_hlsl_user_defined_type_missing_member)
6154 <<
static_cast<int>(RT);
6162 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6167 diag::warn_hlsl_user_defined_type_missing_member)
6168 <<
static_cast<int>(RT);
6176class InitListTransformer {
6180 QualType *DstIt =
nullptr;
6181 Expr **ArgIt =
nullptr;
6187 bool castInitializer(Expr *E) {
6188 assert(DstIt &&
"This should always be something!");
6189 if (DstIt == DestTypes.end()) {
6191 ArgExprs.push_back(E);
6196 DstIt = DestTypes.begin();
6199 Ctx, *DstIt,
false);
6204 ArgExprs.push_back(
Init);
6209 bool buildInitializerListImpl(Expr *E) {
6211 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6212 for (
auto *SubInit :
Init->inits())
6213 if (!buildInitializerListImpl(SubInit))
6223 return castInitializer(E);
6237 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6242 for (uint64_t I = 0; I <
Size; ++I) {
6244 SizeTy, SourceLocation());
6250 if (!castInitializer(ElExpr.
get()))
6255 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6256 unsigned Rows = MTy->getNumRows();
6257 unsigned Cols = MTy->getNumColumns();
6258 QualType ElemTy = MTy->getElementType();
6260 for (
unsigned R = 0;
R < Rows; ++
R) {
6261 for (
unsigned C = 0;
C < Cols; ++
C) {
6274 if (!castInitializer(ElExpr.
get()))
6282 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6286 for (uint64_t I = 0; I <
Size; ++I) {
6288 SizeTy, SourceLocation());
6293 if (!buildInitializerListImpl(ElExpr.
get()))
6300 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6301 RecordDecls.push_back(RD);
6302 while (RecordDecls.back()->getNumBases()) {
6303 CXXRecordDecl *D = RecordDecls.back();
6305 "HLSL doesn't support multiple inheritance");
6306 RecordDecls.push_back(
6309 while (!RecordDecls.empty()) {
6310 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6311 for (
auto *FD : RD->
fields()) {
6312 if (FD->isUnnamedBitField())
6320 if (!buildInitializerListImpl(Res.
get()))
6328 Expr *generateInitListsImpl(QualType Ty) {
6330 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6335 llvm::SmallVector<Expr *>
Inits;
6340 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6341 ElTy = ATy->getElementType();
6342 Size = ATy->getNumElements();
6343 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6344 ElTy = CMTy->getElementType();
6345 Size = CMTy->getNumElementsFlattened();
6348 ElTy = VTy->getElementType();
6349 Size = VTy->getZExtSize();
6351 for (uint64_t I = 0; I <
Size; ++I)
6352 Inits.push_back(generateInitListsImpl(ElTy));
6355 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6356 RecordDecls.push_back(RD);
6357 while (RecordDecls.back()->getNumBases()) {
6358 CXXRecordDecl *D = RecordDecls.back();
6360 "HLSL doesn't support multiple inheritance");
6361 RecordDecls.push_back(
6364 while (!RecordDecls.empty()) {
6365 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6366 for (
auto *FD : RD->
fields())
6367 if (!FD->isUnnamedBitField())
6372 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6373 Inits.back()->getEndLoc(),
false);
6374 NewInit->setType(Ty);
6379 llvm::SmallVector<QualType, 16> DestTypes;
6380 llvm::SmallVector<Expr *, 16> ArgExprs;
6381 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6382 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6383 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6384 InitTy = Entity.
getType().getNonReferenceType();
6394 DstIt = DestTypes.begin();
6397 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6399 Expr *generateInitLists() {
6400 assert(!ArgExprs.empty() &&
6401 "Call buildInitializerList to generate argument expressions.");
6402 ArgIt = ArgExprs.begin();
6404 return generateInitListsImpl(InitTy);
6405 llvm::SmallVector<Expr *>
Inits;
6406 while (ArgIt != ArgExprs.end())
6407 Inits.push_back(generateInitListsImpl(InitTy));
6410 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6411 Inits.back()->getEndLoc(),
false);
6412 llvm::APInt ArySize(64,
Inits.size());
6414 ArraySizeModifier::Normal, 0));
6426 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6433 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6437 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6457 if (
Init->getType()->isScalarType())
6460 InitListTransformer ILT(
SemaRef, Entity);
6462 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6470 Init->setInit(I, E);
6472 if (!ILT.buildInitializerList(E))
6475 size_t ExpectedSize = ILT.DestTypes.size();
6476 size_t ActualSize = ILT.ArgExprs.size();
6477 if (ExpectedSize == 0 && ActualSize == 0)
6484 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6486 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6487 << (int)(ExpectedSize < ActualSize) << InitTy
6488 << ExpectedSize << ActualSize;
6498 assert(ExpectedSize > 0 &&
6499 "The expected size of an incomplete array type must be at least 1.");
6501 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6509 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6510 if (ExpectedSize != ActualSize) {
6511 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6512 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6513 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6520 Init->resizeInits(Ctx, NewInit->getNumInits());
6521 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6522 Init->updateInit(Ctx, I, NewInit->getInit(I));
6530 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6540 StringRef AccessorName = CompName->
getName();
6541 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6543 unsigned Rows = MT->getNumRows();
6544 unsigned Cols = MT->getNumColumns();
6545 bool IsZeroBasedAccessor =
false;
6546 unsigned ChunkLen = 0;
6547 if (AccessorName.size() < 2)
6549 "length 4 for zero based: \'_mRC\' or "
6550 "length 3 for one-based: \'_RC\' accessor",
6553 if (AccessorName[0] ==
'_') {
6554 if (AccessorName[1] ==
'm') {
6555 IsZeroBasedAccessor =
true;
6562 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6565 if (AccessorName.size() % ChunkLen != 0) {
6566 const llvm::StringRef
Expected = IsZeroBasedAccessor
6567 ?
"zero based: '_mRC' accessor"
6568 :
"one-based: '_RC' accessor";
6573 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6574 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6575 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6577 bool HasRepeated =
false;
6579 unsigned NumComponents = 0;
6580 const char *Begin = AccessorName.data();
6582 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6583 const char *Chunk = Begin + I;
6584 char RowChar = 0, ColChar = 0;
6585 if (IsZeroBasedAccessor) {
6587 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6588 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6590 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6597 if (Chunk[0] !=
'_')
6599 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6606 bool IsDigitsError =
false;
6608 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6612 IsDigitsError =
true;
6616 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6620 IsDigitsError =
true;
6625 unsigned Row = RowChar -
'0';
6626 unsigned Col = ColChar -
'0';
6628 bool HasIndexingError =
false;
6629 if (IsZeroBasedAccessor) {
6631 if (!isZeroBasedIndex(Row)) {
6632 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6634 HasIndexingError =
true;
6636 if (!isZeroBasedIndex(Col)) {
6637 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6639 HasIndexingError =
true;
6643 if (!isOneBasedIndex(Row)) {
6644 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6646 HasIndexingError =
true;
6648 if (!isOneBasedIndex(Col)) {
6649 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6651 HasIndexingError =
true;
6658 if (HasIndexingError)
6664 bool HasBoundsError =
false;
6666 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6668 HasBoundsError =
true;
6671 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6673 HasBoundsError =
true;
6678 unsigned FlatIndex = Row * Cols + Col;
6679 if (Seen[FlatIndex])
6681 Seen[FlatIndex] =
true;
6684 if (NumComponents == 0 || NumComponents > 4) {
6685 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6690 QualType ElemTy = MT->getElementType();
6691 if (NumComponents == 1)
6697 for (Sema::ExtVectorDeclsType::iterator
6701 if ((*I)->getUnderlyingType() == VT)
6712 trackLocalResource(VDecl,
Init);
6714 const HLSLVkConstantIdAttr *ConstIdAttr =
6715 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6722 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
6732 int ConstantID = ConstIdAttr->getId();
6733 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6735 ConstIdAttr->getLocation());
6739 if (
C->getType()->getCanonicalTypeUnqualified() !=
6743 Context.getTrivialTypeSourceInfo(
6744 Init->getType(),
Init->getExprLoc()),
6763 if (!Params || Params->
size() != 1)
6776 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6777 if (TTP->hasDefaultArgument()) {
6778 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6781 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6782 if (NTTP->hasDefaultArgument()) {
6783 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6786 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6787 if (TTPD->hasDefaultArgument()) {
6788 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6795 return SemaRef.CheckTemplateIdType(
6797 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 CheckIntegerElementTypeShaderModel(Sema &S, CallExpr *TheCall, QualType ContainedType, SampleKind Kind)
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 CheckNoDoubleElementType(Sema &S, CallExpr *TheCall, QualType ContainedType, StringRef DefaultName)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static const Type * createHostLayoutType(Sema &S, const Type *Ty)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool CheckArgAddrSpaceOneOf(Sema *S, CallExpr *TheCall, unsigned ArgIndex, ArrayRef< LangAS > AllowedSpaces)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static StringRef getSampleMethodName(SampleKind Kind)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall)
static RegisterType getRegisterType(ResourceClass RC)
static bool ValidateRegisterNumber(uint64_t SlotNum, Decl *TheDecl, ASTContext &Ctx, RegisterType RegTy)
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
static bool 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 QualType getTypedResourceElementType(QualType ContainedType)
static bool findExistingMatrixLayoutMarker(QualType T, attr::Kind &ExistingKind)
Walks the existing AttributedType sugar of T looking for a previously applied HLSLRowMajor/HLSLColumn...
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckWavePrefix(Sema *S, CallExpr *TheCall)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static LangAS getLangASFromResourceClass(ResourceClass RC)
static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall, bool IncludeArraySlice=true)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static const Type * getHostLayoutFieldType(QualType QT)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool isLayoutAdaptingMatrixBuiltin(unsigned BuiltinID)
static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind)
static bool CheckScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckFloatRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyDoubleRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
static StringRef getCurrentResourceMethodName(Sema &S, StringRef DefaultName)
static bool IsDefaultBufferConstantDecl(const ASTContext &Ctx, VarDecl *VD)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool CheckGatherBuiltin(Sema &S, CallExpr *TheCall, bool IsCmp)
static bool isValidWaveSizeValue(unsigned Value)
static bool isResourceRecordTypeOrArrayOf(QualType Ty)
static bool CheckLoadMSBuiltin(Sema &S, CallExpr *TheCall)
static bool AccumulateHLSLResourceSlots(QualType Ty, uint64_t &StartSlot, const uint64_t &Limit, const ResourceClass ResClass, ASTContext &Ctx, uint64_t ArrayCount=1)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
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.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
ExtVectorType - Extended vector type.
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
DeclarationNameInfo getNameInfo() const
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
void addLayoutStruct(CXXRecordDecl *LS)
void setHasValidPackoffset(bool PO)
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
buffer_decl_range buffer_decls() const
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
iterator begin(ExternalSemaSource *source, bool LocalOnly=false)
Represents the results of name lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Represents a matrix type, as defined in the Matrix Types clang extensions.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
NamedDecl * getUnderlyingDecl()
Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
A C++ nested-name-specifier augmented with source location information.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
bool hasParsedType() const
void setInvalid(bool b=true) const
const ParsedType & getTypeArg() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
AttributeCommonInfo::Kind getKind() const
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinitionOrSelf() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
ASTContext & getASTContext() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
void handleVkLocationAttr(Decl *D, const ParsedAttr &AL)
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
void handleSemanticAttr(Decl *D, const ParsedAttr &AL)
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
uint32_t getNextImplicitBindingOrderID()
void CheckEntryPoint(FunctionDecl *FD)
void handleVkExtBuiltinOutputAttr(Decl *D, const ParsedAttr &AL)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
void propagateContextualMatrixLayout(Expr *E, QualType DestType)
T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)
bool initGlobalResourceDecl(VarDecl *VD)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
bool initGlobalResourceArrayDecl(VarDecl *VD)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
Attr * buildMatrixLayoutTypeAttr(QualType T, const ParsedAttr &AL)
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)
std::optional< ExprResult > tryPerformConstantBufferConversion(Expr *BaseExpr)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
bool diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T, SourceLocation Loc)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
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.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult TemporaryMaterializationConversion(Expr *E)
If E is a prvalue denoting an unmaterialized temporary, materialize it as an xvalue.
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExternalSemaSource * getExternalSource() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool 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 hasResourceOffset(llvm::dxil::ResourceDimension Dim)
bool hasCounterHandle(const CXXRecordDecl *RD)
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
@ Template
We are parsing a template declaration.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr, Expr *SampleCountExpr=nullptr)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
__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