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"
57using llvm::hlsl::IOType;
58using llvm::hlsl::SemanticStageInfo;
67 case ResourceClass::SRV:
68 return RegisterType::SRV;
69 case ResourceClass::UAV:
70 return RegisterType::UAV;
71 case ResourceClass::CBuffer:
72 return RegisterType::CBuffer;
73 case ResourceClass::Sampler:
74 return RegisterType::Sampler;
76 llvm_unreachable(
"unexpected ResourceClass value");
85 case ResourceClass::SRV:
86 case ResourceClass::UAV:
88 case ResourceClass::CBuffer:
90 case ResourceClass::Sampler:
93 llvm_unreachable(
"unexpected ResourceClass value");
99 assert(RT !=
nullptr);
103 *RT = RegisterType::SRV;
107 *RT = RegisterType::UAV;
111 *RT = RegisterType::CBuffer;
115 *RT = RegisterType::Sampler;
119 *RT = RegisterType::C;
123 *RT = RegisterType::I;
132 case RegisterType::SRV:
134 case RegisterType::UAV:
136 case RegisterType::CBuffer:
138 case RegisterType::Sampler:
140 case RegisterType::C:
142 case RegisterType::I:
145 llvm_unreachable(
"unexpected RegisterType value");
150 case RegisterType::SRV:
151 return ResourceClass::SRV;
152 case RegisterType::UAV:
153 return ResourceClass::UAV;
154 case RegisterType::CBuffer:
155 return ResourceClass::CBuffer;
156 case RegisterType::Sampler:
157 return ResourceClass::Sampler;
158 case RegisterType::C:
159 case RegisterType::I:
163 llvm_unreachable(
"unexpected RegisterType value");
167 const auto *BT = dyn_cast<BuiltinType>(
Type);
171 return Builtin::BI__builtin_get_spirv_spec_constant_int;
174 switch (BT->getKind()) {
175 case BuiltinType::Bool:
176 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
177 case BuiltinType::Short:
178 return Builtin::BI__builtin_get_spirv_spec_constant_short;
179 case BuiltinType::Int:
180 return Builtin::BI__builtin_get_spirv_spec_constant_int;
181 case BuiltinType::LongLong:
182 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
183 case BuiltinType::UShort:
184 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
185 case BuiltinType::UInt:
186 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
187 case BuiltinType::ULongLong:
188 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
189 case BuiltinType::Half:
190 return Builtin::BI__builtin_get_spirv_spec_constant_half;
191 case BuiltinType::Float:
192 return Builtin::BI__builtin_get_spirv_spec_constant_float;
193 case BuiltinType::Double:
194 return Builtin::BI__builtin_get_spirv_spec_constant_double;
203 llvm::raw_svector_ostream OS(Buffer);
210 ResourceClass ResClass) {
212 "DeclBindingInfo already added");
218 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
219 return &BindingsList.emplace_back(VD, ResClass);
223 ResourceClass ResClass) {
224 auto Entry = DeclToBindingListIndex.find(VD);
225 if (Entry != DeclToBindingListIndex.end()) {
226 for (
unsigned Index = Entry->getSecond();
227 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
229 if (BindingsList[Index].ResClass == ResClass)
230 return &BindingsList[Index];
237 return DeclToBindingListIndex.contains(VD);
249 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
252 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
253 : llvm::hlsl::ResourceClass::SRV;
265 if (
T->isArrayType() ||
T->isStructureType() ||
T->isConstantMatrixType())
272 assert(Context.getTypeSize(
T) <= 64 &&
273 "Scalar bit widths larger than 64 not supported");
276 return Context.getTypeSize(
T) / 8;
283 constexpr unsigned CBufferAlign = 16;
284 if (
const auto *RD =
T->getAsRecordDecl()) {
286 for (
const FieldDecl *Field : RD->fields()) {
293 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
294 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
295 FieldAlign = CBufferAlign;
298 Size = llvm::alignTo(Size, FieldAlign);
305 unsigned ElementCount = AT->getSize().getZExtValue();
306 if (ElementCount == 0)
309 unsigned ElementSize =
311 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
312 return AlignedElementSize * (ElementCount - 1) + ElementSize;
316 unsigned ElementCount = VT->getNumElements();
317 unsigned ElementSize =
319 return ElementSize * ElementCount;
322 return Context.getTypeSize(
T) / 8;
333 bool HasPackOffset =
false;
334 bool HasNonPackOffset =
false;
336 VarDecl *Var = dyn_cast<VarDecl>(Field);
339 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
340 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
341 HasPackOffset =
true;
343 HasNonPackOffset =
true;
350 if (HasNonPackOffset)
357 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
358 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
359 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
360 return LHS.second->getOffsetInBytes() <
361 RHS.second->getOffsetInBytes();
363 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
364 VarDecl *Var = PackOffsetVec[i].first;
365 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
367 unsigned Begin =
Attr->getOffsetInBytes();
368 unsigned End = Begin + Size;
369 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
370 if (End > NextBegin) {
371 VarDecl *NextVar = PackOffsetVec[i + 1].first;
383 CAT = dyn_cast<ConstantArrayType>(
385 return CAT !=
nullptr;
396static const HLSLAttributedResourceType *
399 "expected array of resource records");
401 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
403 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
406static const HLSLAttributedResourceType *
420 return RD->isEmpty();
449 Base.getType()->castAsCXXRecordDecl()))
460 assert(RD ==
nullptr &&
461 "there should be at most 1 record by a given name in a scope");
478 Name.append(NameBaseII->
getName());
485 size_t NameLength = Name.size();
494 Name.append(llvm::Twine(suffix).str());
495 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
502 Name.truncate(NameLength);
517 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
519 S, CAT->getElementType()->getUnqualifiedDesugaredType());
524 CAT->getSizeModifier(),
525 CAT->getIndexTypeCVRQualifiers())
574 "struct is already HLSL buffer compatible");
588 LS->
addAttr(PackedAttr::CreateImplicit(AST));
592 if (
unsigned NumBases = StructDecl->
getNumBases()) {
593 assert(NumBases == 1 &&
"HLSL supports only one base type");
643 LS->
addAttr(PackedAttr::CreateImplicit(AST));
648 VarDecl *VD = dyn_cast<VarDecl>(D);
664 "host layout field for $Globals decl failed to be created");
683 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
684 Attr->setBinding(RT, std::nullopt, 0);
685 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
692 BufDecl->setRBraceLoc(RBrace);
709 BufDecl->isCBuffer() ? RegisterType::CBuffer
719 int X,
int Y,
int Z) {
720 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
721 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
722 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
723 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
733 int Min,
int Max,
int Preferred,
734 int SpelledArgsCount) {
735 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
736 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
737 WS->getPreferred() != Preferred ||
738 WS->getSpelledArgsCount() != SpelledArgsCount) {
739 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
740 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
746 Result->setSpelledArgsCount(SpelledArgsCount);
750HLSLVkConstantIdAttr *
756 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
764 Diag(VD->getLocation(), diag::err_specialization_const);
768 if (!VD->getType().isConstQualified()) {
769 Diag(VD->getLocation(), diag::err_specialization_const);
773 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
774 if (CI->getId() != Id) {
775 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
776 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
781 HLSLVkConstantIdAttr *
Result =
788 llvm::Triple::EnvironmentType ShaderType) {
789 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
790 if (NT->getType() != ShaderType) {
791 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
792 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
796 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
799HLSLParamModifierAttr *
801 HLSLParamModifierAttr::Spelling Spelling) {
804 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
805 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
806 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
807 D->
dropAttr<HLSLParamModifierAttr>();
809 return HLSLParamModifierAttr::Create(
811 HLSLParamModifierAttr::Keyword_inout);
813 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
814 Diag(PA->getLocation(), diag::note_conflicting_attribute);
840 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
841 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
844 if (Shader->getType() != Env) {
845 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
857 case llvm::Triple::UnknownEnvironment:
858 case llvm::Triple::Library:
860 case llvm::Triple::RootSignature:
861 llvm_unreachable(
"rootsig environment has no functions");
863 llvm_unreachable(
"Unhandled environment in triple");
869 HLSLAppliedSemanticAttr *Semantic,
874 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
875 assert(ShaderAttr &&
"Entry point has no shader attribute");
876 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
877 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
880 case SemanticKind::Position:
884 return (ST == llvm::Triple::Vertex && !IsInput) ||
885 (ST == llvm::Triple::Pixel && IsInput);
886 case SemanticKind::VertexID:
893bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
896 SemanticInfo &ActiveSemantic,
897 SemaHLSL::SemanticContext &SC) {
898 if (ActiveSemantic.Semantic ==
nullptr) {
899 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
900 if (ActiveSemantic.Semantic)
901 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
904 if (!ActiveSemantic.Semantic) {
910 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
911 ActiveSemantic.Semantic->getAttrName()->getName(),
912 ActiveSemantic.Index.value_or(0));
916 checkSemanticAnnotation(FD, D, A, SC);
917 OutputDecl->addAttr(A);
919 unsigned Location = ActiveSemantic.Index.value_or(0);
922 any(SC.CurrentIOType & IOType::In))) {
923 bool HasVkLocation =
false;
924 if (
auto *A = D->getAttr<HLSLVkLocationAttr>()) {
925 HasVkLocation = true;
926 Location = A->getLocation();
929 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
930 Diag(D->getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
933 SC.UsesExplicitVkLocations = HasVkLocation;
936 const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->getType());
937 unsigned ElementCount = AT ? AT->
getZExtSize() : 1;
938 ActiveSemantic.Index = Location + ElementCount;
940 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
941 for (
unsigned I = 0; I < ElementCount; ++I) {
942 Twine VariableName = BaseName.concat(Twine(Location + I));
944 auto [_, Inserted] = SC.ActiveSemantics.insert(VariableName.str());
946 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
947 << VariableName.str();
958 SemanticInfo &ActiveSemantic,
959 SemaHLSL::SemanticContext &SC) {
960 if (ActiveSemantic.Semantic ==
nullptr) {
961 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
962 if (ActiveSemantic.Semantic)
963 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
969 const RecordType *RT = dyn_cast<RecordType>(
T);
971 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
974 const RecordDecl *RD = RT->getDecl();
975 for (FieldDecl *Field : RD->
fields()) {
976 SemanticInfo Info = ActiveSemantic;
977 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
978 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
981 if (ActiveSemantic.Semantic)
982 ActiveSemantic = Info;
989 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
990 assert(ShaderAttr &&
"Entry point has no shader attribute");
991 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
995 case llvm::Triple::Pixel:
996 case llvm::Triple::Vertex:
997 case llvm::Triple::Geometry:
998 case llvm::Triple::Hull:
999 case llvm::Triple::Domain:
1000 case llvm::Triple::RayGeneration:
1001 case llvm::Triple::Intersection:
1002 case llvm::Triple::AnyHit:
1003 case llvm::Triple::ClosestHit:
1004 case llvm::Triple::Miss:
1005 case llvm::Triple::Callable:
1006 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1007 diagnoseAttrStageMismatch(NT, ST,
1008 {llvm::Triple::Compute,
1009 llvm::Triple::Amplification,
1010 llvm::Triple::Mesh});
1013 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1014 diagnoseAttrStageMismatch(WS, ST,
1015 {llvm::Triple::Compute,
1016 llvm::Triple::Amplification,
1017 llvm::Triple::Mesh});
1022 case llvm::Triple::Compute:
1023 case llvm::Triple::Amplification:
1024 case llvm::Triple::Mesh:
1025 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1027 << llvm::Triple::getEnvironmentTypeName(ST);
1030 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1032 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1033 }
else if (Ver < VersionTuple(6, 6)) {
1034 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1037 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1040 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1041 << WS << WS->getSpelledArgsCount() <<
"6.8";
1046 case llvm::Triple::RootSignature:
1047 llvm_unreachable(
"rootsig environment has no function entry point");
1049 llvm_unreachable(
"Unhandled environment in triple");
1052 SemaHLSL::SemanticContext InputSC = {};
1053 InputSC.CurrentIOType = IOType::In;
1054 SemaHLSL::SemanticContext OutputSC = {};
1055 OutputSC.CurrentIOType = IOType::Out;
1058 SemanticInfo ActiveSemantic;
1059 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1060 if (ActiveSemantic.Semantic)
1061 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1065 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1066 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1068 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1069 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1074 SemanticInfo ActiveSemantic;
1075 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1076 if (ActiveSemantic.Semantic)
1077 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1079 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1082void SemaHLSL::checkSemanticAnnotation(
1084 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC) {
1085 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1086 assert(ShaderAttr &&
"Entry point has no shader attribute");
1087 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1090 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1091 llvm::hlsl::SemanticInterpretation Interpretation =
1092 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1093 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
1094 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1097 case SemanticKind::DispatchThreadID:
1098 case SemanticKind::GroupID:
1099 case SemanticKind::GroupIndex:
1100 case SemanticKind::GroupThreadID:
1101 if (SemanticAttr->getSemanticIndex() != 0) {
1102 std::string PrettyName =
1103 "'" + SemanticAttr->getSemanticName().str() +
"'";
1104 Diag(SemanticAttr->getLoc(),
1105 diag::err_hlsl_semantic_indexing_not_supported)
1114void SemaHLSL::diagnoseAttrStageMismatch(
1115 const Attr *A, llvm::Triple::EnvironmentType Stage,
1116 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1117 SmallVector<StringRef, 8> StageStrings;
1118 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1119 [](llvm::Triple::EnvironmentType ST) {
1121 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1123 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1124 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1125 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1128void SemaHLSL::diagnoseSemanticStageMismatch(
1129 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1132 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1133 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1134 return Info.Stage == Stage;
1137 StringRef CurrentIOTypeName =
"patch constants or primitives";
1138 if (
any(CurrentIOType & IOType::In))
1139 CurrentIOTypeName =
"inputs";
1140 else if (
any(CurrentIOType & IOType::Out))
1141 CurrentIOTypeName =
"outputs";
1144 if (It == Allowed.end()) {
1145 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1146 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1147 << CurrentIOTypeName;
1151 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1152 if (!(AllowedIOTypes & CurrentIOType)) {
1153 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1154 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1155 << CurrentIOTypeName;
1160template <CastKind Kind>
1163 Ty = VTy->getElementType();
1168template <CastKind Kind>
1180 if (LHSFloat && RHSFloat) {
1208 if (LHSSigned == RHSSigned) {
1209 if (IsCompAssign || IntOrder >= 0)
1217 if (IntOrder != (LHSSigned ? 1 : -1)) {
1218 if (IsCompAssign || RHSSigned)
1226 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1227 if (IsCompAssign || LHSSigned)
1243 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1244 QualType NewTy = Ctx.getExtVectorType(
1254 return CK_FloatingCast;
1256 return CK_IntegralCast;
1258 return CK_IntegralToFloating;
1260 return CK_FloatingToIntegral;
1266 bool IsCompAssign) {
1273 if (!LVecTy && IsCompAssign) {
1275 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1277 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1279 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1284 unsigned EndSz = std::numeric_limits<unsigned>::max();
1287 LSz = EndSz = LVecTy->getNumElements();
1290 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1291 "one of the above should have had a value");
1295 if (IsCompAssign && LSz != EndSz) {
1297 diag::err_hlsl_vector_compound_assignment_truncation)
1298 << LHSType << RHSType;
1304 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1309 if (!IsCompAssign && !LVecTy)
1313 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1314 return Ctx.getCommonSugaredType(LHSType, RHSType);
1322 LElTy, RElTy, IsCompAssign);
1325 "HLSL Vectors can only contain integer or floating point types");
1327 LElTy, RElTy, IsCompAssign);
1332 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1333 "Called with non-logical operator");
1335 llvm::raw_svector_ostream OS(Buff);
1337 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1338 OS << NewFnName <<
"(";
1348std::pair<IdentifierInfo *, bool>
1351 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1358 return {DeclIdent,
Found};
1369 for (
auto &RootSigElement : RootElements)
1370 Elements.push_back(RootSigElement.getElement());
1374 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1376 SignatureDecl->setImplicit();
1382 if (RootSigOverrideIdent) {
1385 if (
SemaRef.LookupQualifiedName(R, DC))
1386 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1394struct PerVisibilityBindingChecker {
1397 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1401 llvm::dxbc::ShaderVisibility Vis;
1406 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1408 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1409 llvm::dxil::ResourceClass RC,
uint32_t Space,
1411 const hlsl::RootSignatureElement *Elem) {
1413 assert(BuilderIndex < Builders.size() &&
1414 "Not enough builders for visibility type");
1415 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1416 static_cast<const void *
>(Elem));
1418 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1419 "'All' visibility must come first");
1420 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1421 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1422 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1423 static_cast<const void *
>(Elem));
1425 ElemInfoMap.push_back({Elem,
Visibility,
false});
1428 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1429 auto It = llvm::lower_bound(
1431 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1432 assert(It->Elem == Elem &&
"Element not in map");
1436 bool checkOverlap() {
1437 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1438 return LHS.Elem < RHS.Elem;
1441 bool HadOverlap =
false;
1443 using llvm::hlsl::BindingInfoBuilder;
1444 auto ReportOverlap = [
this,
1445 &HadOverlap](
const BindingInfoBuilder &Builder,
1446 const llvm::hlsl::Binding &Reported) {
1450 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1451 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1452 const auto *PrevElem =
1453 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1455 ElemInfo &Info =
getInfo(Elem);
1460 Info.Diagnosed =
true;
1462 ElemInfo &PrevInfo =
getInfo(PrevElem);
1463 llvm::dxbc::ShaderVisibility CommonVis =
1464 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1467 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1468 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1469 << Reported.isUnbounded() << Reported.UpperBound
1474 this->S->
Diag(PrevElem->getLocation(),
1475 diag::note_hlsl_resource_range_here);
1478 for (BindingInfoBuilder &Builder : Builders)
1479 Builder.calculateBindingInfo(ReportOverlap);
1499 bool HadError =
false;
1500 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1501 uint32_t UpperBound) {
1503 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1504 << LowerBound << UpperBound;
1511 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1512 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1513 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1516 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1517 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1518 ReportError(Loc, 0, 0xfffffffe);
1521 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1522 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1523 ReportError(Loc, 0, 0xffffffef);
1526 const uint32_t Version =
1527 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1528 const uint32_t VersionEnum = Version - 1;
1529 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1531 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1538 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1539 if (
const auto *Descriptor =
1540 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1541 VerifyRegister(Loc, Descriptor->Reg.Number);
1542 VerifySpace(Loc, Descriptor->Space);
1544 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1546 ReportFlagError(Loc);
1547 }
else if (
const auto *Constants =
1548 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1549 VerifyRegister(Loc, Constants->Reg.Number);
1550 VerifySpace(Loc, Constants->Space);
1551 }
else if (
const auto *Sampler =
1552 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1553 VerifyRegister(Loc, Sampler->Reg.Number);
1554 VerifySpace(Loc, Sampler->Space);
1557 "By construction, parseFloatParam can't produce a NaN from a "
1558 "float_literal token");
1560 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1561 ReportError(Loc, 0, 16);
1562 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1563 ReportFloatError(Loc, -16.f, 15.99f);
1564 }
else if (
const auto *Clause =
1565 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1567 VerifyRegister(Loc, Clause->Reg.Number);
1568 VerifySpace(Loc, Clause->Space);
1570 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1574 ReportError(Loc, 1, 0xfffffffe);
1577 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1579 ReportFlagError(Loc);
1583 PerVisibilityBindingChecker BindingChecker(
this);
1584 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1589 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1590 if (
const auto *Descriptor =
1591 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1592 uint32_t LowerBound(Descriptor->Reg.Number);
1593 uint32_t UpperBound(LowerBound);
1595 BindingChecker.trackBinding(
1596 Descriptor->Visibility,
1597 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1598 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1599 }
else if (
const auto *Constants =
1600 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1601 uint32_t LowerBound(Constants->Reg.Number);
1602 uint32_t UpperBound(LowerBound);
1604 BindingChecker.trackBinding(
1605 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1606 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1607 }
else if (
const auto *Sampler =
1608 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1609 uint32_t LowerBound(Sampler->Reg.Number);
1610 uint32_t UpperBound(LowerBound);
1612 BindingChecker.trackBinding(
1613 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1614 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1615 }
else if (
const auto *Clause =
1616 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1619 UnboundClauses.emplace_back(Clause, &RootSigElem);
1620 }
else if (
const auto *Table =
1621 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1622 assert(UnboundClauses.size() == Table->NumClauses &&
1623 "Number of unbound elements must match the number of clauses");
1624 bool HasAnySampler =
false;
1625 bool HasAnyNonSampler =
false;
1626 uint64_t Offset = 0;
1627 bool IsPrevUnbound =
false;
1628 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1630 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1631 HasAnySampler =
true;
1633 HasAnyNonSampler =
true;
1635 if (HasAnySampler && HasAnyNonSampler)
1636 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1641 if (Clause->NumDescriptors == 0)
1645 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1647 Offset = Clause->Offset;
1649 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1650 Offset, Clause->NumDescriptors);
1652 if (IsPrevUnbound && IsAppending)
1653 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1654 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1655 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1658 Offset = RangeBound + 1;
1659 IsPrevUnbound = Clause->NumDescriptors ==
1660 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1663 uint32_t LowerBound(Clause->Reg.Number);
1664 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1665 LowerBound, Clause->NumDescriptors);
1667 BindingChecker.trackBinding(
1669 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1670 LowerBound, UpperBound, ClauseElem);
1672 UnboundClauses.clear();
1676 return BindingChecker.checkOverlap();
1681 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1686 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1687 if (RS->getSignatureIdent() != Ident) {
1688 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1692 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1698 if (
auto *SignatureDecl =
1699 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1706 llvm::VersionTuple SMVersion =
1711 uint32_t ZMax = 1024;
1712 uint32_t ThreadMax = 1024;
1713 if (IsDXIL && SMVersion.getMajor() <= 4) {
1716 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1726 diag::err_hlsl_numthreads_argument_oor)
1735 diag::err_hlsl_numthreads_argument_oor)
1744 diag::err_hlsl_numthreads_argument_oor)
1749 if (
X * Y * Z > ThreadMax) {
1750 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1767 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1775 if (SpelledArgsCount > 1 &&
1779 uint32_t Preferred = 0;
1780 if (SpelledArgsCount > 2 &&
1784 if (SpelledArgsCount > 2) {
1787 diag::err_attribute_power_of_two_in_range)
1788 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1793 if (Preferred < Min || Preferred >
Max) {
1795 diag::err_attribute_power_of_two_in_range)
1796 << AL <<
Min <<
Max << Preferred;
1799 }
else if (SpelledArgsCount > 1) {
1802 diag::err_attribute_power_of_two_in_range)
1803 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1807 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1810 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1815 diag::err_attribute_power_of_two_in_range)
1816 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1821 HLSLWaveSizeAttr *NewAttr =
1858 uint32_t Binding = 0;
1882 if (!
T->hasUnsignedIntegerRepresentation() ||
1883 (VT && VT->getNumElements() > 3)) {
1884 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1885 << AL <<
"uint/uint2/uint3";
1894 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1895 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1896 << AL <<
"float/float1/float2/float3/float4";
1905 std::optional<unsigned> Index) {
1907 QualType ValueType = VD->getType();
1908 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1912 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>())
1917 case SemanticKind::DispatchThreadID:
1918 case SemanticKind::GroupThreadID:
1919 case SemanticKind::GroupID:
1922 case SemanticKind::GroupIndex:
1924 case SemanticKind::Position:
1925 case SemanticKind::Target:
1928 case SemanticKind::VertexID: {
1929 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
1930 if (!ValueType->isUnsignedIntegerType() || SizeInBits != 32)
1931 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
1935 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1943 uint32_t IndexValue(0), ExplicitIndex(0);
1946 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
1948 assert(IndexValue > 0 ? ExplicitIndex :
true);
1949 std::optional<unsigned> Index =
1950 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1953 if (Kind == SemanticKind::Arbitrary)
1961 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1962 << AL <<
"shader constant in a constant buffer";
1966 uint32_t SubComponent;
1976 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1981 if (IsAggregateTy) {
1982 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
1986 if ((Component * 32 + Size) > 128) {
1987 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1992 EltTy = VT->getElementType();
1994 if (Align > 32 && Component == 1) {
1997 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2011 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2014 llvm::Triple::EnvironmentType ShaderType;
2015 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2016 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2017 << AL << Str << ArgLoc;
2031 Expr *SampleCountExpr) {
2032 assert(AttrList.size() &&
"expected list of resource attributes");
2039 HLSLAttributedResourceType::Attributes ResAttrs;
2041 bool HasResourceClass =
false;
2042 bool HasResourceDimension =
false;
2043 for (
const Attr *A : AttrList) {
2048 case attr::HLSLResourceClass: {
2050 if (HasResourceClass) {
2052 ? diag::warn_duplicate_attribute_exact
2053 : diag::warn_duplicate_attribute)
2057 ResAttrs.ResourceClass = RC;
2058 HasResourceClass =
true;
2061 case attr::HLSLResourceDimension: {
2062 llvm::dxil::ResourceDimension RD =
2064 if (HasResourceDimension) {
2066 ? diag::warn_duplicate_attribute_exact
2067 : diag::warn_duplicate_attribute)
2071 ResAttrs.ResourceDimension = RD;
2072 HasResourceDimension =
true;
2075 case attr::HLSLIsROV:
2076 if (ResAttrs.IsROV) {
2080 ResAttrs.IsROV =
true;
2082 case attr::HLSLRawBuffer:
2083 if (ResAttrs.RawBuffer) {
2087 ResAttrs.RawBuffer =
true;
2089 case attr::HLSLIsArray:
2090 if (ResAttrs.IsArray) {
2094 ResAttrs.IsArray =
true;
2096 case attr::HLSLIsMultiSampled:
2097 if (ResAttrs.SampleCountExpr) {
2103 ResAttrs.SampleCountExpr =
2109 case attr::HLSLIsCounter:
2110 if (ResAttrs.IsCounter) {
2114 ResAttrs.IsCounter =
true;
2116 case attr::HLSLContainedType: {
2119 if (!ContainedTy.
isNull()) {
2121 ? diag::warn_duplicate_attribute_exact
2122 : diag::warn_duplicate_attribute)
2131 llvm_unreachable(
"unhandled resource attribute type");
2135 if (!HasResourceClass) {
2136 S.
Diag(AttrList.back()->getRange().getEnd(),
2137 diag::err_hlsl_missing_resource_class);
2142 Wrapped, ContainedTy, ResAttrs);
2144 if (LocInfo && ContainedTyInfo) {
2157 if (!
T->isHLSLResourceType()) {
2158 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2173 AttributeCommonInfo::AS_CXX11, 0, false ,
2178 case ParsedAttr::AT_HLSLResourceClass: {
2179 StringRef Identifier;
2181 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2186 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2187 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2188 <<
"ResourceClass" << Identifier;
2191 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2195 case ParsedAttr::AT_HLSLResourceDimension: {
2196 StringRef Identifier;
2198 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2202 llvm::dxil::ResourceDimension RD;
2203 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2205 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2206 <<
"ResourceDimension" << Identifier;
2209 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2213 case ParsedAttr::AT_HLSLIsROV:
2217 case ParsedAttr::AT_HLSLRawBuffer:
2221 case ParsedAttr::AT_HLSLIsCounter:
2225 case ParsedAttr::AT_HLSLIsArray:
2229 case ParsedAttr::AT_HLSLIsMultiSampled:
2233 case ParsedAttr::AT_HLSLContainedType: {
2235 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2241 assert(TSI &&
"no type source info for attribute argument");
2243 diag::err_incomplete_type))
2245 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2250 llvm_unreachable(
"unhandled HLSL attribute");
2253 HLSLResourcesTypeAttrs.emplace_back(A);
2259 if (!HLSLResourcesTypeAttrs.size())
2265 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2266 const HLSLAttributedResourceType *RT =
2273 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2275 HLSLResourcesTypeAttrs.clear();
2283 auto I = LocsForHLSLAttributedResources.find(RT);
2284 if (I != LocsForHLSLAttributedResources.end()) {
2285 LocInfo = I->second;
2286 LocsForHLSLAttributedResources.erase(I);
2295void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2296 const RecordType *RT) {
2304 "incomplete arrays inside user defined types are not supported");
2313 if (
const HLSLAttributedResourceType *AttrResType =
2314 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2319 Bindings.addDeclBindingInfo(VD, RC);
2320 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2326 collectResourceBindingsOnUserRecordDecl(VD, RT);
2338 bool SpecifiedSpace) {
2339 int RegTypeNum =
static_cast<int>(RegType);
2342 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2343 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2348 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2349 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2350 : ResourceClass::SRV;
2360 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2364 if (
const HLSLAttributedResourceType *AttrResType =
2365 HLSLAttributedResourceType::findHandleTypeOnResource(
2382 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2383 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2388 if (RegType == RegisterType::CBuffer)
2389 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2390 else if (RegType != RegisterType::C)
2391 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2395 if (RegType == RegisterType::C)
2396 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2398 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2408 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2416 bool RegisterTypesDetected[5] = {
false};
2417 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2420 if (HLSLResourceBindingAttr *
attr =
2421 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2424 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2425 int otherRegTypeNum =
static_cast<int>(otherRegType);
2427 diag::err_hlsl_duplicate_register_annotation)
2431 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2439 bool SpecifiedSpace) {
2444 "expecting VarDecl or HLSLBufferDecl");
2456 const uint64_t &Limit,
2459 uint64_t ArrayCount = 1) {
2464 if (StartSlot > Limit)
2468 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2471 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2472 Count = CAT->
getSize().getZExtValue();
2476 ArrayCount * Count);
2480 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2483 if (ResTy->getAttrs().ResourceClass != ResClass)
2487 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2488 if (EndSlot > Limit)
2492 StartSlot = EndSlot + 1;
2497 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2500 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2503 ResClass, Ctx, ArrayCount))
2510 ResClass, Ctx, ArrayCount))
2524 const uint64_t Limit = UINT32_MAX;
2525 if (SlotNum > Limit)
2530 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2533 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2534 uint64_t BaseSlot = SlotNum;
2542 return (BaseSlot > Limit);
2549 return (SlotNum > Limit);
2552 llvm_unreachable(
"unexpected decl type");
2556 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2558 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2559 Ty = IAT->getElementType();
2561 diag::err_incomplete_type))
2565 StringRef Slot =
"";
2566 StringRef Space =
"";
2570 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2580 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2586 SpaceLoc = Loc->
getLoc();
2589 if (Str.starts_with(
"space")) {
2591 SpaceLoc = Loc->
getLoc();
2600 std::optional<unsigned> SlotNum;
2601 unsigned SpaceNum = 0;
2604 if (!Slot.empty()) {
2606 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2609 if (RegType == RegisterType::I) {
2610 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2613 const StringRef SlotNumStr = Slot.substr(1);
2618 if (SlotNumStr.getAsInteger(10, N)) {
2619 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2627 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2636 if (!Space.starts_with(
"space")) {
2637 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2640 StringRef SpaceNumStr = Space.substr(5);
2641 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2642 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2647 if (SlotNum.has_value())
2652 HLSLResourceBindingAttr *NewAttr =
2653 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2655 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2681 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2683 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2687 Cur = AT->getModifiedType();
2698 ? attr::HLSLRowMajor
2699 : attr::HLSLColumnMajor;
2704 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2713 if (ExistingKind == AttrK) {
2714 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2716 Diag(AL.
getLoc(), diag::note_previous_attribute);
2720 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2721 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2723 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2728 if (AttrK == attr::HLSLRowMajor)
2729 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2730 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2741 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2743 if (
T.isNull() ||
T->isDependentType())
2748 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2749 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2756 switch (BuiltinID) {
2757 case Builtin::BI__builtin_hlsl_mul:
2758 case Builtin::BI__builtin_hlsl_transpose:
2766 if (!E || DestType.
isNull())
2778 if (!CallMat || CallMat->getNumRows() != DestMat->getNumRows() ||
2779 CallMat->getNumColumns() != DestMat->getNumColumns())
2828 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2832 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2833 unsigned CurrentShaderStageBit;
2838 bool ReportOnlyShaderStageIssues;
2841 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2842 static_assert(
sizeof(
unsigned) >= 4);
2843 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2844 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2845 "ShaderType is too big for this bitmap");
2848 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2849 CurrentShaderEnvironment = ShaderType;
2850 CurrentShaderStageBit = (1 << bitmapIndex);
2853 void SetUnknownShaderStageContext() {
2854 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2855 CurrentShaderStageBit = (1 << 31);
2858 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2859 return CurrentShaderEnvironment;
2862 bool InUnknownShaderStageContext()
const {
2863 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2867 void AddToScannedFunctions(
const FunctionDecl *FD) {
2868 unsigned &ScannedStages = ScannedDecls[FD];
2869 ScannedStages |= CurrentShaderStageBit;
2872 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2874 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2875 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2878 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2879 return ScannerStages & CurrentShaderStageBit;
2882 static bool NeverBeenScanned(
unsigned ScannedStages) {
2883 return ScannedStages == 0;
2887 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2888 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2890 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2891 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2894 DiagnoseHLSLAvailability(Sema &SemaRef)
2896 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2897 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2900 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2901 void RunOnFunction(
const FunctionDecl *FD);
2903 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2904 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2906 HandleFunctionOrMethodRef(FD, DRE);
2910 bool VisitMemberExpr(MemberExpr *ME)
override {
2911 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2913 HandleFunctionOrMethodRef(FD, ME);
2918void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2921 "expected DeclRefExpr or MemberExpr");
2923 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
2924 CheckDeclAvailability(
2929 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
2930 DeclsToScan.push_back(FDWithBody);
2933void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2938 llvm::Triple::EnvironmentType::Library;
2947 DeclContextsToScan.push_back(TU);
2949 while (!DeclContextsToScan.empty()) {
2950 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2951 for (
auto &D : DC->
decls()) {
2958 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2959 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2964 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2969 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2970 if (!IsLibraryShader && FD->
getName() == EntryName) {
2973 diag::err_hlsl_ambiguous_entry_point)
2975 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
2981 SetShaderStageContext(ShaderAttr->getType());
2990 for (
const auto *Redecl : FD->
redecls()) {
2991 if (Redecl->isInExportDeclContext()) {
2998 SetUnknownShaderStageContext();
3005 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3012void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3013 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3014 DeclsToScan.push_back(FD);
3016 while (!DeclsToScan.empty()) {
3024 const unsigned ScannedStages = GetScannedStages(FD);
3025 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3028 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3030 AddToScannedFunctions(FD);
3035bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3036 const AvailabilityAttr *AA) {
3041 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3042 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3045 llvm::Triple::EnvironmentType AttrEnv =
3046 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3048 return CurrentEnv == AttrEnv;
3051const AvailabilityAttr *
3052DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3053 AvailabilityAttr
const *PartialMatch =
nullptr;
3057 for (
const auto *A : D->
attrs()) {
3058 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3059 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3060 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3061 StringRef TargetPlatform =
3065 if (AttrPlatform == TargetPlatform) {
3067 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3069 PartialMatch = Avail;
3073 return PartialMatch;
3078void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3079 const AvailabilityAttr *AA,
3098 if (ReportOnlyShaderStageIssues)
3104 if (InUnknownShaderStageContext())
3109 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3110 VersionTuple Introduced = AA->getIntroduced();
3119 llvm::StringRef PlatformName(
3122 llvm::StringRef CurrentEnvStr =
3123 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3125 llvm::StringRef AttrEnvStr =
3126 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3127 bool UseEnvironment = !AttrEnvStr.empty();
3129 if (EnvironmentMatches) {
3130 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3131 <<
Range << D << PlatformName << Introduced.getAsString()
3132 << UseEnvironment << CurrentEnvStr;
3134 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3138 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3139 << D << PlatformName << Introduced.getAsString()
3141 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3148 if (!DefaultCBufferDecls.empty()) {
3151 DefaultCBufferDecls);
3154 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3158 for (
const Decl *VD : DefaultCBufferDecls) {
3159 const HLSLResourceBindingAttr *RBA =
3160 VD->
getAttr<HLSLResourceBindingAttr>();
3161 if (RBA && RBA->hasRegisterSlot() &&
3162 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3169 SemaRef.Consumer.HandleTopLevelDecl(DG);
3171 diagnoseAvailabilityViolations(TU);
3180 "expected member expr to have resource record type or array of them");
3186 const Expr *NonConstIndexExpr =
nullptr;
3189 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3190 if (!NonConstIndexExpr)
3198 diag::err_hlsl_resource_member_array_access_not_constant);
3202 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3203 const Expr *IdxExpr = ASE->getIdx();
3205 NonConstIndexExpr = IdxExpr;
3207 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3208 E = SubME->getBase();
3209 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3210 E = ICE->getSubExpr();
3212 llvm_unreachable(
"unexpected expr type in resource member access");
3221 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3224 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3227 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3231 [[maybe_unused]]
bool LookupSucceeded =
3232 SemaRef.LookupQualifiedName(ConvR, RD);
3233 assert(LookupSucceeded);
3242std::optional<ExprResult>
3245 const HLSLAttributedResourceType *ResTy =
3246 HLSLAttributedResourceType::findHandleTypeOnResource(
3247 BaseType.getTypePtr());
3249 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3250 return std::nullopt;
3252 QualType TemplateType = ResTy->getContainedType();
3256 assert(NamedConversionDecl &&
3257 "Could not find conversion function for ConstantBuffer.");
3258 auto *ConversionDecl =
3261 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3273 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3276 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3283 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3286 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3311 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3326 if (!BaseType->isFloat32Type())
3327 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3328 << ArgOrdinal << 5 << 0
3338 BaseType = VT->getElementType();
3340 BaseType = MT->getElementType();
3342 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3343 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3344 << ArgOrdinal << 5 << 0
3358 if (!BaseType->isDoubleType()) {
3361 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3362 << ArgOrdinal << PassedType;
3369 unsigned ArgIndex) {
3370 auto *Arg = TheCall->
getArg(ArgIndex);
3372 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3375 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3389 << (ArgIndex + 1) << LValueTy;
3399 if (VecTy->getElementType()->isDoubleType())
3400 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3401 << ArgOrdinal << 1 << 0 << 1
3411 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3412 << ArgOrdinal << 5 << 1
3421 if (VecTy->getElementType()->isUnsignedIntegerType())
3424 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3425 << ArgOrdinal << 4 << 3 << 0
3434 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3435 << ArgOrdinal << 5 << 3
3441 unsigned ArgOrdinal,
unsigned Width) {
3444 ArgTy = VTy->getElementType();
3446 uint64_t ElementBitCount =
3448 if (ElementBitCount != Width) {
3450 diag::err_integer_incorrect_bit_count)
3451 << Width << ElementBitCount;
3462 else if (
auto *MatTyA =
3465 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3471 unsigned ArgIndex) {
3480 diag::err_typecheck_expect_scalar_or_vector)
3481 << ArgType << Scalar;
3488 QualType Scalar,
unsigned ArgIndex) {
3499 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3512 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3513 << ArgType << Scalar;
3518 unsigned ArgIndex) {
3523 if (!(ArgType->isScalarType() ||
3524 (VTy && VTy->getElementType()->isScalarType()))) {
3526 diag::err_typecheck_expect_any_scalar_or_vector)
3536 unsigned ArgIndex) {
3538 assert(ArgIndex < TheCall->getNumArgs());
3546 diag::err_typecheck_expect_any_scalar_or_vector)
3571 diag::err_typecheck_call_different_arg_types)
3590 Arg1ScalarTy = VTy->getElementType();
3594 Arg2ScalarTy = VTy->getElementType();
3597 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3598 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3608 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3610 diag::err_typecheck_vector_lengths_not_equal)
3616 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3618 diag::err_typecheck_vector_lengths_not_equal)
3630 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3633 unsigned int ActualDim = 1;
3635 ActualDim = VTy->getNumElements();
3636 IndexTy = VTy->getElementType();
3640 diag::err_typecheck_expect_int)
3646 const HLSLAttributedResourceType *ResTy =
3648 assert(ResTy &&
"Resource argument must be a resource");
3649 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3651 unsigned int ExpectedDim = 1;
3652 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3654 (ResAttrs.IsArray ? 1 : 0);
3656 if (ActualDim != ExpectedDim) {
3658 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3669 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3673 const HLSLAttributedResourceType *ResTy =
3677 diag::err_typecheck_expect_hlsl_resource)
3681 if (Check && Check(ResTy)) {
3683 diag::err_invalid_hlsl_resource_type)
3693 "expected resource handle type");
3694 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3695 auto MainAttrs = MainResType->getAttrs();
3696 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3697 MainAttrs.IsCounter =
true;
3699 MainResType->getContainedType(),
3704 QualType BaseType,
unsigned ExpectedCount,
3706 unsigned PassedCount = 1;
3708 PassedCount = VecTy->getNumElements();
3710 if (PassedCount != ExpectedCount) {
3713 S->
Diag(Loc, diag::err_typecheck_convert_incompatible)
3727 return "SampleBias";
3729 return "SampleGrad";
3731 return "SampleLevel";
3735 return "SampleCmpLevelZero";
3737 llvm_unreachable(
"Invalid SampleKind");
3747 if (!MD || !MD->getDeclName().isIdentifier())
3754 return MD->getName();
3762 return VecTy->getElementType();
3763 return ContainedType;
3771 StringRef DefaultName) {
3776 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
3803 if (SMVersion >= VersionTuple(6, 7))
3806 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
3808 << ContainedType << SMVersion.getAsString();
3813 bool IncludeArraySlice =
true) {
3816 [](
const HLSLAttributedResourceType *ResType) {
3817 return ResType->getAttrs().ResourceDimension ==
3818 llvm::dxil::ResourceDimension::Unknown;
3824 [](
const HLSLAttributedResourceType *ResType) {
3825 return ResType->getAttrs().ResourceClass !=
3826 llvm::hlsl::ResourceClass::Sampler;
3834 unsigned ExpectedDim =
3836 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
3865 unsigned NextIdx = 3;
3871 diag::err_typecheck_convert_incompatible)
3879 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3883 diag::err_typecheck_convert_incompatible)
3890 std::optional<llvm::APSInt> ComponentOpt =
3893 int64_t ComponentVal = ComponentOpt->getSExtValue();
3894 if (ComponentVal != 0) {
3897 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3898 "The component is not in the expected range.");
3900 diag::err_hlsl_gathercmp_invalid_component)
3910 const HLSLAttributedResourceType *ResourceTy =
3913 unsigned ExpectedDim =
3922 assert(ResourceTy->hasContainedType() &&
3923 "Expecting a contained type for resource with a dimension "
3925 QualType ReturnType = ResourceTy->getContainedType();
3928 IsCmp ?
"GatherCmp" :
"Gather"))
3933 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3939 ReturnType = VecTy->getElementType();
3952 [](
const HLSLAttributedResourceType *ResType) {
3953 return ResType->getAttrs().ResourceDimension ==
3954 llvm::dxil::ResourceDimension::Unknown;
3964 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
3971 unsigned ResourceDim =
3973 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
3983 EltTy = VTy->getElementType();
3998 TheCall->
setType(ResourceTy->getContainedType());
4008 [](
const HLSLAttributedResourceType *ResType) {
4009 return !ResType->isMultiSampled();
4018 unsigned ResourceDim =
4020 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4041 TheCall->
setType(ResourceTy->getContainedType());
4046 unsigned MinArgs, MaxArgs;
4074 const HLSLAttributedResourceType *ResourceTy =
4076 unsigned ExpectedDim =
4079 unsigned NextIdx = 3;
4088 diag::err_typecheck_convert_incompatible)
4124 diag::err_typecheck_convert_incompatible)
4130 assert(ResourceTy->hasContainedType() &&
4131 "Expecting a contained type for resource with a dimension "
4133 QualType ReturnType = ResourceTy->getContainedType();
4144 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4157 switch (BuiltinID) {
4158 case Builtin::BI__builtin_hlsl_adduint64: {
4159 if (
SemaRef.checkArgCount(TheCall, 2))
4173 if (NumElementsArg != 2 && NumElementsArg != 4) {
4175 << 1 << 64 << NumElementsArg * 32;
4189 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4190 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4197 QualType ContainedTy = ResourceTy->getContainedType();
4198 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4201 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4206 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4207 if (
SemaRef.checkArgCount(TheCall, 3) ||
4214 "expected pointer type for second argument");
4221 diag::err_invalid_use_of_array_type);
4225 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4228 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4233 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4234 if (
SemaRef.checkArgCount(TheCall, 2) ||
4236 SemaRef.getASTContext().IntTy))
4243 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4244 if (
SemaRef.checkArgCount(TheCall, 3) ||
4247 SemaRef.getASTContext().UnsignedIntTy) ||
4249 SemaRef.getASTContext().UnsignedIntTy) ||
4255 QualType ReturnType = ResourceTy->getContainedType();
4260 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4261 if (
SemaRef.checkArgCount(TheCall, 4) ||
4264 SemaRef.getASTContext().UnsignedIntTy) ||
4266 SemaRef.getASTContext().UnsignedIntTy) ||
4272 "expected pointer type for second argument");
4279 diag::err_invalid_use_of_array_type);
4285 case Builtin::BI__builtin_hlsl_resource_load_level:
4287 case Builtin::BI__builtin_hlsl_resource_load_ms:
4289 case Builtin::BI__builtin_hlsl_resource_sample:
4291 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4293 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4295 case Builtin::BI__builtin_hlsl_resource_sample_level:
4297 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4299 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4301 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4302 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4304 case Builtin::BI__builtin_hlsl_resource_gather:
4306 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4308 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4309 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4315 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4316 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4322 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4323 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4329 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4330 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4336 TheCall->
setType(CounterHandleTy);
4339 case Builtin::BI__builtin_hlsl_and:
4340 case Builtin::BI__builtin_hlsl_or: {
4341 if (
SemaRef.checkArgCount(TheCall, 2))
4355 case Builtin::BI__builtin_hlsl_all:
4356 case Builtin::BI__builtin_hlsl_any: {
4357 if (
SemaRef.checkArgCount(TheCall, 1))
4363 case Builtin::BI__builtin_hlsl_asdouble: {
4364 if (
SemaRef.checkArgCount(TheCall, 2))
4368 SemaRef.Context.UnsignedIntTy,
4373 SemaRef.Context.UnsignedIntTy,
4382 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4383 if (
SemaRef.BuiltinElementwiseTernaryMath(
4389 case Builtin::BI__builtin_hlsl_dot: {
4391 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4397 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4398 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4399 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4409 EltTy = VecTy->getElementType();
4410 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4423 case Builtin::BI__builtin_hlsl_select: {
4424 if (
SemaRef.checkArgCount(TheCall, 3))
4432 if (VTy && VTy->getElementType()->isBooleanType() &&
4437 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4438 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4439 if (
SemaRef.checkArgCount(TheCall, 1))
4445 diag::err_builtin_invalid_arg_type)
4448 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4452 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4453 case Builtin::BI__builtin_hlsl_elementwise_frac:
4454 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4455 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4456 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4457 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4458 if (
SemaRef.checkArgCount(TheCall, 1))
4463 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4467 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4468 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4469 if (
SemaRef.checkArgCount(TheCall, 1))
4474 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4479 case Builtin::BI__builtin_hlsl_mad: {
4480 if (
SemaRef.BuiltinElementwiseTernaryMath(
4486 case Builtin::BI__builtin_hlsl_mul: {
4487 if (
SemaRef.checkArgCount(TheCall, 2))
4497 return VTy->getElementType();
4499 return MTy->getElementType();
4503 QualType EltTy0 = getElemType(Ty0);
4512 if (IsVec0 && IsMat1) {
4515 }
else if (IsMat0 && IsVec1) {
4519 assert(IsMat0 && IsMat1);
4529 case Builtin::BI__builtin_elementwise_fma: {
4530 if (
SemaRef.checkArgCount(TheCall, 3) ||
4545 case Builtin::BI__builtin_hlsl_transpose: {
4546 if (
SemaRef.checkArgCount(TheCall, 1))
4555 << 1 << 3 << 0 << 0 << ArgTy;
4560 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4564 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4565 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4573 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4574 if (
SemaRef.checkArgCount(TheCall, 1))
4588 unsigned NumElts = VecTy->getNumElements();
4598 case Builtin::BI__builtin_hlsl_wave_active_max:
4599 case Builtin::BI__builtin_hlsl_wave_active_min:
4600 case Builtin::BI__builtin_hlsl_wave_active_sum:
4601 case Builtin::BI__builtin_hlsl_wave_active_product: {
4602 if (
SemaRef.checkArgCount(TheCall, 1))
4615 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4616 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4617 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4618 if (
SemaRef.checkArgCount(TheCall, 1))
4633 (VTy && VTy->getElementType()->isIntegerType()))) {
4635 diag::err_builtin_invalid_arg_type)
4636 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4644 case Builtin::BI__builtin_hlsl_interlocked_add:
4645 case Builtin::BI__builtin_hlsl_interlocked_and:
4646 case Builtin::BI__builtin_hlsl_interlocked_min:
4647 case Builtin::BI__builtin_hlsl_interlocked_or:
4648 case Builtin::BI__builtin_hlsl_interlocked_xor: {
4658 diag::err_typecheck_call_too_few_args_at_least)
4663 if (
SemaRef.checkArgCountAtMost(TheCall, 3))
4669 diag::err_builtin_invalid_arg_type)
4681 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4682 SemaRef.Context.getTypeSize(DestTy) == 64 &&
4711 case Builtin::BI__builtin_elementwise_bitreverse: {
4719 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4720 if (
SemaRef.checkArgCount(TheCall, 1))
4725 if (!(
ArgType->isScalarType())) {
4727 diag::err_typecheck_expect_any_scalar_or_vector)
4732 if (!(
ArgType->isBooleanType())) {
4734 diag::err_typecheck_expect_any_scalar_or_vector)
4741 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4742 if (
SemaRef.checkArgCount(TheCall, 2))
4750 diag::err_typecheck_convert_incompatible)
4751 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4764 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4765 if (
SemaRef.checkArgCount(TheCall, 0))
4769 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4770 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4771 if (
SemaRef.checkArgCount(TheCall, 1))
4784 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4785 case Builtin::BI__builtin_hlsl_quad_read_across_y:
4786 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
4787 if (
SemaRef.checkArgCount(TheCall, 1))
4799 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4800 if (
SemaRef.checkArgCount(TheCall, 3))
4806 SemaRef.Context.UnsignedIntTy, 1) ||
4808 SemaRef.Context.UnsignedIntTy, 2))
4816 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4817 if (
SemaRef.checkArgCount(TheCall, 1))
4824 case Builtin::BI__builtin_elementwise_acos:
4825 case Builtin::BI__builtin_elementwise_asin:
4826 case Builtin::BI__builtin_elementwise_atan:
4827 case Builtin::BI__builtin_elementwise_atan2:
4828 case Builtin::BI__builtin_elementwise_ceil:
4829 case Builtin::BI__builtin_elementwise_cos:
4830 case Builtin::BI__builtin_elementwise_cosh:
4831 case Builtin::BI__builtin_elementwise_exp:
4832 case Builtin::BI__builtin_elementwise_exp2:
4833 case Builtin::BI__builtin_elementwise_exp10:
4834 case Builtin::BI__builtin_elementwise_floor:
4835 case Builtin::BI__builtin_elementwise_fmod:
4836 case Builtin::BI__builtin_elementwise_log:
4837 case Builtin::BI__builtin_elementwise_log2:
4838 case Builtin::BI__builtin_elementwise_log10:
4839 case Builtin::BI__builtin_elementwise_pow:
4840 case Builtin::BI__builtin_elementwise_roundeven:
4841 case Builtin::BI__builtin_elementwise_sin:
4842 case Builtin::BI__builtin_elementwise_sinh:
4843 case Builtin::BI__builtin_elementwise_sqrt:
4844 case Builtin::BI__builtin_elementwise_tan:
4845 case Builtin::BI__builtin_elementwise_tanh:
4846 case Builtin::BI__builtin_elementwise_trunc: {
4852 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4853 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4854 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4855 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4856 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4861 std::optional<llvm::APSInt> Offset =
4863 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4865 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4871 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4872 if (
SemaRef.checkArgCount(TheCall, 1))
4883 ArgTy = VTy->getElementType();
4886 diag::err_builtin_invalid_arg_type)
4895 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4896 if (
SemaRef.checkArgCount(TheCall, 1))
4911 WorkList.push_back(BaseTy);
4912 while (!WorkList.empty()) {
4914 T =
T.getCanonicalType().getUnqualifiedType();
4915 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
4923 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4924 llvm::append_range(List, ElementFields);
4929 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
4930 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
4933 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
4934 List.insert(List.end(), MT->getNumElementsFlattened(),
4935 MT->getElementType());
4938 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
4939 if (RD->isStandardLayout())
4940 RD = RD->getStandardLayoutBaseWithFields();
4944 if (RD->
isUnion() || !RD->isAggregate()) {
4950 for (
const auto *FD : RD->
fields())
4951 if (!FD->isUnnamedBitField())
4952 FieldTypes.push_back(FD->
getType());
4954 std::reverse(FieldTypes.begin(), FieldTypes.end());
4955 llvm::append_range(WorkList, FieldTypes);
4959 if (!RD->isStandardLayout()) {
4961 for (
const auto &
Base : RD->bases())
4962 FieldTypes.push_back(
Base.getType());
4963 std::reverse(FieldTypes.begin(), FieldTypes.end());
4964 llvm::append_range(WorkList, FieldTypes);
4999 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5005 int ArraySize = VT->getNumElements();
5010 QualType ElTy = VT->getElementType();
5014 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5030 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5039 return llvm::equal(T1Types, T2Types,
5041 return SemaRef.IsLayoutCompatible(LHS, RHS);
5050 bool HadError =
false;
5052 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5060 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5061 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5062 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5063 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5065 if (NSpellingIdx != OSpellingIdx) {
5067 diag::err_hlsl_param_qualifier_mismatch)
5068 << NDAttr << NewParam;
5084 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5099 llvm_unreachable(
"HLSL doesn't support pointers.");
5102 llvm_unreachable(
"HLSL doesn't support complex types.");
5104 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5106 llvm_unreachable(
"Should have returned before this");
5116 llvm_unreachable(
"HLSL doesn't support complex types.");
5118 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5123 llvm_unreachable(
"HLSL doesn't support pointers.");
5125 llvm_unreachable(
"Should have returned before this");
5131 llvm_unreachable(
"HLSL doesn't support pointers.");
5134 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5138 llvm_unreachable(
"HLSL doesn't support complex types.");
5141 llvm_unreachable(
"Unhandled scalar cast");
5162 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5168 SrcTy = SrcMatTy->getElementType();
5173 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5174 if (DestTypes[I]->isUnionType())
5206 if (SrcTypes.size() < DestTypes.size())
5209 unsigned SrcSize = SrcTypes.size();
5210 unsigned DstSize = DestTypes.size();
5212 for (I = 0; I < DstSize && I < SrcSize; I++) {
5213 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5221 for (; I < SrcSize; I++) {
5222 if (SrcTypes[I]->isUnionType())
5229 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5230 "We should not get here without a parameter modifier expression");
5231 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5238 << Arg << (IsInOut ? 1 : 0);
5244 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5251 << Arg << (IsInOut ? 1 : 0);
5263 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5269 auto *OpV =
new (Ctx)
5275 tok::equal, ArgOpV, OpV);
5291 "Pointer and reference types cannot be inout or out parameters");
5292 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5308 for (
const auto *FD : RD->
fields()) {
5312 assert(RD->getNumBases() <= 1 &&
5313 "HLSL doesn't support multiple inheritance");
5314 return RD->getNumBases()
5319 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5320 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5332 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5337 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5343 if (
Decl->getType().hasAddressSpace())
5346 if (
Decl->getType()->isDependentType())
5358 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5372 llvm::Triple::Vulkan;
5373 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5374 if (HasDeclaredAPushConstant)
5380 HasDeclaredAPushConstant =
true;
5407class StructBindingContext {
5410 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5411 unsigned RegBindingOffset[4];
5414 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5415 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5416 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5417 static_cast<unsigned>(RegisterType::Sampler) == 3,
5418 "unexpected register type values");
5421 HLSLVkBindingAttr *VkBindingAttr;
5422 unsigned VkBindingOffset;
5427 StructBindingContext(
VarDecl *VD) {
5428 for (
unsigned i = 0; i < 4; ++i) {
5429 RegBindingsAttrs[i] =
nullptr;
5430 RegBindingOffset[i] = 0;
5432 VkBindingAttr =
nullptr;
5433 VkBindingOffset = 0;
5439 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5441 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5444 RegBindingsAttrs[RegTypeIdx] = RBA;
5449 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5450 VkBindingAttr = VBA;
5457 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5458 unsigned Range,
bool HasCounter) {
5459 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5461 if (VkBindingAttr) {
5462 unsigned Offset = VkBindingOffset;
5463 VkBindingOffset +=
Range;
5464 return HLSLVkBindingAttr::CreateImplicit(
5465 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5466 VkBindingAttr->getRange());
5469 HLSLResourceBindingAttr *RBA =
5470 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5471 HLSLResourceBindingAttr *NewAttr =
nullptr;
5473 if (RBA && RBA->hasRegisterSlot()) {
5476 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5477 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5479 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5480 StringRef NewSlotNumberStr =
5482 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5483 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5484 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5488 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5489 NewAttr->setBinding(RegType, std::nullopt,
5490 RBA ? RBA->getSpaceNumber() : 0);
5494 NewAttr->setImplicitCounterBindingOrderID(
5503static void createGlobalResourceDeclForStruct(
5505 QualType ResTy, StructBindingContext &BindingCtx) {
5507 "expected resource type or array of resources");
5518 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5519 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5524 const HLSLAttributedResourceType *ResHandleTy =
5525 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5529 Attr *BindingAttr = BindingCtx.createBindingAttr(
5531 ResDecl->
addAttr(BindingAttr);
5532 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5541 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5548static void handleArrayOfStructWithResources(
5550 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5555static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5557 EmbeddedResourceNameBuilder &NameBuilder,
5558 StructBindingContext &BindingCtx) {
5561 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5568 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5582 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5585 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5587 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5589 "resource arrays should have been already handled");
5590 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5599handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5601 EmbeddedResourceNameBuilder &NameBuilder,
5602 StructBindingContext &BindingCtx) {
5610 if (!SubCAT && !ElementRD)
5613 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5616 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5619 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5632void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5633 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5634 StructBindingContext BindingCtx(VD);
5638 "Expected non-resource struct or array type");
5641 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5645 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5646 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5654 if (
SemaRef.RequireCompleteType(
5657 diag::err_typecheck_decl_incomplete_type)) {
5671 DefaultCBufferDecls.push_back(VD);
5676 collectResourceBindingsOnVarDecl(VD);
5678 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5690 processExplicitBindingsOnDecl(VD);
5728 handleGlobalStructOrArrayOfWithResources(VD);
5732 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5741 "expected resource record type");
5757 const char *CreateMethodName;
5759 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5760 :
"__createFromBinding";
5762 CreateMethodName = HasCounter
5763 ?
"__createFromImplicitBindingWithImplicitCounter"
5764 :
"__createFromImplicitBinding";
5769 if (!CreateMethod) {
5774 "create method lookup should always succeed for built-in resource "
5783 Args.push_back(RegSlot);
5791 Args.push_back(OrderId);
5797 Args.push_back(Space);
5801 Args.push_back(RangeSize);
5805 Args.push_back(Index);
5807 StringRef VarName = VD->
getName();
5815 Args.push_back(NameCast);
5823 Args.push_back(CounterId);
5846 SemaRef.CheckCompleteVariableDeclaration(VD);
5852 "expected array of resource records");
5873 lookupMethod(
SemaRef, ResourceDecl,
5874 HasCounter ?
"__createFromBindingWithImplicitCounter"
5875 :
"__createFromBinding",
5879 CreateMethod = lookupMethod(
5881 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5882 :
"__createFromImplicitBinding",
5925std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5926 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5927 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5928 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5929 if (!TrueInfo || !FalseInfo)
5930 return std::nullopt;
5931 if (*TrueInfo != *FalseInfo)
5932 return std::nullopt;
5936 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5945 if (
const auto *AttrResType =
5946 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5948 return Bindings.getDeclBindingInfo(VD, RC);
5955void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
5956 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
5959 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5964 if (*ExprBinding ==
nullptr)
5967 auto PrevBinding = Assigns.find(VD);
5968 if (PrevBinding == Assigns.end()) {
5970 Assigns.insert({VD, *ExprBinding});
5975 if (*ExprBinding != PrevBinding->second) {
5977 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5979 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
5990 "expected LHS to be a resource record or array of resource records");
5991 if (Opc != BO_Assign)
5996 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6004 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6009 trackLocalResource(VD, RHSExpr);
6026void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6028 "expected global variable that contains HLSL resource");
6031 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6032 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6033 ? ResourceClass::CBuffer
6034 : ResourceClass::SRV);
6047 if (
const HLSLAttributedResourceType *AttrResType =
6048 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6049 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6054 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6055 collectResourceBindingsOnUserRecordDecl(VD, RT);
6061void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6064 bool HasBinding =
false;
6065 for (Attr *A : VD->
attrs()) {
6068 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6069 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6072 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6073 if (!RBA || !RBA->hasRegisterSlot())
6078 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6079 "never have an attribute created");
6081 if (RT == RegisterType::C) {
6082 if (Bindings.hasBindingInfoForDecl(VD))
6084 diag::warn_hlsl_user_defined_type_missing_member)
6085 <<
static_cast<int>(RT);
6093 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6098 diag::warn_hlsl_user_defined_type_missing_member)
6099 <<
static_cast<int>(RT);
6107class InitListTransformer {
6111 QualType *DstIt =
nullptr;
6112 Expr **ArgIt =
nullptr;
6118 bool castInitializer(Expr *E) {
6119 assert(DstIt &&
"This should always be something!");
6120 if (DstIt == DestTypes.end()) {
6122 ArgExprs.push_back(E);
6127 DstIt = DestTypes.begin();
6130 Ctx, *DstIt,
false);
6135 ArgExprs.push_back(
Init);
6140 bool buildInitializerListImpl(Expr *E) {
6142 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6143 for (
auto *SubInit :
Init->inits())
6144 if (!buildInitializerListImpl(SubInit))
6154 return castInitializer(E);
6168 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6173 for (uint64_t I = 0; I <
Size; ++I) {
6175 SizeTy, SourceLocation());
6181 if (!castInitializer(ElExpr.
get()))
6186 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6187 unsigned Rows = MTy->getNumRows();
6188 unsigned Cols = MTy->getNumColumns();
6189 QualType ElemTy = MTy->getElementType();
6191 for (
unsigned R = 0;
R < Rows; ++
R) {
6192 for (
unsigned C = 0;
C < Cols; ++
C) {
6205 if (!castInitializer(ElExpr.
get()))
6213 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6217 for (uint64_t I = 0; I <
Size; ++I) {
6219 SizeTy, SourceLocation());
6224 if (!buildInitializerListImpl(ElExpr.
get()))
6231 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6232 RecordDecls.push_back(RD);
6233 while (RecordDecls.back()->getNumBases()) {
6234 CXXRecordDecl *D = RecordDecls.back();
6236 "HLSL doesn't support multiple inheritance");
6237 RecordDecls.push_back(
6240 while (!RecordDecls.empty()) {
6241 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6242 for (
auto *FD : RD->
fields()) {
6243 if (FD->isUnnamedBitField())
6251 if (!buildInitializerListImpl(Res.
get()))
6259 Expr *generateInitListsImpl(QualType Ty) {
6261 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6266 llvm::SmallVector<Expr *>
Inits;
6271 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6272 ElTy = ATy->getElementType();
6273 Size = ATy->getNumElements();
6274 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6275 ElTy = CMTy->getElementType();
6276 Size = CMTy->getNumElementsFlattened();
6279 ElTy = VTy->getElementType();
6280 Size = VTy->getZExtSize();
6282 for (uint64_t I = 0; I <
Size; ++I)
6283 Inits.push_back(generateInitListsImpl(ElTy));
6286 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6287 RecordDecls.push_back(RD);
6288 while (RecordDecls.back()->getNumBases()) {
6289 CXXRecordDecl *D = RecordDecls.back();
6291 "HLSL doesn't support multiple inheritance");
6292 RecordDecls.push_back(
6295 while (!RecordDecls.empty()) {
6296 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6297 for (
auto *FD : RD->
fields())
6298 if (!FD->isUnnamedBitField())
6303 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6304 Inits.back()->getEndLoc(),
false);
6305 NewInit->setType(Ty);
6310 llvm::SmallVector<QualType, 16> DestTypes;
6311 llvm::SmallVector<Expr *, 16> ArgExprs;
6312 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6313 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6314 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6315 InitTy = Entity.
getType().getNonReferenceType();
6325 DstIt = DestTypes.begin();
6328 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6330 Expr *generateInitLists() {
6331 assert(!ArgExprs.empty() &&
6332 "Call buildInitializerList to generate argument expressions.");
6333 ArgIt = ArgExprs.begin();
6335 return generateInitListsImpl(InitTy);
6336 llvm::SmallVector<Expr *>
Inits;
6337 while (ArgIt != ArgExprs.end())
6338 Inits.push_back(generateInitListsImpl(InitTy));
6341 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6342 Inits.back()->getEndLoc(),
false);
6343 llvm::APInt ArySize(64,
Inits.size());
6345 ArraySizeModifier::Normal, 0));
6357 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6364 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6368 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6388 if (
Init->getType()->isScalarType())
6391 InitListTransformer ILT(
SemaRef, Entity);
6393 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6401 Init->setInit(I, E);
6403 if (!ILT.buildInitializerList(E))
6406 size_t ExpectedSize = ILT.DestTypes.size();
6407 size_t ActualSize = ILT.ArgExprs.size();
6408 if (ExpectedSize == 0 && ActualSize == 0)
6415 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6417 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6418 << (int)(ExpectedSize < ActualSize) << InitTy
6419 << ExpectedSize << ActualSize;
6429 assert(ExpectedSize > 0 &&
6430 "The expected size of an incomplete array type must be at least 1.");
6432 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6440 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6441 if (ExpectedSize != ActualSize) {
6442 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6443 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6444 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6451 Init->resizeInits(Ctx, NewInit->getNumInits());
6452 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6453 Init->updateInit(Ctx, I, NewInit->getInit(I));
6461 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6471 StringRef AccessorName = CompName->
getName();
6472 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6474 unsigned Rows = MT->getNumRows();
6475 unsigned Cols = MT->getNumColumns();
6476 bool IsZeroBasedAccessor =
false;
6477 unsigned ChunkLen = 0;
6478 if (AccessorName.size() < 2)
6480 "length 4 for zero based: \'_mRC\' or "
6481 "length 3 for one-based: \'_RC\' accessor",
6484 if (AccessorName[0] ==
'_') {
6485 if (AccessorName[1] ==
'm') {
6486 IsZeroBasedAccessor =
true;
6493 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6496 if (AccessorName.size() % ChunkLen != 0) {
6497 const llvm::StringRef
Expected = IsZeroBasedAccessor
6498 ?
"zero based: '_mRC' accessor"
6499 :
"one-based: '_RC' accessor";
6504 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6505 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6506 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6508 bool HasRepeated =
false;
6510 unsigned NumComponents = 0;
6511 const char *Begin = AccessorName.data();
6513 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6514 const char *Chunk = Begin + I;
6515 char RowChar = 0, ColChar = 0;
6516 if (IsZeroBasedAccessor) {
6518 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6519 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6521 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6528 if (Chunk[0] !=
'_')
6530 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6537 bool IsDigitsError =
false;
6539 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6543 IsDigitsError =
true;
6547 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6551 IsDigitsError =
true;
6556 unsigned Row = RowChar -
'0';
6557 unsigned Col = ColChar -
'0';
6559 bool HasIndexingError =
false;
6560 if (IsZeroBasedAccessor) {
6562 if (!isZeroBasedIndex(Row)) {
6563 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6565 HasIndexingError =
true;
6567 if (!isZeroBasedIndex(Col)) {
6568 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6570 HasIndexingError =
true;
6574 if (!isOneBasedIndex(Row)) {
6575 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6577 HasIndexingError =
true;
6579 if (!isOneBasedIndex(Col)) {
6580 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6582 HasIndexingError =
true;
6589 if (HasIndexingError)
6595 bool HasBoundsError =
false;
6597 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6599 HasBoundsError =
true;
6602 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6604 HasBoundsError =
true;
6609 unsigned FlatIndex = Row * Cols + Col;
6610 if (Seen[FlatIndex])
6612 Seen[FlatIndex] =
true;
6615 if (NumComponents == 0 || NumComponents > 4) {
6616 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6621 QualType ElemTy = MT->getElementType();
6622 if (NumComponents == 1)
6628 for (Sema::ExtVectorDeclsType::iterator
6632 if ((*I)->getUnderlyingType() == VT)
6643 trackLocalResource(VDecl,
Init);
6645 const HLSLVkConstantIdAttr *ConstIdAttr =
6646 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6653 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
6663 int ConstantID = ConstIdAttr->getId();
6664 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6666 ConstIdAttr->getLocation());
6670 if (
C->getType()->getCanonicalTypeUnqualified() !=
6674 Context.getTrivialTypeSourceInfo(
6675 Init->getType(),
Init->getExprLoc()),
6694 if (!Params || Params->
size() != 1)
6707 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6708 if (TTP->hasDefaultArgument()) {
6709 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6712 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6713 if (NTTP->hasDefaultArgument()) {
6714 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6717 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6718 if (TTPD->hasDefaultArgument()) {
6719 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6726 return SemaRef.CheckTemplateIdType(
6728 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)
llvm::dxbc::PSV::SemanticKind SemanticKind
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckIntegerElementTypeShaderModel(Sema &S, CallExpr *TheCall, QualType ContainedType, SampleKind Kind)
static bool 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 handleInitialization(VarDecl *VDecl, Expr *&Init)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool diagnoseIndexType(QualType T, const ParsedAttr &AL)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool ActOnResourceMemberAccessExpr(MemberExpr *ME)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
QualType ActOnTemplateShorthand(TemplateDecl *Template, SourceLocation NameLoc)
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
QualType checkMatrixComponent(Sema &S, QualType baseType, ExprValueKind &VK, SourceLocation OpLoc, const IdentifierInfo *CompName, SourceLocation CompLoc)
bool IsConstantBufferElementCompatible(QualType T1)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
bool ActOnUninitializedVarDecl(VarDecl *D)
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
bool canHaveOverloadedBinOp(QualType Ty, BinaryOperatorKind Opc)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
void handleVkPushConstantAttr(Decl *D, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
NamedDecl * getConstantBufferConversionFunction(QualType Type, CXXRecordDecl *RD)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional< unsigned > Index)
QualType getInoutParameterType(QualType Ty)
bool diagnoseFloatType(QualType T, const ParsedAttr &AL)
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
std::optional< ExprResult > tryPerformConstantBufferConversion(Expr *BaseExpr)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
bool diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T, SourceLocation Loc)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
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)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
__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