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);
2694 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2696 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2700 Cur = AT->getModifiedType();
2711 ? attr::HLSLRowMajor
2712 : attr::HLSLColumnMajor;
2717 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2726 if (ExistingKind == AttrK) {
2727 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2729 Diag(AL.
getLoc(), diag::note_previous_attribute);
2733 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2734 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2736 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2741 if (AttrK == attr::HLSLRowMajor)
2742 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2743 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2754 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2756 if (
T.isNull() ||
T->isDependentType())
2761 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2762 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2810 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2814 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2815 unsigned CurrentShaderStageBit;
2820 bool ReportOnlyShaderStageIssues;
2823 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2824 static_assert(
sizeof(
unsigned) >= 4);
2825 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2826 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2827 "ShaderType is too big for this bitmap");
2830 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2831 CurrentShaderEnvironment = ShaderType;
2832 CurrentShaderStageBit = (1 << bitmapIndex);
2835 void SetUnknownShaderStageContext() {
2836 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2837 CurrentShaderStageBit = (1 << 31);
2840 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2841 return CurrentShaderEnvironment;
2844 bool InUnknownShaderStageContext()
const {
2845 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2849 void AddToScannedFunctions(
const FunctionDecl *FD) {
2850 unsigned &ScannedStages = ScannedDecls[FD];
2851 ScannedStages |= CurrentShaderStageBit;
2854 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2856 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2857 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2860 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2861 return ScannerStages & CurrentShaderStageBit;
2864 static bool NeverBeenScanned(
unsigned ScannedStages) {
2865 return ScannedStages == 0;
2869 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2870 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2872 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2873 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2876 DiagnoseHLSLAvailability(Sema &SemaRef)
2878 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2879 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2882 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2883 void RunOnFunction(
const FunctionDecl *FD);
2885 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2886 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2888 HandleFunctionOrMethodRef(FD, DRE);
2892 bool VisitMemberExpr(MemberExpr *ME)
override {
2893 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2895 HandleFunctionOrMethodRef(FD, ME);
2900void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2903 "expected DeclRefExpr or MemberExpr");
2905 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
2906 CheckDeclAvailability(
2911 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
2912 DeclsToScan.push_back(FDWithBody);
2915void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2920 llvm::Triple::EnvironmentType::Library;
2929 DeclContextsToScan.push_back(TU);
2931 while (!DeclContextsToScan.empty()) {
2932 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2933 for (
auto &D : DC->
decls()) {
2940 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2941 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2946 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2951 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2952 if (!IsLibraryShader && FD->
getName() == EntryName) {
2955 diag::err_hlsl_ambiguous_entry_point)
2957 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
2963 SetShaderStageContext(ShaderAttr->getType());
2972 for (
const auto *Redecl : FD->
redecls()) {
2973 if (Redecl->isInExportDeclContext()) {
2980 SetUnknownShaderStageContext();
2987 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
2994void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2995 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2996 DeclsToScan.push_back(FD);
2998 while (!DeclsToScan.empty()) {
3006 const unsigned ScannedStages = GetScannedStages(FD);
3007 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3010 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3012 AddToScannedFunctions(FD);
3017bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3018 const AvailabilityAttr *AA) {
3023 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3024 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3027 llvm::Triple::EnvironmentType AttrEnv =
3028 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3030 return CurrentEnv == AttrEnv;
3033const AvailabilityAttr *
3034DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3035 AvailabilityAttr
const *PartialMatch =
nullptr;
3039 for (
const auto *A : D->
attrs()) {
3040 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3041 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3042 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3043 StringRef TargetPlatform =
3047 if (AttrPlatform == TargetPlatform) {
3049 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3051 PartialMatch = Avail;
3055 return PartialMatch;
3060void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3061 const AvailabilityAttr *AA,
3080 if (ReportOnlyShaderStageIssues)
3086 if (InUnknownShaderStageContext())
3091 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3092 VersionTuple Introduced = AA->getIntroduced();
3101 llvm::StringRef PlatformName(
3104 llvm::StringRef CurrentEnvStr =
3105 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3107 llvm::StringRef AttrEnvStr =
3108 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3109 bool UseEnvironment = !AttrEnvStr.empty();
3111 if (EnvironmentMatches) {
3112 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3113 <<
Range << D << PlatformName << Introduced.getAsString()
3114 << UseEnvironment << CurrentEnvStr;
3116 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3120 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3121 << D << PlatformName << Introduced.getAsString()
3123 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3130 if (!DefaultCBufferDecls.empty()) {
3133 DefaultCBufferDecls);
3136 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3140 for (
const Decl *VD : DefaultCBufferDecls) {
3141 const HLSLResourceBindingAttr *RBA =
3142 VD->
getAttr<HLSLResourceBindingAttr>();
3143 if (RBA && RBA->hasRegisterSlot() &&
3144 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3151 SemaRef.Consumer.HandleTopLevelDecl(DG);
3153 diagnoseAvailabilityViolations(TU);
3162 "expected member expr to have resource record type or array of them");
3168 const Expr *NonConstIndexExpr =
nullptr;
3171 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3172 if (!NonConstIndexExpr)
3180 diag::err_hlsl_resource_member_array_access_not_constant);
3184 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3185 const Expr *IdxExpr = ASE->getIdx();
3187 NonConstIndexExpr = IdxExpr;
3189 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3190 E = SubME->getBase();
3191 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3192 E = ICE->getSubExpr();
3194 llvm_unreachable(
"unexpected expr type in resource member access");
3203 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3206 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3209 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3213 [[maybe_unused]]
bool LookupSucceeded =
3214 SemaRef.LookupQualifiedName(ConvR, RD);
3215 assert(LookupSucceeded);
3224std::optional<ExprResult>
3227 const HLSLAttributedResourceType *ResTy =
3228 HLSLAttributedResourceType::findHandleTypeOnResource(
3229 BaseType.getTypePtr());
3231 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3232 return std::nullopt;
3234 QualType TemplateType = ResTy->getContainedType();
3238 assert(NamedConversionDecl &&
3239 "Could not find conversion function for ConstantBuffer.");
3240 auto *ConversionDecl =
3243 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3255 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3258 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3265 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3268 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3293 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3308 if (!BaseType->isFloat32Type())
3309 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3310 << ArgOrdinal << 5 << 0
3320 BaseType = VT->getElementType();
3322 BaseType = MT->getElementType();
3324 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3325 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3326 << ArgOrdinal << 5 << 0
3340 if (!BaseType->isDoubleType()) {
3343 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3344 << ArgOrdinal << PassedType;
3351 unsigned ArgIndex) {
3352 auto *Arg = TheCall->
getArg(ArgIndex);
3354 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3357 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3371 << (ArgIndex + 1) << LValueTy;
3381 if (VecTy->getElementType()->isDoubleType())
3382 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3383 << ArgOrdinal << 1 << 0 << 1
3393 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3394 << ArgOrdinal << 5 << 1
3403 if (VecTy->getElementType()->isUnsignedIntegerType())
3406 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3407 << ArgOrdinal << 4 << 3 << 0
3416 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3417 << ArgOrdinal << 5 << 3
3423 unsigned ArgOrdinal,
unsigned Width) {
3426 ArgTy = VTy->getElementType();
3428 uint64_t ElementBitCount =
3430 if (ElementBitCount != Width) {
3432 diag::err_integer_incorrect_bit_count)
3433 << Width << ElementBitCount;
3444 else if (
auto *MatTyA =
3447 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3453 unsigned ArgIndex) {
3462 diag::err_typecheck_expect_scalar_or_vector)
3463 << ArgType << Scalar;
3470 QualType Scalar,
unsigned ArgIndex) {
3481 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3494 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3495 << ArgType << Scalar;
3500 unsigned ArgIndex) {
3505 if (!(ArgType->isScalarType() ||
3506 (VTy && VTy->getElementType()->isScalarType()))) {
3508 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3516 unsigned ArgIndex) {
3519 if (ArgType->isDependentType())
3523 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3524 ElementType = VectorTy->getElementType();
3526 ElementType = MatrixTy->getElementType();
3528 if (ElementType->isBooleanType())
3531 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3533 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3538 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3546 unsigned ArgIndex) {
3548 assert(ArgIndex < TheCall->getNumArgs());
3556 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3581 diag::err_typecheck_call_different_arg_types)
3600 Arg1ScalarTy = VTy->getElementType();
3604 Arg2ScalarTy = VTy->getElementType();
3607 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3608 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3618 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3620 diag::err_typecheck_vector_lengths_not_equal)
3626 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3628 diag::err_typecheck_vector_lengths_not_equal)
3645 unsigned ArgIndex) {
3650 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3653 unsigned int ActualDim = 1;
3655 ActualDim = VTy->getNumElements();
3656 IndexTy = VTy->getElementType();
3660 diag::err_typecheck_expect_int)
3666 const HLSLAttributedResourceType *ResTy =
3668 assert(ResTy &&
"Resource argument must be a resource");
3669 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3671 unsigned int ExpectedDim = 1;
3672 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3674 (ResAttrs.IsArray ? 1 : 0);
3676 if (ActualDim != ExpectedDim) {
3678 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3689 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3693 const HLSLAttributedResourceType *ResTy =
3697 diag::err_typecheck_expect_hlsl_resource)
3701 if (Check && Check(ResTy)) {
3703 diag::err_invalid_hlsl_resource_type)
3713 "expected resource handle type");
3714 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3715 auto MainAttrs = MainResType->getAttrs();
3716 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3717 MainAttrs.IsCounter =
true;
3719 MainResType->getContainedType(),
3730 return "SampleBias";
3732 return "SampleGrad";
3734 return "SampleLevel";
3738 return "SampleCmpLevelZero";
3740 llvm_unreachable(
"Invalid SampleKind");
3750 if (!MD || !MD->getDeclName().isIdentifier())
3757 return MD->getName();
3765 return VecTy->getElementType();
3766 return ContainedType;
3774 StringRef DefaultName) {
3779 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
3806 if (SMVersion >= VersionTuple(6, 7))
3809 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
3811 << ContainedType << SMVersion.getAsString();
3816 bool IncludeArraySlice =
true) {
3819 [](
const HLSLAttributedResourceType *ResType) {
3820 return ResType->getAttrs().ResourceDimension ==
3821 llvm::dxil::ResourceDimension::Unknown;
3827 [](
const HLSLAttributedResourceType *ResType) {
3828 return ResType->getAttrs().ResourceClass !=
3829 llvm::hlsl::ResourceClass::Sampler;
3837 unsigned ExpectedDim =
3839 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
3868 unsigned NextIdx = 3;
3880 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3884 std::optional<llvm::APSInt> ComponentOpt =
3887 int64_t ComponentVal = ComponentOpt->getSExtValue();
3888 if (ComponentVal != 0) {
3891 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3892 "The component is not in the expected range.");
3894 diag::err_hlsl_gathercmp_invalid_component)
3904 const HLSLAttributedResourceType *ResourceTy =
3907 unsigned ExpectedDim =
3910 &S, TheCall->
getArg(NextIdx),
3916 assert(ResourceTy->hasContainedType() &&
3917 "Expecting a contained type for resource with a dimension "
3919 QualType ReturnType = ResourceTy->getContainedType();
3922 IsCmp ?
"GatherCmp" :
"Gather"))
3927 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3933 ReturnType = VecTy->getElementType();
3946 [](
const HLSLAttributedResourceType *ResType) {
3947 return ResType->getAttrs().ResourceDimension ==
3948 llvm::dxil::ResourceDimension::Unknown;
3958 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
3965 unsigned ResourceDim =
3967 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
3983 TheCall->
setType(ResourceTy->getContainedType());
3993 [](
const HLSLAttributedResourceType *ResType) {
3994 return !ResType->isMultiSampled();
4003 unsigned ResourceDim =
4005 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4023 TheCall->
setType(ResourceTy->getContainedType());
4028 unsigned MinArgs, MaxArgs;
4056 const HLSLAttributedResourceType *ResourceTy =
4058 unsigned ExpectedDim =
4061 unsigned NextIdx = 3;
4086 &S, TheCall->
getArg(NextIdx),
4099 assert(ResourceTy->hasContainedType() &&
4100 "Expecting a contained type for resource with a dimension "
4102 QualType ReturnType = ResourceTy->getContainedType();
4113 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4126 switch (BuiltinID) {
4127 case Builtin::BI__builtin_hlsl_adduint64: {
4128 if (
SemaRef.checkArgCount(TheCall, 2))
4142 if (NumElementsArg != 2 && NumElementsArg != 4) {
4144 << 1 << 64 << NumElementsArg * 32;
4158 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4159 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4166 QualType ContainedTy = ResourceTy->getContainedType();
4167 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4170 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4175 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4176 if (
SemaRef.checkArgCount(TheCall, 3) ||
4183 "expected pointer type for second argument");
4190 diag::err_invalid_use_of_array_type);
4194 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4197 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4202 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4203 if (
SemaRef.checkArgCount(TheCall, 2) ||
4205 SemaRef.getASTContext().IntTy))
4212 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4213 if (
SemaRef.checkArgCount(TheCall, 3) ||
4216 SemaRef.getASTContext().UnsignedIntTy) ||
4218 SemaRef.getASTContext().UnsignedIntTy) ||
4224 QualType ReturnType = ResourceTy->getContainedType();
4229 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4230 if (
SemaRef.checkArgCount(TheCall, 4) ||
4233 SemaRef.getASTContext().UnsignedIntTy) ||
4235 SemaRef.getASTContext().UnsignedIntTy) ||
4241 "expected pointer type for second argument");
4248 diag::err_invalid_use_of_array_type);
4254 case Builtin::BI__builtin_hlsl_resource_load_level:
4256 case Builtin::BI__builtin_hlsl_resource_load_ms:
4258 case Builtin::BI__builtin_hlsl_resource_sample:
4260 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4262 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4264 case Builtin::BI__builtin_hlsl_resource_sample_level:
4266 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4268 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4270 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4271 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4273 case Builtin::BI__builtin_hlsl_resource_gather:
4275 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4277 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4278 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4284 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4285 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4291 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4292 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4298 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4299 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4305 TheCall->
setType(CounterHandleTy);
4308 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4309 if (
SemaRef.checkArgCount(TheCall, 2) ||
4312 SemaRef.getASTContext().UnsignedIntTy))
4320 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4321 if (
SemaRef.checkArgCount(TheCall, 1) ||
4329 TheCall->
setType(CounterHandleTy);
4332 case Builtin::BI__builtin_hlsl_and:
4333 case Builtin::BI__builtin_hlsl_or: {
4334 if (
SemaRef.checkArgCount(TheCall, 2))
4348 case Builtin::BI__builtin_hlsl_all:
4349 case Builtin::BI__builtin_hlsl_any: {
4350 if (
SemaRef.checkArgCount(TheCall, 1))
4356 case Builtin::BI__builtin_hlsl_asdouble: {
4357 if (
SemaRef.checkArgCount(TheCall, 2))
4361 SemaRef.Context.UnsignedIntTy,
4366 SemaRef.Context.UnsignedIntTy,
4375 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4376 if (
SemaRef.BuiltinElementwiseTernaryMath(
4382 case Builtin::BI__builtin_hlsl_dot: {
4384 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4390 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4391 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4392 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4402 EltTy = VecTy->getElementType();
4403 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4416 case Builtin::BI__builtin_hlsl_select: {
4417 if (
SemaRef.checkArgCount(TheCall, 3))
4425 if (VTy && VTy->getElementType()->isBooleanType() &&
4430 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4431 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4432 if (
SemaRef.checkArgCount(TheCall, 1))
4438 diag::err_builtin_invalid_arg_type)
4441 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4445 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4446 case Builtin::BI__builtin_hlsl_elementwise_frac:
4447 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4448 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4449 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4450 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4451 if (
SemaRef.checkArgCount(TheCall, 1))
4456 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4460 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4461 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4462 if (
SemaRef.checkArgCount(TheCall, 1))
4467 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4472 case Builtin::BI__builtin_hlsl_mad: {
4473 if (
SemaRef.BuiltinElementwiseTernaryMath(
4479 case Builtin::BI__builtin_hlsl_mul: {
4480 if (
SemaRef.checkArgCount(TheCall, 2))
4490 return VTy->getElementType();
4492 return MTy->getElementType();
4496 QualType EltTy0 = getElemType(Ty0);
4505 if (IsVec0 && IsMat1) {
4508 }
else if (IsMat0 && IsVec1) {
4512 assert(IsMat0 && IsMat1);
4522 case Builtin::BI__builtin_elementwise_fma: {
4523 if (
SemaRef.checkArgCount(TheCall, 3) ||
4538 case Builtin::BI__builtin_hlsl_transpose: {
4539 if (
SemaRef.checkArgCount(TheCall, 1))
4548 << 1 << 3 << 0 << 0 << ArgTy;
4553 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4557 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4558 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4566 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4567 if (
SemaRef.checkArgCount(TheCall, 1))
4581 unsigned NumElts = VecTy->getNumElements();
4591 case Builtin::BI__builtin_hlsl_wave_active_max:
4592 case Builtin::BI__builtin_hlsl_wave_active_min:
4593 case Builtin::BI__builtin_hlsl_wave_active_sum:
4594 case Builtin::BI__builtin_hlsl_wave_active_product: {
4595 if (
SemaRef.checkArgCount(TheCall, 1))
4608 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4609 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4610 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4611 if (
SemaRef.checkArgCount(TheCall, 1))
4626 (VTy && VTy->getElementType()->isIntegerType()))) {
4628 diag::err_builtin_invalid_arg_type)
4629 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4637 case Builtin::BI__builtin_hlsl_interlocked_add:
4638 case Builtin::BI__builtin_hlsl_interlocked_and:
4639 case Builtin::BI__builtin_hlsl_interlocked_exchange:
4640 case Builtin::BI__builtin_hlsl_interlocked_max:
4641 case Builtin::BI__builtin_hlsl_interlocked_min:
4642 case Builtin::BI__builtin_hlsl_interlocked_or:
4643 case Builtin::BI__builtin_hlsl_interlocked_xor: {
4653 if (BuiltinID == Builtin::BI__builtin_hlsl_interlocked_exchange) {
4654 if (
SemaRef.checkArgCount(TheCall, 3))
4659 diag::err_typecheck_call_too_few_args_at_least)
4664 if (
SemaRef.checkArgCountAtMost(TheCall, 3))
4672 const bool AllowsFloat =
4673 BuiltinID == Builtin::BI__builtin_hlsl_interlocked_exchange;
4677 diag::err_builtin_invalid_arg_type)
4679 << (AllowsFloat ? 3 : 0) << DestTy;
4689 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4690 SemaRef.Context.getTypeSize(DestTy) == 64 &&
4719 case Builtin::BI__builtin_elementwise_bitreverse: {
4727 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4728 if (
SemaRef.checkArgCount(TheCall, 1))
4733 if (!(
ArgType->isScalarType())) {
4735 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4740 if (!(
ArgType->isBooleanType())) {
4742 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4749 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4750 if (
SemaRef.checkArgCount(TheCall, 2))
4758 diag::err_typecheck_convert_incompatible)
4759 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4772 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
4773 if (
SemaRef.checkArgCount(TheCall, 1))
4782 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4783 if (
SemaRef.checkArgCount(TheCall, 0))
4787 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4788 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4789 if (
SemaRef.checkArgCount(TheCall, 1))
4802 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4803 case Builtin::BI__builtin_hlsl_quad_read_across_y:
4804 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
4805 if (
SemaRef.checkArgCount(TheCall, 1))
4817 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4818 if (
SemaRef.checkArgCount(TheCall, 3))
4824 SemaRef.Context.UnsignedIntTy, 1) ||
4826 SemaRef.Context.UnsignedIntTy, 2))
4834 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4835 if (
SemaRef.checkArgCount(TheCall, 1))
4842 case Builtin::BI__builtin_elementwise_acos:
4843 case Builtin::BI__builtin_elementwise_asin:
4844 case Builtin::BI__builtin_elementwise_atan:
4845 case Builtin::BI__builtin_elementwise_atan2:
4846 case Builtin::BI__builtin_elementwise_ceil:
4847 case Builtin::BI__builtin_elementwise_cos:
4848 case Builtin::BI__builtin_elementwise_cosh:
4849 case Builtin::BI__builtin_elementwise_exp:
4850 case Builtin::BI__builtin_elementwise_exp2:
4851 case Builtin::BI__builtin_elementwise_exp10:
4852 case Builtin::BI__builtin_elementwise_floor:
4853 case Builtin::BI__builtin_elementwise_fmod:
4854 case Builtin::BI__builtin_elementwise_log:
4855 case Builtin::BI__builtin_elementwise_log2:
4856 case Builtin::BI__builtin_elementwise_log10:
4857 case Builtin::BI__builtin_elementwise_pow:
4858 case Builtin::BI__builtin_elementwise_roundeven:
4859 case Builtin::BI__builtin_elementwise_sin:
4860 case Builtin::BI__builtin_elementwise_sinh:
4861 case Builtin::BI__builtin_elementwise_sqrt:
4862 case Builtin::BI__builtin_elementwise_tan:
4863 case Builtin::BI__builtin_elementwise_tanh:
4864 case Builtin::BI__builtin_elementwise_trunc: {
4870 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4871 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4872 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4873 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4874 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4879 std::optional<llvm::APSInt> Offset =
4881 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4883 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4889 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4890 if (
SemaRef.checkArgCount(TheCall, 1))
4901 ArgTy = VTy->getElementType();
4904 diag::err_builtin_invalid_arg_type)
4913 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4914 if (
SemaRef.checkArgCount(TheCall, 1))
4929 WorkList.push_back(BaseTy);
4930 while (!WorkList.empty()) {
4932 T =
T.getCanonicalType().getUnqualifiedType();
4933 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
4941 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4942 llvm::append_range(List, ElementFields);
4947 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
4948 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
4951 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
4952 List.insert(List.end(), MT->getNumElementsFlattened(),
4953 MT->getElementType());
4956 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
4957 if (RD->isStandardLayout())
4958 RD = RD->getStandardLayoutBaseWithFields();
4962 if (RD->
isUnion() || !RD->isAggregate()) {
4968 for (
const auto *FD : RD->
fields())
4969 if (!FD->isUnnamedBitField())
4970 FieldTypes.push_back(FD->
getType());
4972 std::reverse(FieldTypes.begin(), FieldTypes.end());
4973 llvm::append_range(WorkList, FieldTypes);
4977 if (!RD->isStandardLayout()) {
4979 for (
const auto &
Base : RD->bases())
4980 FieldTypes.push_back(
Base.getType());
4981 std::reverse(FieldTypes.begin(), FieldTypes.end());
4982 llvm::append_range(WorkList, FieldTypes);
5017 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5023 int ArraySize = VT->getNumElements();
5028 QualType ElTy = VT->getElementType();
5032 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5048 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5057 return llvm::equal(T1Types, T2Types,
5059 return SemaRef.IsLayoutCompatible(LHS, RHS);
5068 bool HadError =
false;
5070 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5078 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5079 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5080 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5081 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5083 if (NSpellingIdx != OSpellingIdx) {
5085 diag::err_hlsl_param_qualifier_mismatch)
5086 << NDAttr << NewParam;
5102 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5117 llvm_unreachable(
"HLSL doesn't support pointers.");
5120 llvm_unreachable(
"HLSL doesn't support complex types.");
5122 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5124 llvm_unreachable(
"Should have returned before this");
5134 llvm_unreachable(
"HLSL doesn't support complex types.");
5136 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5141 llvm_unreachable(
"HLSL doesn't support pointers.");
5143 llvm_unreachable(
"Should have returned before this");
5149 llvm_unreachable(
"HLSL doesn't support pointers.");
5152 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5156 llvm_unreachable(
"HLSL doesn't support complex types.");
5159 llvm_unreachable(
"Unhandled scalar cast");
5180 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5186 SrcTy = SrcMatTy->getElementType();
5191 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5192 if (DestTypes[I]->isUnionType())
5224 if (SrcTypes.size() < DestTypes.size())
5227 unsigned SrcSize = SrcTypes.size();
5228 unsigned DstSize = DestTypes.size();
5230 for (I = 0; I < DstSize && I < SrcSize; I++) {
5231 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5239 for (; I < SrcSize; I++) {
5240 if (SrcTypes[I]->isUnionType())
5247 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5248 "We should not get here without a parameter modifier expression");
5249 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5256 << Arg << (IsInOut ? 1 : 0);
5262 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5269 << Arg << (IsInOut ? 1 : 0);
5281 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5287 auto *OpV =
new (Ctx)
5293 tok::equal, ArgOpV, OpV);
5309 "Pointer and reference types cannot be inout or out parameters");
5310 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5326 for (
const auto *FD : RD->
fields()) {
5330 assert(RD->getNumBases() <= 1 &&
5331 "HLSL doesn't support multiple inheritance");
5332 return RD->getNumBases()
5337 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5338 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5350 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5355 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5361 if (
Decl->getType().hasAddressSpace())
5364 if (
Decl->getType()->isDependentType())
5376 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5390 llvm::Triple::Vulkan;
5391 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5392 if (HasDeclaredAPushConstant)
5398 HasDeclaredAPushConstant =
true;
5425class StructBindingContext {
5428 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5429 unsigned RegBindingOffset[4];
5432 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5433 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5434 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5435 static_cast<unsigned>(RegisterType::Sampler) == 3,
5436 "unexpected register type values");
5439 HLSLVkBindingAttr *VkBindingAttr;
5440 unsigned VkBindingOffset;
5445 StructBindingContext(
VarDecl *VD) {
5446 for (
unsigned i = 0; i < 4; ++i) {
5447 RegBindingsAttrs[i] =
nullptr;
5448 RegBindingOffset[i] = 0;
5450 VkBindingAttr =
nullptr;
5451 VkBindingOffset = 0;
5457 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5459 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5462 RegBindingsAttrs[RegTypeIdx] = RBA;
5467 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5468 VkBindingAttr = VBA;
5475 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5476 unsigned Range,
bool HasCounter) {
5477 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5479 if (VkBindingAttr) {
5480 unsigned Offset = VkBindingOffset;
5481 VkBindingOffset +=
Range;
5482 return HLSLVkBindingAttr::CreateImplicit(
5483 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5484 VkBindingAttr->getRange());
5487 HLSLResourceBindingAttr *RBA =
5488 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5489 HLSLResourceBindingAttr *NewAttr =
nullptr;
5491 if (RBA && RBA->hasRegisterSlot()) {
5494 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5495 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5497 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5498 StringRef NewSlotNumberStr =
5500 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5501 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5502 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5506 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5507 NewAttr->setBinding(RegType, std::nullopt,
5508 RBA ? RBA->getSpaceNumber() : 0);
5512 NewAttr->setImplicitCounterBindingOrderID(
5521static void createGlobalResourceDeclForStruct(
5523 QualType ResTy, StructBindingContext &BindingCtx) {
5525 "expected resource type or array of resources");
5536 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5537 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5542 const HLSLAttributedResourceType *ResHandleTy =
5543 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5547 Attr *BindingAttr = BindingCtx.createBindingAttr(
5549 ResDecl->
addAttr(BindingAttr);
5550 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5559 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5566static void handleArrayOfStructWithResources(
5568 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5573static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5575 EmbeddedResourceNameBuilder &NameBuilder,
5576 StructBindingContext &BindingCtx) {
5579 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5586 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5600 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5603 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5605 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5607 "resource arrays should have been already handled");
5608 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5617handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5619 EmbeddedResourceNameBuilder &NameBuilder,
5620 StructBindingContext &BindingCtx) {
5628 if (!SubCAT && !ElementRD)
5631 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5634 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5637 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5650void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5651 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5652 StructBindingContext BindingCtx(VD);
5656 "Expected non-resource struct or array type");
5659 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5663 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5664 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5672 if (
SemaRef.RequireCompleteType(
5675 diag::err_typecheck_decl_incomplete_type)) {
5689 DefaultCBufferDecls.push_back(VD);
5694 collectResourceBindingsOnVarDecl(VD);
5696 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5708 processExplicitBindingsOnDecl(VD);
5746 handleGlobalStructOrArrayOfWithResources(VD);
5750 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5759 "expected resource record type");
5775 const char *CreateMethodName;
5777 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5778 :
"__createFromBinding";
5780 CreateMethodName = HasCounter
5781 ?
"__createFromImplicitBindingWithImplicitCounter"
5782 :
"__createFromImplicitBinding";
5787 if (!CreateMethod) {
5792 "create method lookup should always succeed for built-in resource "
5801 Args.push_back(RegSlot);
5809 Args.push_back(OrderId);
5815 Args.push_back(Space);
5819 Args.push_back(RangeSize);
5823 Args.push_back(Index);
5825 StringRef VarName = VD->
getName();
5833 Args.push_back(NameCast);
5841 Args.push_back(CounterId);
5864 SemaRef.CheckCompleteVariableDeclaration(VD);
5870 "expected array of resource records");
5891 lookupMethod(
SemaRef, ResourceDecl,
5892 HasCounter ?
"__createFromBindingWithImplicitCounter"
5893 :
"__createFromBinding",
5897 CreateMethod = lookupMethod(
5899 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5900 :
"__createFromImplicitBinding",
5943std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5944 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5945 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5946 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5947 if (!TrueInfo || !FalseInfo)
5948 return std::nullopt;
5949 if (*TrueInfo != *FalseInfo)
5950 return std::nullopt;
5954 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5963 if (
const auto *AttrResType =
5964 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5966 return Bindings.getDeclBindingInfo(VD, RC);
5973void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
5974 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
5977 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5982 if (*ExprBinding ==
nullptr)
5985 auto PrevBinding = Assigns.find(VD);
5986 if (PrevBinding == Assigns.end()) {
5988 Assigns.insert({VD, *ExprBinding});
5993 if (*ExprBinding != PrevBinding->second) {
5995 diag::warn_hlsl_assigning_local_resource_is_not_unique)
5997 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6008 "expected LHS to be a resource record or array of resource records");
6009 if (Opc != BO_Assign)
6014 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6022 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6027 trackLocalResource(VD, RHSExpr);
6044void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6046 "expected global variable that contains HLSL resource");
6049 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6050 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6051 ? ResourceClass::CBuffer
6052 : ResourceClass::SRV);
6065 if (
const HLSLAttributedResourceType *AttrResType =
6066 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6067 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6072 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6073 collectResourceBindingsOnUserRecordDecl(VD, RT);
6079void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6082 bool HasBinding =
false;
6083 for (Attr *A : VD->
attrs()) {
6086 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6087 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6090 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6091 if (!RBA || !RBA->hasRegisterSlot())
6096 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6097 "never have an attribute created");
6099 if (RT == RegisterType::C) {
6100 if (Bindings.hasBindingInfoForDecl(VD))
6102 diag::warn_hlsl_user_defined_type_missing_member)
6103 <<
static_cast<int>(RT);
6111 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6116 diag::warn_hlsl_user_defined_type_missing_member)
6117 <<
static_cast<int>(RT);
6125class InitListTransformer {
6129 QualType *DstIt =
nullptr;
6130 Expr **ArgIt =
nullptr;
6136 bool castInitializer(Expr *E) {
6137 assert(DstIt &&
"This should always be something!");
6138 if (DstIt == DestTypes.end()) {
6140 ArgExprs.push_back(E);
6145 DstIt = DestTypes.begin();
6148 Ctx, *DstIt,
false);
6153 ArgExprs.push_back(
Init);
6158 bool buildInitializerListImpl(Expr *E) {
6160 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6161 for (
auto *SubInit :
Init->inits())
6162 if (!buildInitializerListImpl(SubInit))
6172 return castInitializer(E);
6186 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6191 for (uint64_t I = 0; I <
Size; ++I) {
6193 SizeTy, SourceLocation());
6199 if (!castInitializer(ElExpr.
get()))
6204 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6205 unsigned Rows = MTy->getNumRows();
6206 unsigned Cols = MTy->getNumColumns();
6207 QualType ElemTy = MTy->getElementType();
6209 for (
unsigned R = 0;
R < Rows; ++
R) {
6210 for (
unsigned C = 0;
C < Cols; ++
C) {
6223 if (!castInitializer(ElExpr.
get()))
6231 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6235 for (uint64_t I = 0; I <
Size; ++I) {
6237 SizeTy, SourceLocation());
6242 if (!buildInitializerListImpl(ElExpr.
get()))
6249 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6250 RecordDecls.push_back(RD);
6251 while (RecordDecls.back()->getNumBases()) {
6252 CXXRecordDecl *D = RecordDecls.back();
6254 "HLSL doesn't support multiple inheritance");
6255 RecordDecls.push_back(
6258 while (!RecordDecls.empty()) {
6259 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6260 for (
auto *FD : RD->
fields()) {
6261 if (FD->isUnnamedBitField())
6269 if (!buildInitializerListImpl(Res.
get()))
6277 Expr *generateInitListsImpl(QualType Ty) {
6279 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6284 llvm::SmallVector<Expr *>
Inits;
6289 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6290 ElTy = ATy->getElementType();
6291 Size = ATy->getNumElements();
6292 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6293 ElTy = CMTy->getElementType();
6294 Size = CMTy->getNumElementsFlattened();
6297 ElTy = VTy->getElementType();
6298 Size = VTy->getZExtSize();
6300 for (uint64_t I = 0; I <
Size; ++I)
6301 Inits.push_back(generateInitListsImpl(ElTy));
6304 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6305 RecordDecls.push_back(RD);
6306 while (RecordDecls.back()->getNumBases()) {
6307 CXXRecordDecl *D = RecordDecls.back();
6309 "HLSL doesn't support multiple inheritance");
6310 RecordDecls.push_back(
6313 while (!RecordDecls.empty()) {
6314 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6315 for (
auto *FD : RD->
fields())
6316 if (!FD->isUnnamedBitField())
6321 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6322 Inits.back()->getEndLoc(),
false);
6323 NewInit->setType(Ty);
6328 llvm::SmallVector<QualType, 16> DestTypes;
6329 llvm::SmallVector<Expr *, 16> ArgExprs;
6330 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6331 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6332 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6333 InitTy = Entity.
getType().getNonReferenceType();
6343 DstIt = DestTypes.begin();
6346 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6348 Expr *generateInitLists() {
6349 assert(!ArgExprs.empty() &&
6350 "Call buildInitializerList to generate argument expressions.");
6351 ArgIt = ArgExprs.begin();
6353 return generateInitListsImpl(InitTy);
6354 llvm::SmallVector<Expr *>
Inits;
6355 while (ArgIt != ArgExprs.end())
6356 Inits.push_back(generateInitListsImpl(InitTy));
6359 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6360 Inits.back()->getEndLoc(),
false);
6361 llvm::APInt ArySize(64,
Inits.size());
6363 ArraySizeModifier::Normal, 0));
6375 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6382 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6386 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6406 if (
Init->getType()->isScalarType())
6409 InitListTransformer ILT(
SemaRef, Entity);
6411 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6419 Init->setInit(I, E);
6421 if (!ILT.buildInitializerList(E))
6424 size_t ExpectedSize = ILT.DestTypes.size();
6425 size_t ActualSize = ILT.ArgExprs.size();
6426 if (ExpectedSize == 0 && ActualSize == 0)
6433 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6435 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6436 << (int)(ExpectedSize < ActualSize) << InitTy
6437 << ExpectedSize << ActualSize;
6447 assert(ExpectedSize > 0 &&
6448 "The expected size of an incomplete array type must be at least 1.");
6450 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6458 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6459 if (ExpectedSize != ActualSize) {
6460 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6461 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6462 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6469 Init->resizeInits(Ctx, NewInit->getNumInits());
6470 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6471 Init->updateInit(Ctx, I, NewInit->getInit(I));
6479 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6489 StringRef AccessorName = CompName->
getName();
6490 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6492 unsigned Rows = MT->getNumRows();
6493 unsigned Cols = MT->getNumColumns();
6494 bool IsZeroBasedAccessor =
false;
6495 unsigned ChunkLen = 0;
6496 if (AccessorName.size() < 2)
6498 "length 4 for zero based: \'_mRC\' or "
6499 "length 3 for one-based: \'_RC\' accessor",
6502 if (AccessorName[0] ==
'_') {
6503 if (AccessorName[1] ==
'm') {
6504 IsZeroBasedAccessor =
true;
6511 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6514 if (AccessorName.size() % ChunkLen != 0) {
6515 const llvm::StringRef
Expected = IsZeroBasedAccessor
6516 ?
"zero based: '_mRC' accessor"
6517 :
"one-based: '_RC' accessor";
6522 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6523 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6524 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6526 bool HasRepeated =
false;
6528 unsigned NumComponents = 0;
6529 const char *Begin = AccessorName.data();
6531 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6532 const char *Chunk = Begin + I;
6533 char RowChar = 0, ColChar = 0;
6534 if (IsZeroBasedAccessor) {
6536 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6537 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6539 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6546 if (Chunk[0] !=
'_')
6548 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6555 bool IsDigitsError =
false;
6557 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6561 IsDigitsError =
true;
6565 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6569 IsDigitsError =
true;
6574 unsigned Row = RowChar -
'0';
6575 unsigned Col = ColChar -
'0';
6577 bool HasIndexingError =
false;
6578 if (IsZeroBasedAccessor) {
6580 if (!isZeroBasedIndex(Row)) {
6581 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6583 HasIndexingError =
true;
6585 if (!isZeroBasedIndex(Col)) {
6586 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6588 HasIndexingError =
true;
6592 if (!isOneBasedIndex(Row)) {
6593 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6595 HasIndexingError =
true;
6597 if (!isOneBasedIndex(Col)) {
6598 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6600 HasIndexingError =
true;
6607 if (HasIndexingError)
6613 bool HasBoundsError =
false;
6615 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6617 HasBoundsError =
true;
6620 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6622 HasBoundsError =
true;
6627 unsigned FlatIndex = Row * Cols + Col;
6628 if (Seen[FlatIndex])
6630 Seen[FlatIndex] =
true;
6633 if (NumComponents == 0 || NumComponents > 4) {
6634 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6639 QualType ElemTy = MT->getElementType();
6640 if (NumComponents == 1)
6646 for (Sema::ExtVectorDeclsType::iterator
6650 if ((*I)->getUnderlyingType() == VT)
6661 trackLocalResource(VDecl,
Init);
6663 const HLSLVkConstantIdAttr *ConstIdAttr =
6664 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6671 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
6681 int ConstantID = ConstIdAttr->getId();
6682 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6684 ConstIdAttr->getLocation());
6688 if (
C->getType()->getCanonicalTypeUnqualified() !=
6692 Context.getTrivialTypeSourceInfo(
6693 Init->getType(),
Init->getExprLoc()),
6712 if (!Params || Params->
size() != 1)
6725 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6726 if (TTP->hasDefaultArgument()) {
6727 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6730 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6731 if (NTTP->hasDefaultArgument()) {
6732 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6735 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6736 if (TTPD->hasDefaultArgument()) {
6737 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6744 return SemaRef.CheckTemplateIdType(
6746 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 CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckCalculateLodBuiltin(Sema &S, CallExpr *TheCall)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckNoDoubleElementType(Sema &S, CallExpr *TheCall, QualType ContainedType, StringRef DefaultName)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static const Type * createHostLayoutType(Sema &S, const Type *Ty)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool CheckArgAddrSpaceOneOf(Sema *S, CallExpr *TheCall, unsigned ArgIndex, ArrayRef< LangAS > AllowedSpaces)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static StringRef getSampleMethodName(SampleKind Kind)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall)
static RegisterType getRegisterType(ResourceClass RC)
static bool ValidateRegisterNumber(uint64_t SlotNum, Decl *TheDecl, ASTContext &Ctx, RegisterType RegTy)
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static char getRegisterTypeChar(RegisterType RT)
static bool CheckNotBoolScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool isMatrixOrArrayOfMatrix(const ASTContext &Ctx, QualType QT)
static QualType getTypedResourceElementType(QualType ContainedType)
static bool findExistingMatrixLayoutMarker(QualType T, attr::Kind &ExistingKind)
Walks the existing AttributedType sugar of T looking for a previously applied HLSLRowMajor/HLSLColumn...
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckWavePrefix(Sema *S, CallExpr *TheCall)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static LangAS getLangASFromResourceClass(ResourceClass RC)
static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall, bool IncludeArraySlice=true)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static const Type * getHostLayoutFieldType(QualType QT)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static 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.
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)
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
ExtVectorDeclsType ExtVectorDecls
ExtVectorDecls - This is a list all the extended vector types.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult TemporaryMaterializationConversion(Expr *E)
If E is a prvalue denoting an unmaterialized temporary, materialize it as an xvalue.
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExternalSemaSource * getExternalSource() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
void pushBaseName(llvm::StringRef N)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
Defines the clang::TargetInfo interface.
uint32_t getResourceDimensions(llvm::dxil::ResourceDimension Dim)
bool hasResourceOffset(llvm::dxil::ResourceDimension Dim)
bool hasCounterHandle(const CXXRecordDecl *RD)
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
@ Template
We are parsing a template declaration.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr, Expr *SampleCountExpr=nullptr)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
__builtin_elementwise_add_sat __builtin_elementwise_sub_sat uint32_t __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
unsigned getImplicitOrderID() const
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
bool hasImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const