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:
888 case SemanticKind::InstanceID:
889 return ST == llvm::Triple::Vertex && IsInput;
895bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
898 SemanticInfo &ActiveSemantic,
899 SemaHLSL::SemanticContext &SC) {
900 if (ActiveSemantic.Semantic ==
nullptr) {
901 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
902 if (ActiveSemantic.Semantic)
903 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
906 if (!ActiveSemantic.Semantic) {
912 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
913 ActiveSemantic.Semantic->getAttrName()->getName(),
914 ActiveSemantic.Index.value_or(0));
918 checkSemanticAnnotation(FD, D, A, SC);
919 OutputDecl->addAttr(A);
921 unsigned Location = ActiveSemantic.Index.value_or(0);
924 any(SC.CurrentIOType & IOType::In))) {
925 bool HasVkLocation =
false;
926 if (
auto *A = D->getAttr<HLSLVkLocationAttr>()) {
927 HasVkLocation = true;
928 Location = A->getLocation();
931 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
932 Diag(D->getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
935 SC.UsesExplicitVkLocations = HasVkLocation;
938 const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->getType());
939 unsigned ElementCount = AT ? AT->
getZExtSize() : 1;
940 ActiveSemantic.Index = Location + ElementCount;
942 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
943 for (
unsigned I = 0; I < ElementCount; ++I) {
944 Twine VariableName = BaseName.concat(Twine(Location + I));
946 auto [_, Inserted] = SC.ActiveSemantics.insert(VariableName.str());
948 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
949 << VariableName.str();
960 SemanticInfo &ActiveSemantic,
961 SemaHLSL::SemanticContext &SC) {
962 if (ActiveSemantic.Semantic ==
nullptr) {
963 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
964 if (ActiveSemantic.Semantic)
965 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
971 const RecordType *RT = dyn_cast<RecordType>(
T);
973 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
976 const RecordDecl *RD = RT->getDecl();
977 for (FieldDecl *Field : RD->
fields()) {
978 SemanticInfo Info = ActiveSemantic;
979 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
980 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
983 if (ActiveSemantic.Semantic)
984 ActiveSemantic = Info;
991 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
992 assert(ShaderAttr &&
"Entry point has no shader attribute");
993 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
997 case llvm::Triple::Pixel:
998 case llvm::Triple::Vertex:
999 case llvm::Triple::Geometry:
1000 case llvm::Triple::Hull:
1001 case llvm::Triple::Domain:
1002 case llvm::Triple::RayGeneration:
1003 case llvm::Triple::Intersection:
1004 case llvm::Triple::AnyHit:
1005 case llvm::Triple::ClosestHit:
1006 case llvm::Triple::Miss:
1007 case llvm::Triple::Callable:
1008 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1009 diagnoseAttrStageMismatch(NT, ST,
1010 {llvm::Triple::Compute,
1011 llvm::Triple::Amplification,
1012 llvm::Triple::Mesh});
1015 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1016 diagnoseAttrStageMismatch(WS, ST,
1017 {llvm::Triple::Compute,
1018 llvm::Triple::Amplification,
1019 llvm::Triple::Mesh});
1024 case llvm::Triple::Compute:
1025 case llvm::Triple::Amplification:
1026 case llvm::Triple::Mesh:
1027 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1029 << llvm::Triple::getEnvironmentTypeName(ST);
1032 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1034 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1035 }
else if (Ver < VersionTuple(6, 6)) {
1036 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1039 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1042 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1043 << WS << WS->getSpelledArgsCount() <<
"6.8";
1048 case llvm::Triple::RootSignature:
1049 llvm_unreachable(
"rootsig environment has no function entry point");
1051 llvm_unreachable(
"Unhandled environment in triple");
1054 SemaHLSL::SemanticContext InputSC = {};
1055 InputSC.CurrentIOType = IOType::In;
1056 SemaHLSL::SemanticContext OutputSC = {};
1057 OutputSC.CurrentIOType = IOType::Out;
1060 SemanticInfo ActiveSemantic;
1061 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1062 if (ActiveSemantic.Semantic)
1063 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1067 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1068 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1070 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1071 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1076 SemanticInfo ActiveSemantic;
1077 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1078 if (ActiveSemantic.Semantic)
1079 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1081 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1084void SemaHLSL::checkSemanticAnnotation(
1086 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC) {
1087 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1088 assert(ShaderAttr &&
"Entry point has no shader attribute");
1089 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1092 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1093 llvm::hlsl::SemanticInterpretation Interpretation =
1094 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1095 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
1096 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1099 case SemanticKind::DispatchThreadID:
1100 case SemanticKind::GroupID:
1101 case SemanticKind::GroupIndex:
1102 case SemanticKind::GroupThreadID:
1103 case SemanticKind::InstanceID:
1104 if (SemanticAttr->getSemanticIndex() != 0) {
1105 std::string PrettyName =
1106 "'" + SemanticAttr->getSemanticName().str() +
"'";
1107 Diag(SemanticAttr->getLoc(),
1108 diag::err_hlsl_semantic_indexing_not_supported)
1117void SemaHLSL::diagnoseAttrStageMismatch(
1118 const Attr *A, llvm::Triple::EnvironmentType Stage,
1119 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1120 SmallVector<StringRef, 8> StageStrings;
1121 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1122 [](llvm::Triple::EnvironmentType ST) {
1124 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1126 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1127 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1128 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1131void SemaHLSL::diagnoseSemanticStageMismatch(
1132 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1135 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1136 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1137 return Info.Stage == Stage;
1140 StringRef CurrentIOTypeName =
"patch constants or primitives";
1141 if (
any(CurrentIOType & IOType::In))
1142 CurrentIOTypeName =
"inputs";
1143 else if (
any(CurrentIOType & IOType::Out))
1144 CurrentIOTypeName =
"outputs";
1147 if (It == Allowed.end()) {
1148 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1149 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1150 << CurrentIOTypeName;
1154 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1155 if (!(AllowedIOTypes & CurrentIOType)) {
1156 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1157 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1158 << CurrentIOTypeName;
1163template <CastKind Kind>
1166 Ty = VTy->getElementType();
1171template <CastKind Kind>
1183 if (LHSFloat && RHSFloat) {
1211 if (LHSSigned == RHSSigned) {
1212 if (IsCompAssign || IntOrder >= 0)
1220 if (IntOrder != (LHSSigned ? 1 : -1)) {
1221 if (IsCompAssign || RHSSigned)
1229 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1230 if (IsCompAssign || LHSSigned)
1246 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1247 QualType NewTy = Ctx.getExtVectorType(
1257 return CK_FloatingCast;
1259 return CK_IntegralCast;
1261 return CK_IntegralToFloating;
1263 return CK_FloatingToIntegral;
1269 bool IsCompAssign) {
1276 if (!LVecTy && IsCompAssign) {
1278 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1280 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1282 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1287 unsigned EndSz = std::numeric_limits<unsigned>::max();
1290 LSz = EndSz = LVecTy->getNumElements();
1293 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1294 "one of the above should have had a value");
1298 if (IsCompAssign && LSz != EndSz) {
1300 diag::err_hlsl_vector_compound_assignment_truncation)
1301 << LHSType << RHSType;
1307 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1312 if (!IsCompAssign && !LVecTy)
1316 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1317 return Ctx.getCommonSugaredType(LHSType, RHSType);
1325 LElTy, RElTy, IsCompAssign);
1328 "HLSL Vectors can only contain integer or floating point types");
1330 LElTy, RElTy, IsCompAssign);
1335 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1336 "Called with non-logical operator");
1338 llvm::raw_svector_ostream OS(Buff);
1340 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1341 OS << NewFnName <<
"(";
1351std::pair<IdentifierInfo *, bool>
1354 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1361 return {DeclIdent,
Found};
1372 for (
auto &RootSigElement : RootElements)
1373 Elements.push_back(RootSigElement.getElement());
1377 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1379 SignatureDecl->setImplicit();
1385 if (RootSigOverrideIdent) {
1388 if (
SemaRef.LookupQualifiedName(R, DC))
1389 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1397struct PerVisibilityBindingChecker {
1400 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1404 llvm::dxbc::ShaderVisibility Vis;
1409 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1411 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1412 llvm::dxil::ResourceClass RC,
uint32_t Space,
1414 const hlsl::RootSignatureElement *Elem) {
1416 assert(BuilderIndex < Builders.size() &&
1417 "Not enough builders for visibility type");
1418 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1419 static_cast<const void *
>(Elem));
1421 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1422 "'All' visibility must come first");
1423 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1424 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1425 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1426 static_cast<const void *
>(Elem));
1428 ElemInfoMap.push_back({Elem,
Visibility,
false});
1431 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1432 auto It = llvm::lower_bound(
1434 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1435 assert(It->Elem == Elem &&
"Element not in map");
1439 bool checkOverlap() {
1440 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1441 return LHS.Elem < RHS.Elem;
1444 bool HadOverlap =
false;
1446 using llvm::hlsl::BindingInfoBuilder;
1447 auto ReportOverlap = [
this,
1448 &HadOverlap](
const BindingInfoBuilder &Builder,
1449 const llvm::hlsl::Binding &Reported) {
1453 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1454 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1455 const auto *PrevElem =
1456 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1458 ElemInfo &Info =
getInfo(Elem);
1463 Info.Diagnosed =
true;
1465 ElemInfo &PrevInfo =
getInfo(PrevElem);
1466 llvm::dxbc::ShaderVisibility CommonVis =
1467 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1470 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1471 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1472 << Reported.isUnbounded() << Reported.UpperBound
1477 this->S->
Diag(PrevElem->getLocation(),
1478 diag::note_hlsl_resource_range_here);
1481 for (BindingInfoBuilder &Builder : Builders)
1482 Builder.calculateBindingInfo(ReportOverlap);
1502 bool HadError =
false;
1503 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1504 uint32_t UpperBound) {
1506 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1507 << LowerBound << UpperBound;
1514 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1515 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1516 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1519 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1520 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1521 ReportError(Loc, 0, 0xfffffffe);
1524 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1525 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1526 ReportError(Loc, 0, 0xffffffef);
1529 const uint32_t Version =
1530 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1531 const uint32_t VersionEnum = Version - 1;
1532 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1534 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1541 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1542 if (
const auto *Descriptor =
1543 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1544 VerifyRegister(Loc, Descriptor->Reg.Number);
1545 VerifySpace(Loc, Descriptor->Space);
1547 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1549 ReportFlagError(Loc);
1550 }
else if (
const auto *Constants =
1551 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1552 VerifyRegister(Loc, Constants->Reg.Number);
1553 VerifySpace(Loc, Constants->Space);
1554 }
else if (
const auto *Sampler =
1555 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1556 VerifyRegister(Loc, Sampler->Reg.Number);
1557 VerifySpace(Loc, Sampler->Space);
1560 "By construction, parseFloatParam can't produce a NaN from a "
1561 "float_literal token");
1563 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1564 ReportError(Loc, 0, 16);
1565 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1566 ReportFloatError(Loc, -16.f, 15.99f);
1567 }
else if (
const auto *Clause =
1568 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1570 VerifyRegister(Loc, Clause->Reg.Number);
1571 VerifySpace(Loc, Clause->Space);
1573 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1577 ReportError(Loc, 1, 0xfffffffe);
1580 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1582 ReportFlagError(Loc);
1586 PerVisibilityBindingChecker BindingChecker(
this);
1587 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1592 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1593 if (
const auto *Descriptor =
1594 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1595 uint32_t LowerBound(Descriptor->Reg.Number);
1596 uint32_t UpperBound(LowerBound);
1598 BindingChecker.trackBinding(
1599 Descriptor->Visibility,
1600 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1601 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1602 }
else if (
const auto *Constants =
1603 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1604 uint32_t LowerBound(Constants->Reg.Number);
1605 uint32_t UpperBound(LowerBound);
1607 BindingChecker.trackBinding(
1608 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1609 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1610 }
else if (
const auto *Sampler =
1611 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1612 uint32_t LowerBound(Sampler->Reg.Number);
1613 uint32_t UpperBound(LowerBound);
1615 BindingChecker.trackBinding(
1616 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1617 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1618 }
else if (
const auto *Clause =
1619 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1622 UnboundClauses.emplace_back(Clause, &RootSigElem);
1623 }
else if (
const auto *Table =
1624 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1625 assert(UnboundClauses.size() == Table->NumClauses &&
1626 "Number of unbound elements must match the number of clauses");
1627 bool HasAnySampler =
false;
1628 bool HasAnyNonSampler =
false;
1629 uint64_t Offset = 0;
1630 bool IsPrevUnbound =
false;
1631 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1633 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1634 HasAnySampler =
true;
1636 HasAnyNonSampler =
true;
1638 if (HasAnySampler && HasAnyNonSampler)
1639 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1644 if (Clause->NumDescriptors == 0)
1648 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1650 Offset = Clause->Offset;
1652 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1653 Offset, Clause->NumDescriptors);
1655 if (IsPrevUnbound && IsAppending)
1656 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1657 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1658 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1661 Offset = RangeBound + 1;
1662 IsPrevUnbound = Clause->NumDescriptors ==
1663 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1666 uint32_t LowerBound(Clause->Reg.Number);
1667 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1668 LowerBound, Clause->NumDescriptors);
1670 BindingChecker.trackBinding(
1672 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1673 LowerBound, UpperBound, ClauseElem);
1675 UnboundClauses.clear();
1679 return BindingChecker.checkOverlap();
1684 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1689 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1690 if (RS->getSignatureIdent() != Ident) {
1691 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1695 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1701 if (
auto *SignatureDecl =
1702 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1709 llvm::VersionTuple SMVersion =
1714 uint32_t ZMax = 1024;
1715 uint32_t ThreadMax = 1024;
1716 if (IsDXIL && SMVersion.getMajor() <= 4) {
1719 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1729 diag::err_hlsl_numthreads_argument_oor)
1738 diag::err_hlsl_numthreads_argument_oor)
1747 diag::err_hlsl_numthreads_argument_oor)
1752 if (
X * Y * Z > ThreadMax) {
1753 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1770 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1778 if (SpelledArgsCount > 1 &&
1782 uint32_t Preferred = 0;
1783 if (SpelledArgsCount > 2 &&
1787 if (SpelledArgsCount > 2) {
1790 diag::err_attribute_power_of_two_in_range)
1791 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1796 if (Preferred < Min || Preferred >
Max) {
1798 diag::err_attribute_power_of_two_in_range)
1799 << AL <<
Min <<
Max << Preferred;
1802 }
else if (SpelledArgsCount > 1) {
1805 diag::err_attribute_power_of_two_in_range)
1806 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1810 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1813 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1818 diag::err_attribute_power_of_two_in_range)
1819 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1824 HLSLWaveSizeAttr *NewAttr =
1861 uint32_t Binding = 0;
1885 if (!
T->hasUnsignedIntegerRepresentation() ||
1886 (VT && VT->getNumElements() > 3)) {
1887 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1888 << AL <<
"uint/uint2/uint3";
1897 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1898 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1899 << AL <<
"float/float1/float2/float3/float4";
1908 std::optional<unsigned> Index) {
1910 QualType ValueType = VD->getType();
1911 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1915 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>())
1920 case SemanticKind::DispatchThreadID:
1921 case SemanticKind::GroupThreadID:
1922 case SemanticKind::GroupID:
1925 case SemanticKind::GroupIndex:
1927 case SemanticKind::Position:
1928 case SemanticKind::Target:
1931 case SemanticKind::VertexID: {
1932 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
1933 if (!ValueType->isUnsignedIntegerType() || SizeInBits != 32)
1934 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
1937 case SemanticKind::InstanceID: {
1938 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
1942 if (!ValueType->isUnsignedIntegerType() ||
1943 !(SizeInBits == 32 || (!IsSPIRV && SizeInBits == 16)))
1944 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
1948 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1956 uint32_t IndexValue(0), ExplicitIndex(0);
1959 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
1961 assert(IndexValue > 0 ? ExplicitIndex :
true);
1962 std::optional<unsigned> Index =
1963 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1966 if (Kind == SemanticKind::Arbitrary)
1974 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1975 << AL <<
"shader constant in a constant buffer";
1979 uint32_t SubComponent;
1989 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1994 if (IsAggregateTy) {
1995 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
1999 if ((Component * 32 + Size) > 128) {
2000 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2005 EltTy = VT->getElementType();
2007 if (Align > 32 && Component == 1) {
2010 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2024 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2027 llvm::Triple::EnvironmentType ShaderType;
2028 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2029 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2030 << AL << Str << ArgLoc;
2044 Expr *SampleCountExpr) {
2045 assert(AttrList.size() &&
"expected list of resource attributes");
2052 HLSLAttributedResourceType::Attributes ResAttrs;
2054 bool HasResourceClass =
false;
2055 bool HasResourceDimension =
false;
2056 for (
const Attr *A : AttrList) {
2061 case attr::HLSLResourceClass: {
2063 if (HasResourceClass) {
2065 ? diag::warn_duplicate_attribute_exact
2066 : diag::warn_duplicate_attribute)
2070 ResAttrs.ResourceClass = RC;
2071 HasResourceClass =
true;
2074 case attr::HLSLResourceDimension: {
2075 llvm::dxil::ResourceDimension RD =
2077 if (HasResourceDimension) {
2079 ? diag::warn_duplicate_attribute_exact
2080 : diag::warn_duplicate_attribute)
2084 ResAttrs.ResourceDimension = RD;
2085 HasResourceDimension =
true;
2088 case attr::HLSLIsROV:
2089 if (ResAttrs.IsROV) {
2093 ResAttrs.IsROV =
true;
2095 case attr::HLSLRawBuffer:
2096 if (ResAttrs.RawBuffer) {
2100 ResAttrs.RawBuffer =
true;
2102 case attr::HLSLIsArray:
2103 if (ResAttrs.IsArray) {
2107 ResAttrs.IsArray =
true;
2109 case attr::HLSLIsMultiSampled:
2110 if (ResAttrs.SampleCountExpr) {
2116 ResAttrs.SampleCountExpr =
2122 case attr::HLSLIsCounter:
2123 if (ResAttrs.IsCounter) {
2127 ResAttrs.IsCounter =
true;
2129 case attr::HLSLContainedType: {
2132 if (!ContainedTy.
isNull()) {
2134 ? diag::warn_duplicate_attribute_exact
2135 : diag::warn_duplicate_attribute)
2144 llvm_unreachable(
"unhandled resource attribute type");
2148 if (!HasResourceClass) {
2149 S.
Diag(AttrList.back()->getRange().getEnd(),
2150 diag::err_hlsl_missing_resource_class);
2155 Wrapped, ContainedTy, ResAttrs);
2157 if (LocInfo && ContainedTyInfo) {
2170 if (!
T->isHLSLResourceType()) {
2171 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2186 AttributeCommonInfo::AS_CXX11, 0, false ,
2191 case ParsedAttr::AT_HLSLResourceClass: {
2192 StringRef Identifier;
2194 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2199 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2200 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2201 <<
"ResourceClass" << Identifier;
2204 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2208 case ParsedAttr::AT_HLSLResourceDimension: {
2209 StringRef Identifier;
2211 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2215 llvm::dxil::ResourceDimension RD;
2216 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2218 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2219 <<
"ResourceDimension" << Identifier;
2222 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2226 case ParsedAttr::AT_HLSLIsROV:
2230 case ParsedAttr::AT_HLSLRawBuffer:
2234 case ParsedAttr::AT_HLSLIsCounter:
2238 case ParsedAttr::AT_HLSLIsArray:
2242 case ParsedAttr::AT_HLSLIsMultiSampled:
2246 case ParsedAttr::AT_HLSLContainedType: {
2248 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2254 assert(TSI &&
"no type source info for attribute argument");
2256 diag::err_incomplete_type))
2258 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2263 llvm_unreachable(
"unhandled HLSL attribute");
2266 HLSLResourcesTypeAttrs.emplace_back(A);
2272 if (!HLSLResourcesTypeAttrs.size())
2278 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2279 const HLSLAttributedResourceType *RT =
2286 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2288 HLSLResourcesTypeAttrs.clear();
2296 auto I = LocsForHLSLAttributedResources.find(RT);
2297 if (I != LocsForHLSLAttributedResources.end()) {
2298 LocInfo = I->second;
2299 LocsForHLSLAttributedResources.erase(I);
2308void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2309 const RecordType *RT) {
2317 "incomplete arrays inside user defined types are not supported");
2326 if (
const HLSLAttributedResourceType *AttrResType =
2327 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2332 Bindings.addDeclBindingInfo(VD, RC);
2333 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2339 collectResourceBindingsOnUserRecordDecl(VD, RT);
2351 bool SpecifiedSpace) {
2352 int RegTypeNum =
static_cast<int>(RegType);
2355 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2356 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2361 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2362 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2363 : ResourceClass::SRV;
2373 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2377 if (
const HLSLAttributedResourceType *AttrResType =
2378 HLSLAttributedResourceType::findHandleTypeOnResource(
2395 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2396 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2401 if (RegType == RegisterType::CBuffer)
2402 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2403 else if (RegType != RegisterType::C)
2404 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2408 if (RegType == RegisterType::C)
2409 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2411 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2421 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2429 bool RegisterTypesDetected[5] = {
false};
2430 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2433 if (HLSLResourceBindingAttr *
attr =
2434 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2437 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2438 int otherRegTypeNum =
static_cast<int>(otherRegType);
2440 diag::err_hlsl_duplicate_register_annotation)
2444 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2452 bool SpecifiedSpace) {
2457 "expecting VarDecl or HLSLBufferDecl");
2469 const uint64_t &Limit,
2472 uint64_t ArrayCount = 1) {
2477 if (StartSlot > Limit)
2481 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2484 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2485 Count = CAT->
getSize().getZExtValue();
2489 ArrayCount * Count);
2493 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2496 if (ResTy->getAttrs().ResourceClass != ResClass)
2500 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2501 if (EndSlot > Limit)
2505 StartSlot = EndSlot + 1;
2510 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2513 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2516 ResClass, Ctx, ArrayCount))
2523 ResClass, Ctx, ArrayCount))
2537 const uint64_t Limit = UINT32_MAX;
2538 if (SlotNum > Limit)
2543 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2546 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2547 uint64_t BaseSlot = SlotNum;
2555 return (BaseSlot > Limit);
2562 return (SlotNum > Limit);
2565 llvm_unreachable(
"unexpected decl type");
2569 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2571 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2572 Ty = IAT->getElementType();
2574 diag::err_incomplete_type))
2578 StringRef Slot =
"";
2579 StringRef Space =
"";
2583 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2593 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2599 SpaceLoc = Loc->
getLoc();
2602 if (Str.starts_with(
"space")) {
2604 SpaceLoc = Loc->
getLoc();
2613 std::optional<unsigned> SlotNum;
2614 unsigned SpaceNum = 0;
2617 if (!Slot.empty()) {
2619 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2622 if (RegType == RegisterType::I) {
2623 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2626 const StringRef SlotNumStr = Slot.substr(1);
2631 if (SlotNumStr.getAsInteger(10, N)) {
2632 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2640 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2649 if (!Space.starts_with(
"space")) {
2650 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2653 StringRef SpaceNumStr = Space.substr(5);
2654 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2655 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2660 if (SlotNum.has_value())
2665 HLSLResourceBindingAttr *NewAttr =
2666 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2668 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2692 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2694 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2698 Cur = AT->getModifiedType();
2709 ? attr::HLSLRowMajor
2710 : attr::HLSLColumnMajor;
2714 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2723 if (ExistingKind == AttrK) {
2724 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2726 Diag(AL.
getLoc(), diag::note_previous_attribute);
2730 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2731 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2733 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2738 if (AttrK == attr::HLSLRowMajor)
2739 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2740 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2751 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2753 if (
T.isNull() ||
T->isDependentType())
2758 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2759 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2807 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2811 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2812 unsigned CurrentShaderStageBit;
2817 bool ReportOnlyShaderStageIssues;
2820 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2821 static_assert(
sizeof(
unsigned) >= 4);
2822 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2823 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2824 "ShaderType is too big for this bitmap");
2827 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2828 CurrentShaderEnvironment = ShaderType;
2829 CurrentShaderStageBit = (1 << bitmapIndex);
2832 void SetUnknownShaderStageContext() {
2833 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2834 CurrentShaderStageBit = (1 << 31);
2837 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2838 return CurrentShaderEnvironment;
2841 bool InUnknownShaderStageContext()
const {
2842 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2846 void AddToScannedFunctions(
const FunctionDecl *FD) {
2847 unsigned &ScannedStages = ScannedDecls[FD];
2848 ScannedStages |= CurrentShaderStageBit;
2851 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2853 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2854 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2857 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2858 return ScannerStages & CurrentShaderStageBit;
2861 static bool NeverBeenScanned(
unsigned ScannedStages) {
2862 return ScannedStages == 0;
2866 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2867 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2869 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2870 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2873 DiagnoseHLSLAvailability(Sema &SemaRef)
2875 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2876 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2879 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2880 void RunOnFunction(
const FunctionDecl *FD);
2882 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2883 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2885 HandleFunctionOrMethodRef(FD, DRE);
2889 bool VisitMemberExpr(MemberExpr *ME)
override {
2890 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2892 HandleFunctionOrMethodRef(FD, ME);
2897void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2900 "expected DeclRefExpr or MemberExpr");
2902 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
2903 CheckDeclAvailability(
2908 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
2909 DeclsToScan.push_back(FDWithBody);
2912void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2917 llvm::Triple::EnvironmentType::Library;
2926 DeclContextsToScan.push_back(TU);
2928 while (!DeclContextsToScan.empty()) {
2929 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2930 for (
auto &D : DC->
decls()) {
2937 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2938 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2943 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2948 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2949 if (!IsLibraryShader && FD->
getName() == EntryName) {
2952 diag::err_hlsl_ambiguous_entry_point)
2954 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
2960 SetShaderStageContext(ShaderAttr->getType());
2969 for (
const auto *Redecl : FD->
redecls()) {
2970 if (Redecl->isInExportDeclContext()) {
2977 SetUnknownShaderStageContext();
2984 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
2991void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2992 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2993 DeclsToScan.push_back(FD);
2995 while (!DeclsToScan.empty()) {
3003 const unsigned ScannedStages = GetScannedStages(FD);
3004 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3007 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3009 AddToScannedFunctions(FD);
3014bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3015 const AvailabilityAttr *AA) {
3020 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3021 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3024 llvm::Triple::EnvironmentType AttrEnv =
3025 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3027 return CurrentEnv == AttrEnv;
3030const AvailabilityAttr *
3031DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3032 AvailabilityAttr
const *PartialMatch =
nullptr;
3036 for (
const auto *A : D->
attrs()) {
3037 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3038 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3039 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3040 StringRef TargetPlatform =
3044 if (AttrPlatform == TargetPlatform) {
3046 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3048 PartialMatch = Avail;
3052 return PartialMatch;
3057void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3058 const AvailabilityAttr *AA,
3077 if (ReportOnlyShaderStageIssues)
3083 if (InUnknownShaderStageContext())
3088 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3089 VersionTuple Introduced = AA->getIntroduced();
3098 llvm::StringRef PlatformName(
3101 llvm::StringRef CurrentEnvStr =
3102 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3104 llvm::StringRef AttrEnvStr =
3105 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3106 bool UseEnvironment = !AttrEnvStr.empty();
3108 if (EnvironmentMatches) {
3109 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3110 <<
Range << D << PlatformName << Introduced.getAsString()
3111 << UseEnvironment << CurrentEnvStr;
3113 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3117 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3118 << D << PlatformName << Introduced.getAsString()
3120 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3127 if (!DefaultCBufferDecls.empty()) {
3130 DefaultCBufferDecls);
3133 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3137 for (
const Decl *VD : DefaultCBufferDecls) {
3138 const HLSLResourceBindingAttr *RBA =
3139 VD->
getAttr<HLSLResourceBindingAttr>();
3140 if (RBA && RBA->hasRegisterSlot() &&
3141 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3148 SemaRef.Consumer.HandleTopLevelDecl(DG);
3150 diagnoseAvailabilityViolations(TU);
3159 "expected member expr to have resource record type or array of them");
3165 const Expr *NonConstIndexExpr =
nullptr;
3168 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3169 if (!NonConstIndexExpr)
3177 diag::err_hlsl_resource_member_array_access_not_constant);
3181 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3182 const Expr *IdxExpr = ASE->getIdx();
3184 NonConstIndexExpr = IdxExpr;
3186 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3187 E = SubME->getBase();
3188 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3189 E = ICE->getSubExpr();
3191 llvm_unreachable(
"unexpected expr type in resource member access");
3200 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3203 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3206 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3210 [[maybe_unused]]
bool LookupSucceeded =
3211 SemaRef.LookupQualifiedName(ConvR, RD);
3212 assert(LookupSucceeded);
3221std::optional<ExprResult>
3224 const HLSLAttributedResourceType *ResTy =
3225 HLSLAttributedResourceType::findHandleTypeOnResource(
3226 BaseType.getTypePtr());
3228 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3229 return std::nullopt;
3231 QualType TemplateType = ResTy->getContainedType();
3235 assert(NamedConversionDecl &&
3236 "Could not find conversion function for ConstantBuffer.");
3237 auto *ConversionDecl =
3240 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3252 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3255 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3262 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3265 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3290 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3305 if (!BaseType->isFloat32Type())
3306 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3307 << ArgOrdinal << 5 << 0
3317 BaseType = VT->getElementType();
3319 BaseType = MT->getElementType();
3321 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3322 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3323 << ArgOrdinal << 5 << 0
3337 if (!BaseType->isDoubleType()) {
3340 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3341 << ArgOrdinal << PassedType;
3348 unsigned ArgIndex) {
3349 auto *Arg = TheCall->
getArg(ArgIndex);
3351 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3354 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3368 << (ArgIndex + 1) << LValueTy;
3378 if (VecTy->getElementType()->isDoubleType())
3379 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3380 << ArgOrdinal << 1 << 0 << 1
3390 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3391 << ArgOrdinal << 5 << 1
3400 if (VecTy->getElementType()->isUnsignedIntegerType())
3403 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3404 << ArgOrdinal << 4 << 3 << 0
3413 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3414 << ArgOrdinal << 5 << 3
3420 unsigned ArgOrdinal,
unsigned Width) {
3423 ArgTy = VTy->getElementType();
3425 uint64_t ElementBitCount =
3427 if (ElementBitCount != Width) {
3429 diag::err_integer_incorrect_bit_count)
3430 << Width << ElementBitCount;
3441 else if (
auto *MatTyA =
3444 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3450 unsigned ArgIndex) {
3459 diag::err_typecheck_expect_scalar_or_vector)
3460 << ArgType << Scalar;
3467 QualType Scalar,
unsigned ArgIndex) {
3478 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3491 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3492 << ArgType << Scalar;
3497 unsigned ArgIndex) {
3502 if (!(ArgType->isScalarType() ||
3503 (VTy && VTy->getElementType()->isScalarType()))) {
3505 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3513 unsigned ArgIndex) {
3516 if (ArgType->isDependentType())
3520 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3521 ElementType = VectorTy->getElementType();
3523 ElementType = MatrixTy->getElementType();
3525 if (ElementType->isBooleanType())
3528 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3530 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3535 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3543 unsigned ArgIndex) {
3545 assert(ArgIndex < TheCall->getNumArgs());
3553 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3578 diag::err_typecheck_call_different_arg_types)
3597 Arg1ScalarTy = VTy->getElementType();
3601 Arg2ScalarTy = VTy->getElementType();
3604 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3605 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3615 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3617 diag::err_typecheck_vector_lengths_not_equal)
3623 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3625 diag::err_typecheck_vector_lengths_not_equal)
3645 Arg1ScalarTy = MTy->getElementType();
3649 Arg2ScalarTy = MTy->getElementType();
3652 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3653 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3658 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
3660 for (
Expr *Arg : {Arg1, Arg2}) {
3663 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
3665 diag::err_typecheck_vector_lengths_not_equal)
3667 << Arg->getSourceRange();
3683 unsigned ArgIndex) {
3688 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3691 unsigned int ActualDim = 1;
3693 ActualDim = VTy->getNumElements();
3694 IndexTy = VTy->getElementType();
3698 diag::err_typecheck_expect_int)
3704 const HLSLAttributedResourceType *ResTy =
3706 assert(ResTy &&
"Resource argument must be a resource");
3707 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3709 unsigned int ExpectedDim = 1;
3710 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3712 (ResAttrs.IsArray ? 1 : 0);
3714 if (ActualDim != ExpectedDim) {
3716 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3727 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3731 const HLSLAttributedResourceType *ResTy =
3735 diag::err_typecheck_expect_hlsl_resource)
3739 if (Check && Check(ResTy)) {
3741 diag::err_invalid_hlsl_resource_type)
3751 "expected resource handle type");
3752 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3753 auto MainAttrs = MainResType->getAttrs();
3754 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3755 MainAttrs.IsCounter =
true;
3757 MainResType->getContainedType(),
3768 return "SampleBias";
3770 return "SampleGrad";
3772 return "SampleLevel";
3776 return "SampleCmpLevelZero";
3778 llvm_unreachable(
"Invalid SampleKind");
3788 if (!MD || !MD->getDeclName().isIdentifier())
3795 return MD->getName();
3803 return VecTy->getElementType();
3804 return ContainedType;
3812 StringRef DefaultName) {
3817 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
3844 if (SMVersion >= VersionTuple(6, 7))
3847 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
3849 << ContainedType << SMVersion.getAsString();
3854 bool IncludeArraySlice =
true) {
3857 [](
const HLSLAttributedResourceType *ResType) {
3858 return ResType->getAttrs().ResourceDimension ==
3859 llvm::dxil::ResourceDimension::Unknown;
3865 [](
const HLSLAttributedResourceType *ResType) {
3866 return ResType->getAttrs().ResourceClass !=
3867 llvm::hlsl::ResourceClass::Sampler;
3875 unsigned ExpectedDim =
3877 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
3906 unsigned NextIdx = 3;
3918 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3922 std::optional<llvm::APSInt> ComponentOpt =
3925 int64_t ComponentVal = ComponentOpt->getSExtValue();
3926 if (ComponentVal != 0) {
3929 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3930 "The component is not in the expected range.");
3932 diag::err_hlsl_gathercmp_invalid_component)
3942 const HLSLAttributedResourceType *ResourceTy =
3945 unsigned ExpectedDim =
3948 &S, TheCall->
getArg(NextIdx),
3954 assert(ResourceTy->hasContainedType() &&
3955 "Expecting a contained type for resource with a dimension "
3957 QualType ReturnType = ResourceTy->getContainedType();
3960 IsCmp ?
"GatherCmp" :
"Gather"))
3965 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3971 ReturnType = VecTy->getElementType();
3984 [](
const HLSLAttributedResourceType *ResType) {
3985 return ResType->getAttrs().ResourceDimension ==
3986 llvm::dxil::ResourceDimension::Unknown;
3996 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4003 unsigned ResourceDim =
4005 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4021 TheCall->
setType(ResourceTy->getContainedType());
4031 [](
const HLSLAttributedResourceType *ResType) {
4032 return !ResType->isMultiSampled();
4041 unsigned ResourceDim =
4043 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4061 TheCall->
setType(ResourceTy->getContainedType());
4066 unsigned MinArgs, MaxArgs;
4094 const HLSLAttributedResourceType *ResourceTy =
4096 unsigned ExpectedDim =
4099 unsigned NextIdx = 3;
4124 &S, TheCall->
getArg(NextIdx),
4137 assert(ResourceTy->hasContainedType() &&
4138 "Expecting a contained type for resource with a dimension "
4140 QualType ReturnType = ResourceTy->getContainedType();
4151 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4168 unsigned MinArgs,
unsigned MaxArgs,
4170 bool ReportsOriginalValue) {
4171 if (MinArgs == MaxArgs) {
4174 }
else if (TheCall->
getNumArgs() < MinArgs) {
4175 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4185 const bool DestIsOK =
4191 diag::err_builtin_invalid_arg_type)
4205 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4221 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4227 const unsigned NumArgs = TheCall->
getNumArgs();
4228 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4239 switch (BuiltinID) {
4240 case Builtin::BI__builtin_hlsl_adduint64: {
4241 if (
SemaRef.checkArgCount(TheCall, 2))
4255 if (NumElementsArg != 2 && NumElementsArg != 4) {
4257 << 1 << 64 << NumElementsArg * 32;
4271 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4272 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4279 QualType ContainedTy = ResourceTy->getContainedType();
4280 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4283 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4288 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4289 if (
SemaRef.checkArgCount(TheCall, 3) ||
4296 "expected pointer type for second argument");
4303 diag::err_invalid_use_of_array_type);
4307 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4310 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4315 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4316 if (
SemaRef.checkArgCount(TheCall, 2) ||
4318 SemaRef.getASTContext().IntTy))
4325 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4326 if (
SemaRef.checkArgCount(TheCall, 3) ||
4329 SemaRef.getASTContext().UnsignedIntTy) ||
4331 SemaRef.getASTContext().UnsignedIntTy) ||
4337 QualType ReturnType = ResourceTy->getContainedType();
4342 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4343 if (
SemaRef.checkArgCount(TheCall, 4) ||
4346 SemaRef.getASTContext().UnsignedIntTy) ||
4348 SemaRef.getASTContext().UnsignedIntTy) ||
4354 "expected pointer type for second argument");
4361 diag::err_invalid_use_of_array_type);
4367 case Builtin::BI__builtin_hlsl_resource_load_level:
4369 case Builtin::BI__builtin_hlsl_resource_load_ms:
4371 case Builtin::BI__builtin_hlsl_resource_sample:
4373 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4375 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4377 case Builtin::BI__builtin_hlsl_resource_sample_level:
4379 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4381 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4383 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4384 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4386 case Builtin::BI__builtin_hlsl_resource_gather:
4388 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4390 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4391 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4397 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4398 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4404 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4405 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4411 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4412 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4418 TheCall->
setType(CounterHandleTy);
4421 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4422 if (
SemaRef.checkArgCount(TheCall, 2) ||
4425 SemaRef.getASTContext().UnsignedIntTy))
4433 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4434 if (
SemaRef.checkArgCount(TheCall, 1) ||
4442 TheCall->
setType(CounterHandleTy);
4445 case Builtin::BI__builtin_hlsl_and:
4446 case Builtin::BI__builtin_hlsl_or: {
4447 if (
SemaRef.checkArgCount(TheCall, 2))
4461 case Builtin::BI__builtin_hlsl_all:
4462 case Builtin::BI__builtin_hlsl_any: {
4463 if (
SemaRef.checkArgCount(TheCall, 1))
4469 case Builtin::BI__builtin_hlsl_asdouble: {
4470 if (
SemaRef.checkArgCount(TheCall, 2))
4474 SemaRef.Context.UnsignedIntTy,
4479 SemaRef.Context.UnsignedIntTy,
4488 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4489 if (
SemaRef.BuiltinElementwiseTernaryMath(
4495 case Builtin::BI__builtin_hlsl_dot: {
4497 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4503 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4504 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4505 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4515 EltTy = VecTy->getElementType();
4516 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4529 case Builtin::BI__builtin_hlsl_select: {
4530 if (
SemaRef.checkArgCount(TheCall, 3))
4539 if (VTy && VTy->getElementType()->isBooleanType() &&
4543 if (MTy && MTy->getElementType()->isBooleanType() &&
4548 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4549 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4550 if (
SemaRef.checkArgCount(TheCall, 1))
4556 diag::err_builtin_invalid_arg_type)
4559 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4563 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4564 case Builtin::BI__builtin_hlsl_elementwise_frac:
4565 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4566 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4567 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4568 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4569 if (
SemaRef.checkArgCount(TheCall, 1))
4574 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4578 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4579 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4580 if (
SemaRef.checkArgCount(TheCall, 1))
4585 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4590 case Builtin::BI__builtin_hlsl_mad: {
4591 if (
SemaRef.BuiltinElementwiseTernaryMath(
4597 case Builtin::BI__builtin_hlsl_mul: {
4598 if (
SemaRef.checkArgCount(TheCall, 2))
4608 return VTy->getElementType();
4610 return MTy->getElementType();
4614 QualType EltTy0 = getElemType(Ty0);
4623 if (IsVec0 && IsMat1) {
4626 }
else if (IsMat0 && IsVec1) {
4630 assert(IsMat0 && IsMat1);
4640 case Builtin::BI__builtin_elementwise_fma: {
4641 if (
SemaRef.checkArgCount(TheCall, 3) ||
4656 case Builtin::BI__builtin_hlsl_transpose: {
4657 if (
SemaRef.checkArgCount(TheCall, 1))
4666 << 1 << 3 << 0 << 0 << ArgTy;
4671 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4675 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4676 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4684 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4685 if (
SemaRef.checkArgCount(TheCall, 1))
4699 unsigned NumElts = VecTy->getNumElements();
4709 case Builtin::BI__builtin_hlsl_wave_active_max:
4710 case Builtin::BI__builtin_hlsl_wave_active_min:
4711 case Builtin::BI__builtin_hlsl_wave_active_sum:
4712 case Builtin::BI__builtin_hlsl_wave_active_product: {
4713 if (
SemaRef.checkArgCount(TheCall, 1))
4726 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4727 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4728 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4729 if (
SemaRef.checkArgCount(TheCall, 1))
4744 (VTy && VTy->getElementType()->isIntegerType()))) {
4746 diag::err_builtin_invalid_arg_type)
4747 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4755 case Builtin::BI__builtin_hlsl_interlocked_add:
4756 case Builtin::BI__builtin_hlsl_interlocked_and:
4757 case Builtin::BI__builtin_hlsl_interlocked_max:
4758 case Builtin::BI__builtin_hlsl_interlocked_min:
4759 case Builtin::BI__builtin_hlsl_interlocked_or:
4760 case Builtin::BI__builtin_hlsl_interlocked_xor:
4766 case Builtin::BI__builtin_hlsl_interlocked_exchange:
4772 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
4778 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
4784 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
4790 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
4798 case Builtin::BI__builtin_elementwise_bitreverse: {
4806 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4807 if (
SemaRef.checkArgCount(TheCall, 1))
4812 if (!(
ArgType->isScalarType())) {
4814 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4819 if (!(
ArgType->isBooleanType())) {
4821 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4828 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4829 if (
SemaRef.checkArgCount(TheCall, 2))
4837 diag::err_typecheck_convert_incompatible)
4838 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4851 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
4852 if (
SemaRef.checkArgCount(TheCall, 1))
4861 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4862 if (
SemaRef.checkArgCount(TheCall, 0))
4866 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4867 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4868 if (
SemaRef.checkArgCount(TheCall, 1))
4881 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4882 case Builtin::BI__builtin_hlsl_quad_read_across_y:
4883 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
4884 if (
SemaRef.checkArgCount(TheCall, 1))
4896 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4897 if (
SemaRef.checkArgCount(TheCall, 3))
4903 SemaRef.Context.UnsignedIntTy, 1) ||
4905 SemaRef.Context.UnsignedIntTy, 2))
4913 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4914 if (
SemaRef.checkArgCount(TheCall, 1))
4921 case Builtin::BI__builtin_elementwise_acos:
4922 case Builtin::BI__builtin_elementwise_asin:
4923 case Builtin::BI__builtin_elementwise_atan:
4924 case Builtin::BI__builtin_elementwise_atan2:
4925 case Builtin::BI__builtin_elementwise_ceil:
4926 case Builtin::BI__builtin_elementwise_cos:
4927 case Builtin::BI__builtin_elementwise_cosh:
4928 case Builtin::BI__builtin_elementwise_exp:
4929 case Builtin::BI__builtin_elementwise_exp2:
4930 case Builtin::BI__builtin_elementwise_exp10:
4931 case Builtin::BI__builtin_elementwise_floor:
4932 case Builtin::BI__builtin_elementwise_fmod:
4933 case Builtin::BI__builtin_elementwise_log:
4934 case Builtin::BI__builtin_elementwise_log2:
4935 case Builtin::BI__builtin_elementwise_log10:
4936 case Builtin::BI__builtin_elementwise_pow:
4937 case Builtin::BI__builtin_elementwise_roundeven:
4938 case Builtin::BI__builtin_elementwise_sin:
4939 case Builtin::BI__builtin_elementwise_sinh:
4940 case Builtin::BI__builtin_elementwise_sqrt:
4941 case Builtin::BI__builtin_elementwise_tan:
4942 case Builtin::BI__builtin_elementwise_tanh:
4943 case Builtin::BI__builtin_elementwise_trunc: {
4949 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4950 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4951 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4952 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4953 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4958 std::optional<llvm::APSInt> Offset =
4960 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4962 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4968 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4969 if (
SemaRef.checkArgCount(TheCall, 1))
4980 ArgTy = VTy->getElementType();
4983 diag::err_builtin_invalid_arg_type)
4992 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4993 if (
SemaRef.checkArgCount(TheCall, 1))
5008 WorkList.push_back(BaseTy);
5009 while (!WorkList.empty()) {
5011 T =
T.getCanonicalType().getUnqualifiedType();
5012 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5020 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
5021 llvm::append_range(List, ElementFields);
5026 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5027 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5030 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5031 List.insert(List.end(), MT->getNumElementsFlattened(),
5032 MT->getElementType());
5035 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5036 if (RD->isStandardLayout())
5037 RD = RD->getStandardLayoutBaseWithFields();
5041 if (RD->
isUnion() || !RD->isAggregate()) {
5047 for (
const auto *FD : RD->
fields())
5048 if (!FD->isUnnamedBitField())
5049 FieldTypes.push_back(FD->
getType());
5051 std::reverse(FieldTypes.begin(), FieldTypes.end());
5052 llvm::append_range(WorkList, FieldTypes);
5056 if (!RD->isStandardLayout()) {
5058 for (
const auto &
Base : RD->bases())
5059 FieldTypes.push_back(
Base.getType());
5060 std::reverse(FieldTypes.begin(), FieldTypes.end());
5061 llvm::append_range(WorkList, FieldTypes);
5096 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5102 int ArraySize = VT->getNumElements();
5107 QualType ElTy = VT->getElementType();
5111 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5127 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5136 return llvm::equal(T1Types, T2Types,
5138 return SemaRef.IsLayoutCompatible(LHS, RHS);
5147 bool HadError =
false;
5149 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5157 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5158 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5159 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5160 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5162 if (NSpellingIdx != OSpellingIdx) {
5164 diag::err_hlsl_param_qualifier_mismatch)
5165 << NDAttr << NewParam;
5181 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5196 llvm_unreachable(
"HLSL doesn't support pointers.");
5199 llvm_unreachable(
"HLSL doesn't support complex types.");
5201 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5203 llvm_unreachable(
"Should have returned before this");
5213 llvm_unreachable(
"HLSL doesn't support complex types.");
5215 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5220 llvm_unreachable(
"HLSL doesn't support pointers.");
5222 llvm_unreachable(
"Should have returned before this");
5228 llvm_unreachable(
"HLSL doesn't support pointers.");
5231 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5235 llvm_unreachable(
"HLSL doesn't support complex types.");
5238 llvm_unreachable(
"Unhandled scalar cast");
5259 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5265 SrcTy = SrcMatTy->getElementType();
5270 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5271 if (DestTypes[I]->isUnionType())
5303 if (SrcTypes.size() < DestTypes.size())
5306 unsigned SrcSize = SrcTypes.size();
5307 unsigned DstSize = DestTypes.size();
5309 for (I = 0; I < DstSize && I < SrcSize; I++) {
5310 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5318 for (; I < SrcSize; I++) {
5319 if (SrcTypes[I]->isUnionType())
5339 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5340 "We should not get here without a parameter modifier expression");
5341 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5348 << Arg << (IsInOut ? 1 : 0);
5354 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5361 << Arg << (IsInOut ? 1 : 0);
5373 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5379 auto *OpV =
new (Ctx)
5385 tok::equal, ArgOpV, OpV);
5401 "Pointer and reference types cannot be inout or out parameters");
5402 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5418 for (
const auto *FD : RD->
fields()) {
5422 assert(RD->getNumBases() <= 1 &&
5423 "HLSL doesn't support multiple inheritance");
5424 return RD->getNumBases()
5429 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5430 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5442 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5447 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5453 if (
Decl->getType().hasAddressSpace())
5456 if (
Decl->getType()->isDependentType())
5468 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5482 llvm::Triple::Vulkan;
5483 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5484 if (HasDeclaredAPushConstant)
5490 HasDeclaredAPushConstant =
true;
5517class StructBindingContext {
5520 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5521 unsigned RegBindingOffset[4];
5524 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5525 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5526 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5527 static_cast<unsigned>(RegisterType::Sampler) == 3,
5528 "unexpected register type values");
5531 HLSLVkBindingAttr *VkBindingAttr;
5532 unsigned VkBindingOffset;
5537 StructBindingContext(
VarDecl *VD) {
5538 for (
unsigned i = 0; i < 4; ++i) {
5539 RegBindingsAttrs[i] =
nullptr;
5540 RegBindingOffset[i] = 0;
5542 VkBindingAttr =
nullptr;
5543 VkBindingOffset = 0;
5549 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5551 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5554 RegBindingsAttrs[RegTypeIdx] = RBA;
5559 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5560 VkBindingAttr = VBA;
5567 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5568 unsigned Range,
bool HasCounter) {
5569 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5571 if (VkBindingAttr) {
5572 unsigned Offset = VkBindingOffset;
5573 VkBindingOffset +=
Range;
5574 return HLSLVkBindingAttr::CreateImplicit(
5575 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5576 VkBindingAttr->getRange());
5579 HLSLResourceBindingAttr *RBA =
5580 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5581 HLSLResourceBindingAttr *NewAttr =
nullptr;
5583 if (RBA && RBA->hasRegisterSlot()) {
5586 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5587 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5589 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5590 StringRef NewSlotNumberStr =
5592 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5593 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5594 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5598 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5599 NewAttr->setBinding(RegType, std::nullopt,
5600 RBA ? RBA->getSpaceNumber() : 0);
5604 NewAttr->setImplicitCounterBindingOrderID(
5613static void createGlobalResourceDeclForStruct(
5615 QualType ResTy, StructBindingContext &BindingCtx) {
5617 "expected resource type or array of resources");
5628 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5629 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5634 const HLSLAttributedResourceType *ResHandleTy =
5635 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5639 Attr *BindingAttr = BindingCtx.createBindingAttr(
5641 ResDecl->
addAttr(BindingAttr);
5642 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5651 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5658static void handleArrayOfStructWithResources(
5660 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5665static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5667 EmbeddedResourceNameBuilder &NameBuilder,
5668 StructBindingContext &BindingCtx) {
5671 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5678 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5692 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5695 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5697 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5699 "resource arrays should have been already handled");
5700 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5709handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5711 EmbeddedResourceNameBuilder &NameBuilder,
5712 StructBindingContext &BindingCtx) {
5720 if (!SubCAT && !ElementRD)
5723 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5726 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5729 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5742void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5743 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5744 StructBindingContext BindingCtx(VD);
5748 "Expected non-resource struct or array type");
5751 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5755 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5756 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5764 if (
SemaRef.RequireCompleteType(
5767 diag::err_typecheck_decl_incomplete_type)) {
5781 DefaultCBufferDecls.push_back(VD);
5786 collectResourceBindingsOnVarDecl(VD);
5788 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5800 processExplicitBindingsOnDecl(VD);
5838 handleGlobalStructOrArrayOfWithResources(VD);
5842 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5851 "expected resource record type");
5867 const char *CreateMethodName;
5869 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5870 :
"__createFromBinding";
5872 CreateMethodName = HasCounter
5873 ?
"__createFromImplicitBindingWithImplicitCounter"
5874 :
"__createFromImplicitBinding";
5879 if (!CreateMethod) {
5884 "create method lookup should always succeed for built-in resource "
5893 Args.push_back(RegSlot);
5901 Args.push_back(OrderId);
5907 Args.push_back(Space);
5911 Args.push_back(RangeSize);
5915 Args.push_back(Index);
5917 StringRef VarName = VD->
getName();
5925 Args.push_back(NameCast);
5933 Args.push_back(CounterId);
5956 SemaRef.CheckCompleteVariableDeclaration(VD);
5962 "expected array of resource records");
5983 lookupMethod(
SemaRef, ResourceDecl,
5984 HasCounter ?
"__createFromBindingWithImplicitCounter"
5985 :
"__createFromBinding",
5989 CreateMethod = lookupMethod(
5991 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5992 :
"__createFromImplicitBinding",
6035std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6036 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6037 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6038 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6039 if (!TrueInfo || !FalseInfo)
6040 return std::nullopt;
6041 if (*TrueInfo != *FalseInfo)
6042 return std::nullopt;
6046 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6055 if (
const auto *AttrResType =
6056 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6058 return Bindings.getDeclBindingInfo(VD, RC);
6065void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6066 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6069 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6074 if (*ExprBinding ==
nullptr)
6077 auto PrevBinding = Assigns.find(VD);
6078 if (PrevBinding == Assigns.end()) {
6080 Assigns.insert({VD, *ExprBinding});
6085 if (*ExprBinding != PrevBinding->second) {
6087 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6089 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6100 "expected LHS to be a resource record or array of resource records");
6101 if (Opc != BO_Assign)
6106 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6114 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6119 trackLocalResource(VD, RHSExpr);
6136void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6138 "expected global variable that contains HLSL resource");
6141 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6142 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6143 ? ResourceClass::CBuffer
6144 : ResourceClass::SRV);
6157 if (
const HLSLAttributedResourceType *AttrResType =
6158 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6159 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6164 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6165 collectResourceBindingsOnUserRecordDecl(VD, RT);
6171void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6174 bool HasBinding =
false;
6175 for (Attr *A : VD->
attrs()) {
6178 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6179 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6182 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6183 if (!RBA || !RBA->hasRegisterSlot())
6188 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6189 "never have an attribute created");
6191 if (RT == RegisterType::C) {
6192 if (Bindings.hasBindingInfoForDecl(VD))
6194 diag::warn_hlsl_user_defined_type_missing_member)
6195 <<
static_cast<int>(RT);
6203 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6208 diag::warn_hlsl_user_defined_type_missing_member)
6209 <<
static_cast<int>(RT);
6217class InitListTransformer {
6221 QualType *DstIt =
nullptr;
6222 Expr **ArgIt =
nullptr;
6228 bool castInitializer(Expr *E) {
6229 assert(DstIt &&
"This should always be something!");
6230 if (DstIt == DestTypes.end()) {
6232 ArgExprs.push_back(E);
6237 DstIt = DestTypes.begin();
6240 Ctx, *DstIt,
false);
6245 ArgExprs.push_back(
Init);
6250 bool buildInitializerListImpl(Expr *E) {
6252 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6253 for (
auto *SubInit :
Init->inits())
6254 if (!buildInitializerListImpl(SubInit))
6264 return castInitializer(E);
6278 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6283 for (uint64_t I = 0; I <
Size; ++I) {
6285 SizeTy, SourceLocation());
6291 if (!castInitializer(ElExpr.
get()))
6296 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6297 unsigned Rows = MTy->getNumRows();
6298 unsigned Cols = MTy->getNumColumns();
6299 QualType ElemTy = MTy->getElementType();
6301 for (
unsigned R = 0;
R < Rows; ++
R) {
6302 for (
unsigned C = 0;
C < Cols; ++
C) {
6315 if (!castInitializer(ElExpr.
get()))
6323 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6327 for (uint64_t I = 0; I <
Size; ++I) {
6329 SizeTy, SourceLocation());
6334 if (!buildInitializerListImpl(ElExpr.
get()))
6341 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6342 RecordDecls.push_back(RD);
6343 while (RecordDecls.back()->getNumBases()) {
6344 CXXRecordDecl *D = RecordDecls.back();
6346 "HLSL doesn't support multiple inheritance");
6347 RecordDecls.push_back(
6350 while (!RecordDecls.empty()) {
6351 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6352 for (
auto *FD : RD->
fields()) {
6353 if (FD->isUnnamedBitField())
6361 if (!buildInitializerListImpl(Res.
get()))
6369 Expr *generateInitListsImpl(QualType Ty) {
6371 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6376 llvm::SmallVector<Expr *>
Inits;
6381 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6382 ElTy = ATy->getElementType();
6383 Size = ATy->getNumElements();
6384 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6385 ElTy = CMTy->getElementType();
6386 Size = CMTy->getNumElementsFlattened();
6389 ElTy = VTy->getElementType();
6390 Size = VTy->getZExtSize();
6392 for (uint64_t I = 0; I <
Size; ++I)
6393 Inits.push_back(generateInitListsImpl(ElTy));
6396 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6397 RecordDecls.push_back(RD);
6398 while (RecordDecls.back()->getNumBases()) {
6399 CXXRecordDecl *D = RecordDecls.back();
6401 "HLSL doesn't support multiple inheritance");
6402 RecordDecls.push_back(
6405 while (!RecordDecls.empty()) {
6406 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6407 for (
auto *FD : RD->
fields())
6408 if (!FD->isUnnamedBitField())
6413 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6414 Inits.back()->getEndLoc(),
false);
6415 NewInit->setType(Ty);
6420 llvm::SmallVector<QualType, 16> DestTypes;
6421 llvm::SmallVector<Expr *, 16> ArgExprs;
6422 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6423 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6424 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6425 InitTy = Entity.
getType().getNonReferenceType();
6435 DstIt = DestTypes.begin();
6438 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6440 Expr *generateInitLists() {
6441 assert(!ArgExprs.empty() &&
6442 "Call buildInitializerList to generate argument expressions.");
6443 ArgIt = ArgExprs.begin();
6445 return generateInitListsImpl(InitTy);
6446 llvm::SmallVector<Expr *>
Inits;
6447 while (ArgIt != ArgExprs.end())
6448 Inits.push_back(generateInitListsImpl(InitTy));
6451 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6452 Inits.back()->getEndLoc(),
false);
6453 llvm::APInt ArySize(64,
Inits.size());
6455 ArraySizeModifier::Normal, 0));
6467 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6474 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6478 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6498 if (
Init->getType()->isScalarType())
6501 InitListTransformer ILT(
SemaRef, Entity);
6503 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6511 Init->setInit(I, E);
6513 if (!ILT.buildInitializerList(E))
6516 size_t ExpectedSize = ILT.DestTypes.size();
6517 size_t ActualSize = ILT.ArgExprs.size();
6518 if (ExpectedSize == 0 && ActualSize == 0)
6525 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6527 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6528 << (int)(ExpectedSize < ActualSize) << InitTy
6529 << ExpectedSize << ActualSize;
6539 assert(ExpectedSize > 0 &&
6540 "The expected size of an incomplete array type must be at least 1.");
6542 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6550 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6551 if (ExpectedSize != ActualSize) {
6552 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6553 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6554 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6561 Init->resizeInits(Ctx, NewInit->getNumInits());
6562 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6563 Init->updateInit(Ctx, I, NewInit->getInit(I));
6571 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6581 StringRef AccessorName = CompName->
getName();
6582 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6584 unsigned Rows = MT->getNumRows();
6585 unsigned Cols = MT->getNumColumns();
6586 bool IsZeroBasedAccessor =
false;
6587 unsigned ChunkLen = 0;
6588 if (AccessorName.size() < 2)
6590 "length 4 for zero based: \'_mRC\' or "
6591 "length 3 for one-based: \'_RC\' accessor",
6594 if (AccessorName[0] ==
'_') {
6595 if (AccessorName[1] ==
'm') {
6596 IsZeroBasedAccessor =
true;
6603 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6606 if (AccessorName.size() % ChunkLen != 0) {
6607 const llvm::StringRef
Expected = IsZeroBasedAccessor
6608 ?
"zero based: '_mRC' accessor"
6609 :
"one-based: '_RC' accessor";
6614 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6615 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6616 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6618 bool HasRepeated =
false;
6620 unsigned NumComponents = 0;
6621 const char *Begin = AccessorName.data();
6623 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6624 const char *Chunk = Begin + I;
6625 char RowChar = 0, ColChar = 0;
6626 if (IsZeroBasedAccessor) {
6628 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6629 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6631 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6638 if (Chunk[0] !=
'_')
6640 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6647 bool IsDigitsError =
false;
6649 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6653 IsDigitsError =
true;
6657 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6661 IsDigitsError =
true;
6666 unsigned Row = RowChar -
'0';
6667 unsigned Col = ColChar -
'0';
6669 bool HasIndexingError =
false;
6670 if (IsZeroBasedAccessor) {
6672 if (!isZeroBasedIndex(Row)) {
6673 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6675 HasIndexingError =
true;
6677 if (!isZeroBasedIndex(Col)) {
6678 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6680 HasIndexingError =
true;
6684 if (!isOneBasedIndex(Row)) {
6685 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6687 HasIndexingError =
true;
6689 if (!isOneBasedIndex(Col)) {
6690 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6692 HasIndexingError =
true;
6699 if (HasIndexingError)
6705 bool HasBoundsError =
false;
6707 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6709 HasBoundsError =
true;
6712 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6714 HasBoundsError =
true;
6719 unsigned FlatIndex = Row * Cols + Col;
6720 if (Seen[FlatIndex])
6722 Seen[FlatIndex] =
true;
6725 if (NumComponents == 0 || NumComponents > 4) {
6726 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6731 QualType ElemTy = MT->getElementType();
6732 if (NumComponents == 1)
6738 for (Sema::ExtVectorDeclsType::iterator
6742 if ((*I)->getUnderlyingType() == VT)
6753 trackLocalResource(VDecl,
Init);
6755 const HLSLVkConstantIdAttr *ConstIdAttr =
6756 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6763 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
6773 int ConstantID = ConstIdAttr->getId();
6774 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6776 ConstIdAttr->getLocation());
6780 if (
C->getType()->getCanonicalTypeUnqualified() !=
6784 Context.getTrivialTypeSourceInfo(
6785 Init->getType(),
Init->getExprLoc()),
6804 if (!Params || Params->
size() != 1)
6817 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6818 if (TTP->hasDefaultArgument()) {
6819 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6822 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6823 if (NTTP->hasDefaultArgument()) {
6824 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6827 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6828 if (TTPD->hasDefaultArgument()) {
6829 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6836 return SemaRef.CheckTemplateIdType(
6838 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 CheckScalarFloatOperand(Sema &S, CallExpr *TheCall, unsigned ArgIndex)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckAnyScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
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 isMatrixType(QualType QT)
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 bool CheckInterlockedBuiltin(Sema &S, CallExpr *TheCall, unsigned MinArgs, unsigned MaxArgs, InterlockedDest Dest, bool ReportsOriginalValue)
Check a call to an HLSL interlocked builtin.
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool CheckMatrixSelect(Sema *S, CallExpr *TheCall)
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 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 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)
InterlockedDest
The dest types an interlocked operation accepts. Float is 32-bit only.
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static QualType getVectorOrScalarType(Sema &S, QualType BaseType, unsigned Count)
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
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns, std::optional< MatrixType::LayoutKind > Layout=std::nullopt) const
Return the unique reference to the matrix type of the specified element type and size.
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.
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
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.
unsigned getNumRows() const
Returns the number of rows 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)
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)
bool CanPerformPackedTypeCast(Expr *Src, QualType DestTy)
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.
bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount)
Checks that a call expression's argument count is at most the desired number.
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 isHLSLBuiltinPackedType() 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.
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