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);
4130 unsigned MinArgs,
unsigned MaxArgs,
4132 bool ReportsOriginalValue) {
4133 if (MinArgs == MaxArgs) {
4136 }
else if (TheCall->
getNumArgs() < MinArgs) {
4137 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4147 const bool DestIsOK =
4153 diag::err_builtin_invalid_arg_type)
4167 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4183 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4189 const unsigned NumArgs = TheCall->
getNumArgs();
4190 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4201 switch (BuiltinID) {
4202 case Builtin::BI__builtin_hlsl_adduint64: {
4203 if (
SemaRef.checkArgCount(TheCall, 2))
4217 if (NumElementsArg != 2 && NumElementsArg != 4) {
4219 << 1 << 64 << NumElementsArg * 32;
4233 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4234 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4241 QualType ContainedTy = ResourceTy->getContainedType();
4242 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4245 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4250 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4251 if (
SemaRef.checkArgCount(TheCall, 3) ||
4258 "expected pointer type for second argument");
4265 diag::err_invalid_use_of_array_type);
4269 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4272 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4277 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4278 if (
SemaRef.checkArgCount(TheCall, 2) ||
4280 SemaRef.getASTContext().IntTy))
4287 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4288 if (
SemaRef.checkArgCount(TheCall, 3) ||
4291 SemaRef.getASTContext().UnsignedIntTy) ||
4293 SemaRef.getASTContext().UnsignedIntTy) ||
4299 QualType ReturnType = ResourceTy->getContainedType();
4304 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4305 if (
SemaRef.checkArgCount(TheCall, 4) ||
4308 SemaRef.getASTContext().UnsignedIntTy) ||
4310 SemaRef.getASTContext().UnsignedIntTy) ||
4316 "expected pointer type for second argument");
4323 diag::err_invalid_use_of_array_type);
4329 case Builtin::BI__builtin_hlsl_resource_load_level:
4331 case Builtin::BI__builtin_hlsl_resource_load_ms:
4333 case Builtin::BI__builtin_hlsl_resource_sample:
4335 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4337 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4339 case Builtin::BI__builtin_hlsl_resource_sample_level:
4341 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4343 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4345 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4346 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4348 case Builtin::BI__builtin_hlsl_resource_gather:
4350 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4352 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4353 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4359 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4360 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4366 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4367 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4373 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4374 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4380 TheCall->
setType(CounterHandleTy);
4383 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4384 if (
SemaRef.checkArgCount(TheCall, 2) ||
4387 SemaRef.getASTContext().UnsignedIntTy))
4395 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4396 if (
SemaRef.checkArgCount(TheCall, 1) ||
4404 TheCall->
setType(CounterHandleTy);
4407 case Builtin::BI__builtin_hlsl_and:
4408 case Builtin::BI__builtin_hlsl_or: {
4409 if (
SemaRef.checkArgCount(TheCall, 2))
4423 case Builtin::BI__builtin_hlsl_all:
4424 case Builtin::BI__builtin_hlsl_any: {
4425 if (
SemaRef.checkArgCount(TheCall, 1))
4431 case Builtin::BI__builtin_hlsl_asdouble: {
4432 if (
SemaRef.checkArgCount(TheCall, 2))
4436 SemaRef.Context.UnsignedIntTy,
4441 SemaRef.Context.UnsignedIntTy,
4450 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4451 if (
SemaRef.BuiltinElementwiseTernaryMath(
4457 case Builtin::BI__builtin_hlsl_dot: {
4459 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4465 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4466 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4467 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4477 EltTy = VecTy->getElementType();
4478 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4491 case Builtin::BI__builtin_hlsl_select: {
4492 if (
SemaRef.checkArgCount(TheCall, 3))
4500 if (VTy && VTy->getElementType()->isBooleanType() &&
4505 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4506 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4507 if (
SemaRef.checkArgCount(TheCall, 1))
4513 diag::err_builtin_invalid_arg_type)
4516 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4520 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4521 case Builtin::BI__builtin_hlsl_elementwise_frac:
4522 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4523 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4524 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4525 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4526 if (
SemaRef.checkArgCount(TheCall, 1))
4531 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4535 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4536 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4537 if (
SemaRef.checkArgCount(TheCall, 1))
4542 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4547 case Builtin::BI__builtin_hlsl_mad: {
4548 if (
SemaRef.BuiltinElementwiseTernaryMath(
4554 case Builtin::BI__builtin_hlsl_mul: {
4555 if (
SemaRef.checkArgCount(TheCall, 2))
4565 return VTy->getElementType();
4567 return MTy->getElementType();
4571 QualType EltTy0 = getElemType(Ty0);
4580 if (IsVec0 && IsMat1) {
4583 }
else if (IsMat0 && IsVec1) {
4587 assert(IsMat0 && IsMat1);
4597 case Builtin::BI__builtin_elementwise_fma: {
4598 if (
SemaRef.checkArgCount(TheCall, 3) ||
4613 case Builtin::BI__builtin_hlsl_transpose: {
4614 if (
SemaRef.checkArgCount(TheCall, 1))
4623 << 1 << 3 << 0 << 0 << ArgTy;
4628 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4632 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4633 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4641 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4642 if (
SemaRef.checkArgCount(TheCall, 1))
4656 unsigned NumElts = VecTy->getNumElements();
4666 case Builtin::BI__builtin_hlsl_wave_active_max:
4667 case Builtin::BI__builtin_hlsl_wave_active_min:
4668 case Builtin::BI__builtin_hlsl_wave_active_sum:
4669 case Builtin::BI__builtin_hlsl_wave_active_product: {
4670 if (
SemaRef.checkArgCount(TheCall, 1))
4683 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4684 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4685 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4686 if (
SemaRef.checkArgCount(TheCall, 1))
4701 (VTy && VTy->getElementType()->isIntegerType()))) {
4703 diag::err_builtin_invalid_arg_type)
4704 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4712 case Builtin::BI__builtin_hlsl_interlocked_add:
4713 case Builtin::BI__builtin_hlsl_interlocked_and:
4714 case Builtin::BI__builtin_hlsl_interlocked_max:
4715 case Builtin::BI__builtin_hlsl_interlocked_min:
4716 case Builtin::BI__builtin_hlsl_interlocked_or:
4717 case Builtin::BI__builtin_hlsl_interlocked_xor:
4723 case Builtin::BI__builtin_hlsl_interlocked_exchange:
4729 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
4735 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
4741 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
4747 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
4755 case Builtin::BI__builtin_elementwise_bitreverse: {
4763 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4764 if (
SemaRef.checkArgCount(TheCall, 1))
4769 if (!(
ArgType->isScalarType())) {
4771 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4776 if (!(
ArgType->isBooleanType())) {
4778 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4785 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4786 if (
SemaRef.checkArgCount(TheCall, 2))
4794 diag::err_typecheck_convert_incompatible)
4795 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4808 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
4809 if (
SemaRef.checkArgCount(TheCall, 1))
4818 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4819 if (
SemaRef.checkArgCount(TheCall, 0))
4823 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4824 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4825 if (
SemaRef.checkArgCount(TheCall, 1))
4838 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4839 case Builtin::BI__builtin_hlsl_quad_read_across_y:
4840 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
4841 if (
SemaRef.checkArgCount(TheCall, 1))
4853 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4854 if (
SemaRef.checkArgCount(TheCall, 3))
4860 SemaRef.Context.UnsignedIntTy, 1) ||
4862 SemaRef.Context.UnsignedIntTy, 2))
4870 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4871 if (
SemaRef.checkArgCount(TheCall, 1))
4878 case Builtin::BI__builtin_elementwise_acos:
4879 case Builtin::BI__builtin_elementwise_asin:
4880 case Builtin::BI__builtin_elementwise_atan:
4881 case Builtin::BI__builtin_elementwise_atan2:
4882 case Builtin::BI__builtin_elementwise_ceil:
4883 case Builtin::BI__builtin_elementwise_cos:
4884 case Builtin::BI__builtin_elementwise_cosh:
4885 case Builtin::BI__builtin_elementwise_exp:
4886 case Builtin::BI__builtin_elementwise_exp2:
4887 case Builtin::BI__builtin_elementwise_exp10:
4888 case Builtin::BI__builtin_elementwise_floor:
4889 case Builtin::BI__builtin_elementwise_fmod:
4890 case Builtin::BI__builtin_elementwise_log:
4891 case Builtin::BI__builtin_elementwise_log2:
4892 case Builtin::BI__builtin_elementwise_log10:
4893 case Builtin::BI__builtin_elementwise_pow:
4894 case Builtin::BI__builtin_elementwise_roundeven:
4895 case Builtin::BI__builtin_elementwise_sin:
4896 case Builtin::BI__builtin_elementwise_sinh:
4897 case Builtin::BI__builtin_elementwise_sqrt:
4898 case Builtin::BI__builtin_elementwise_tan:
4899 case Builtin::BI__builtin_elementwise_tanh:
4900 case Builtin::BI__builtin_elementwise_trunc: {
4906 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4907 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4908 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4909 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4910 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4915 std::optional<llvm::APSInt> Offset =
4917 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4919 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4925 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4926 if (
SemaRef.checkArgCount(TheCall, 1))
4937 ArgTy = VTy->getElementType();
4940 diag::err_builtin_invalid_arg_type)
4949 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4950 if (
SemaRef.checkArgCount(TheCall, 1))
4965 WorkList.push_back(BaseTy);
4966 while (!WorkList.empty()) {
4968 T =
T.getCanonicalType().getUnqualifiedType();
4969 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
4977 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4978 llvm::append_range(List, ElementFields);
4983 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
4984 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
4987 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
4988 List.insert(List.end(), MT->getNumElementsFlattened(),
4989 MT->getElementType());
4992 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
4993 if (RD->isStandardLayout())
4994 RD = RD->getStandardLayoutBaseWithFields();
4998 if (RD->
isUnion() || !RD->isAggregate()) {
5004 for (
const auto *FD : RD->
fields())
5005 if (!FD->isUnnamedBitField())
5006 FieldTypes.push_back(FD->
getType());
5008 std::reverse(FieldTypes.begin(), FieldTypes.end());
5009 llvm::append_range(WorkList, FieldTypes);
5013 if (!RD->isStandardLayout()) {
5015 for (
const auto &
Base : RD->bases())
5016 FieldTypes.push_back(
Base.getType());
5017 std::reverse(FieldTypes.begin(), FieldTypes.end());
5018 llvm::append_range(WorkList, FieldTypes);
5053 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5059 int ArraySize = VT->getNumElements();
5064 QualType ElTy = VT->getElementType();
5068 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5084 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5093 return llvm::equal(T1Types, T2Types,
5095 return SemaRef.IsLayoutCompatible(LHS, RHS);
5104 bool HadError =
false;
5106 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5114 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5115 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5116 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5117 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5119 if (NSpellingIdx != OSpellingIdx) {
5121 diag::err_hlsl_param_qualifier_mismatch)
5122 << NDAttr << NewParam;
5138 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5153 llvm_unreachable(
"HLSL doesn't support pointers.");
5156 llvm_unreachable(
"HLSL doesn't support complex types.");
5158 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5160 llvm_unreachable(
"Should have returned before this");
5170 llvm_unreachable(
"HLSL doesn't support complex types.");
5172 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5177 llvm_unreachable(
"HLSL doesn't support pointers.");
5179 llvm_unreachable(
"Should have returned before this");
5185 llvm_unreachable(
"HLSL doesn't support pointers.");
5188 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5192 llvm_unreachable(
"HLSL doesn't support complex types.");
5195 llvm_unreachable(
"Unhandled scalar cast");
5216 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5222 SrcTy = SrcMatTy->getElementType();
5227 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5228 if (DestTypes[I]->isUnionType())
5260 if (SrcTypes.size() < DestTypes.size())
5263 unsigned SrcSize = SrcTypes.size();
5264 unsigned DstSize = DestTypes.size();
5266 for (I = 0; I < DstSize && I < SrcSize; I++) {
5267 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5275 for (; I < SrcSize; I++) {
5276 if (SrcTypes[I]->isUnionType())
5283 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5284 "We should not get here without a parameter modifier expression");
5285 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5292 << Arg << (IsInOut ? 1 : 0);
5298 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5305 << Arg << (IsInOut ? 1 : 0);
5317 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5323 auto *OpV =
new (Ctx)
5329 tok::equal, ArgOpV, OpV);
5345 "Pointer and reference types cannot be inout or out parameters");
5346 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5362 for (
const auto *FD : RD->
fields()) {
5366 assert(RD->getNumBases() <= 1 &&
5367 "HLSL doesn't support multiple inheritance");
5368 return RD->getNumBases()
5373 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5374 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5386 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5391 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5397 if (
Decl->getType().hasAddressSpace())
5400 if (
Decl->getType()->isDependentType())
5412 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5426 llvm::Triple::Vulkan;
5427 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5428 if (HasDeclaredAPushConstant)
5434 HasDeclaredAPushConstant =
true;
5461class StructBindingContext {
5464 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5465 unsigned RegBindingOffset[4];
5468 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5469 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5470 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5471 static_cast<unsigned>(RegisterType::Sampler) == 3,
5472 "unexpected register type values");
5475 HLSLVkBindingAttr *VkBindingAttr;
5476 unsigned VkBindingOffset;
5481 StructBindingContext(
VarDecl *VD) {
5482 for (
unsigned i = 0; i < 4; ++i) {
5483 RegBindingsAttrs[i] =
nullptr;
5484 RegBindingOffset[i] = 0;
5486 VkBindingAttr =
nullptr;
5487 VkBindingOffset = 0;
5493 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5495 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5498 RegBindingsAttrs[RegTypeIdx] = RBA;
5503 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5504 VkBindingAttr = VBA;
5511 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5512 unsigned Range,
bool HasCounter) {
5513 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5515 if (VkBindingAttr) {
5516 unsigned Offset = VkBindingOffset;
5517 VkBindingOffset +=
Range;
5518 return HLSLVkBindingAttr::CreateImplicit(
5519 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5520 VkBindingAttr->getRange());
5523 HLSLResourceBindingAttr *RBA =
5524 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5525 HLSLResourceBindingAttr *NewAttr =
nullptr;
5527 if (RBA && RBA->hasRegisterSlot()) {
5530 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5531 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5533 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5534 StringRef NewSlotNumberStr =
5536 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5537 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5538 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5542 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5543 NewAttr->setBinding(RegType, std::nullopt,
5544 RBA ? RBA->getSpaceNumber() : 0);
5548 NewAttr->setImplicitCounterBindingOrderID(
5557static void createGlobalResourceDeclForStruct(
5559 QualType ResTy, StructBindingContext &BindingCtx) {
5561 "expected resource type or array of resources");
5572 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5573 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5578 const HLSLAttributedResourceType *ResHandleTy =
5579 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5583 Attr *BindingAttr = BindingCtx.createBindingAttr(
5585 ResDecl->
addAttr(BindingAttr);
5586 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5595 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5602static void handleArrayOfStructWithResources(
5604 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5609static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5611 EmbeddedResourceNameBuilder &NameBuilder,
5612 StructBindingContext &BindingCtx) {
5615 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5622 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5636 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5639 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5641 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5643 "resource arrays should have been already handled");
5644 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5653handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5655 EmbeddedResourceNameBuilder &NameBuilder,
5656 StructBindingContext &BindingCtx) {
5664 if (!SubCAT && !ElementRD)
5667 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5670 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5673 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5686void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5687 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5688 StructBindingContext BindingCtx(VD);
5692 "Expected non-resource struct or array type");
5695 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5699 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5700 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5708 if (
SemaRef.RequireCompleteType(
5711 diag::err_typecheck_decl_incomplete_type)) {
5725 DefaultCBufferDecls.push_back(VD);
5730 collectResourceBindingsOnVarDecl(VD);
5732 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5744 processExplicitBindingsOnDecl(VD);
5782 handleGlobalStructOrArrayOfWithResources(VD);
5786 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5795 "expected resource record type");
5811 const char *CreateMethodName;
5813 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5814 :
"__createFromBinding";
5816 CreateMethodName = HasCounter
5817 ?
"__createFromImplicitBindingWithImplicitCounter"
5818 :
"__createFromImplicitBinding";
5823 if (!CreateMethod) {
5828 "create method lookup should always succeed for built-in resource "
5837 Args.push_back(RegSlot);
5845 Args.push_back(OrderId);
5851 Args.push_back(Space);
5855 Args.push_back(RangeSize);
5859 Args.push_back(Index);
5861 StringRef VarName = VD->
getName();
5869 Args.push_back(NameCast);
5877 Args.push_back(CounterId);
5900 SemaRef.CheckCompleteVariableDeclaration(VD);
5906 "expected array of resource records");
5927 lookupMethod(
SemaRef, ResourceDecl,
5928 HasCounter ?
"__createFromBindingWithImplicitCounter"
5929 :
"__createFromBinding",
5933 CreateMethod = lookupMethod(
5935 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5936 :
"__createFromImplicitBinding",
5979std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5980 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5981 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5982 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5983 if (!TrueInfo || !FalseInfo)
5984 return std::nullopt;
5985 if (*TrueInfo != *FalseInfo)
5986 return std::nullopt;
5990 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5999 if (
const auto *AttrResType =
6000 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6002 return Bindings.getDeclBindingInfo(VD, RC);
6009void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6010 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6013 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6018 if (*ExprBinding ==
nullptr)
6021 auto PrevBinding = Assigns.find(VD);
6022 if (PrevBinding == Assigns.end()) {
6024 Assigns.insert({VD, *ExprBinding});
6029 if (*ExprBinding != PrevBinding->second) {
6031 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6033 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6044 "expected LHS to be a resource record or array of resource records");
6045 if (Opc != BO_Assign)
6050 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6058 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6063 trackLocalResource(VD, RHSExpr);
6080void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6082 "expected global variable that contains HLSL resource");
6085 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6086 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6087 ? ResourceClass::CBuffer
6088 : ResourceClass::SRV);
6101 if (
const HLSLAttributedResourceType *AttrResType =
6102 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6103 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6108 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6109 collectResourceBindingsOnUserRecordDecl(VD, RT);
6115void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6118 bool HasBinding =
false;
6119 for (Attr *A : VD->
attrs()) {
6122 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6123 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6126 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6127 if (!RBA || !RBA->hasRegisterSlot())
6132 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6133 "never have an attribute created");
6135 if (RT == RegisterType::C) {
6136 if (Bindings.hasBindingInfoForDecl(VD))
6138 diag::warn_hlsl_user_defined_type_missing_member)
6139 <<
static_cast<int>(RT);
6147 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6152 diag::warn_hlsl_user_defined_type_missing_member)
6153 <<
static_cast<int>(RT);
6161class InitListTransformer {
6165 QualType *DstIt =
nullptr;
6166 Expr **ArgIt =
nullptr;
6172 bool castInitializer(Expr *E) {
6173 assert(DstIt &&
"This should always be something!");
6174 if (DstIt == DestTypes.end()) {
6176 ArgExprs.push_back(E);
6181 DstIt = DestTypes.begin();
6184 Ctx, *DstIt,
false);
6189 ArgExprs.push_back(
Init);
6194 bool buildInitializerListImpl(Expr *E) {
6196 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6197 for (
auto *SubInit :
Init->inits())
6198 if (!buildInitializerListImpl(SubInit))
6208 return castInitializer(E);
6222 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6227 for (uint64_t I = 0; I <
Size; ++I) {
6229 SizeTy, SourceLocation());
6235 if (!castInitializer(ElExpr.
get()))
6240 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6241 unsigned Rows = MTy->getNumRows();
6242 unsigned Cols = MTy->getNumColumns();
6243 QualType ElemTy = MTy->getElementType();
6245 for (
unsigned R = 0;
R < Rows; ++
R) {
6246 for (
unsigned C = 0;
C < Cols; ++
C) {
6259 if (!castInitializer(ElExpr.
get()))
6267 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6271 for (uint64_t I = 0; I <
Size; ++I) {
6273 SizeTy, SourceLocation());
6278 if (!buildInitializerListImpl(ElExpr.
get()))
6285 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6286 RecordDecls.push_back(RD);
6287 while (RecordDecls.back()->getNumBases()) {
6288 CXXRecordDecl *D = RecordDecls.back();
6290 "HLSL doesn't support multiple inheritance");
6291 RecordDecls.push_back(
6294 while (!RecordDecls.empty()) {
6295 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6296 for (
auto *FD : RD->
fields()) {
6297 if (FD->isUnnamedBitField())
6305 if (!buildInitializerListImpl(Res.
get()))
6313 Expr *generateInitListsImpl(QualType Ty) {
6315 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6320 llvm::SmallVector<Expr *>
Inits;
6325 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6326 ElTy = ATy->getElementType();
6327 Size = ATy->getNumElements();
6328 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6329 ElTy = CMTy->getElementType();
6330 Size = CMTy->getNumElementsFlattened();
6333 ElTy = VTy->getElementType();
6334 Size = VTy->getZExtSize();
6336 for (uint64_t I = 0; I <
Size; ++I)
6337 Inits.push_back(generateInitListsImpl(ElTy));
6340 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6341 RecordDecls.push_back(RD);
6342 while (RecordDecls.back()->getNumBases()) {
6343 CXXRecordDecl *D = RecordDecls.back();
6345 "HLSL doesn't support multiple inheritance");
6346 RecordDecls.push_back(
6349 while (!RecordDecls.empty()) {
6350 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6351 for (
auto *FD : RD->
fields())
6352 if (!FD->isUnnamedBitField())
6357 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6358 Inits.back()->getEndLoc(),
false);
6359 NewInit->setType(Ty);
6364 llvm::SmallVector<QualType, 16> DestTypes;
6365 llvm::SmallVector<Expr *, 16> ArgExprs;
6366 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6367 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6368 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6369 InitTy = Entity.
getType().getNonReferenceType();
6379 DstIt = DestTypes.begin();
6382 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6384 Expr *generateInitLists() {
6385 assert(!ArgExprs.empty() &&
6386 "Call buildInitializerList to generate argument expressions.");
6387 ArgIt = ArgExprs.begin();
6389 return generateInitListsImpl(InitTy);
6390 llvm::SmallVector<Expr *>
Inits;
6391 while (ArgIt != ArgExprs.end())
6392 Inits.push_back(generateInitListsImpl(InitTy));
6395 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6396 Inits.back()->getEndLoc(),
false);
6397 llvm::APInt ArySize(64,
Inits.size());
6399 ArraySizeModifier::Normal, 0));
6411 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6418 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6422 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6442 if (
Init->getType()->isScalarType())
6445 InitListTransformer ILT(
SemaRef, Entity);
6447 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6455 Init->setInit(I, E);
6457 if (!ILT.buildInitializerList(E))
6460 size_t ExpectedSize = ILT.DestTypes.size();
6461 size_t ActualSize = ILT.ArgExprs.size();
6462 if (ExpectedSize == 0 && ActualSize == 0)
6469 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6471 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6472 << (int)(ExpectedSize < ActualSize) << InitTy
6473 << ExpectedSize << ActualSize;
6483 assert(ExpectedSize > 0 &&
6484 "The expected size of an incomplete array type must be at least 1.");
6486 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6494 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6495 if (ExpectedSize != ActualSize) {
6496 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6497 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6498 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6505 Init->resizeInits(Ctx, NewInit->getNumInits());
6506 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6507 Init->updateInit(Ctx, I, NewInit->getInit(I));
6515 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6525 StringRef AccessorName = CompName->
getName();
6526 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6528 unsigned Rows = MT->getNumRows();
6529 unsigned Cols = MT->getNumColumns();
6530 bool IsZeroBasedAccessor =
false;
6531 unsigned ChunkLen = 0;
6532 if (AccessorName.size() < 2)
6534 "length 4 for zero based: \'_mRC\' or "
6535 "length 3 for one-based: \'_RC\' accessor",
6538 if (AccessorName[0] ==
'_') {
6539 if (AccessorName[1] ==
'm') {
6540 IsZeroBasedAccessor =
true;
6547 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6550 if (AccessorName.size() % ChunkLen != 0) {
6551 const llvm::StringRef
Expected = IsZeroBasedAccessor
6552 ?
"zero based: '_mRC' accessor"
6553 :
"one-based: '_RC' accessor";
6558 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6559 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6560 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6562 bool HasRepeated =
false;
6564 unsigned NumComponents = 0;
6565 const char *Begin = AccessorName.data();
6567 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6568 const char *Chunk = Begin + I;
6569 char RowChar = 0, ColChar = 0;
6570 if (IsZeroBasedAccessor) {
6572 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6573 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6575 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6582 if (Chunk[0] !=
'_')
6584 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6591 bool IsDigitsError =
false;
6593 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6597 IsDigitsError =
true;
6601 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6605 IsDigitsError =
true;
6610 unsigned Row = RowChar -
'0';
6611 unsigned Col = ColChar -
'0';
6613 bool HasIndexingError =
false;
6614 if (IsZeroBasedAccessor) {
6616 if (!isZeroBasedIndex(Row)) {
6617 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6619 HasIndexingError =
true;
6621 if (!isZeroBasedIndex(Col)) {
6622 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6624 HasIndexingError =
true;
6628 if (!isOneBasedIndex(Row)) {
6629 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6631 HasIndexingError =
true;
6633 if (!isOneBasedIndex(Col)) {
6634 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6636 HasIndexingError =
true;
6643 if (HasIndexingError)
6649 bool HasBoundsError =
false;
6651 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6653 HasBoundsError =
true;
6656 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6658 HasBoundsError =
true;
6663 unsigned FlatIndex = Row * Cols + Col;
6664 if (Seen[FlatIndex])
6666 Seen[FlatIndex] =
true;
6669 if (NumComponents == 0 || NumComponents > 4) {
6670 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6675 QualType ElemTy = MT->getElementType();
6676 if (NumComponents == 1)
6682 for (Sema::ExtVectorDeclsType::iterator
6686 if ((*I)->getUnderlyingType() == VT)
6697 trackLocalResource(VDecl,
Init);
6699 const HLSLVkConstantIdAttr *ConstIdAttr =
6700 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6707 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
6717 int ConstantID = ConstIdAttr->getId();
6718 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6720 ConstIdAttr->getLocation());
6724 if (
C->getType()->getCanonicalTypeUnqualified() !=
6728 Context.getTrivialTypeSourceInfo(
6729 Init->getType(),
Init->getExprLoc()),
6748 if (!Params || Params->
size() != 1)
6761 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6762 if (TTP->hasDefaultArgument()) {
6763 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6766 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6767 if (NTTP->hasDefaultArgument()) {
6768 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6771 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6772 if (TTPD->hasDefaultArgument()) {
6773 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6780 return SemaRef.CheckTemplateIdType(
6782 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 bool CheckInterlockedBuiltin(Sema &S, CallExpr *TheCall, unsigned MinArgs, unsigned MaxArgs, InterlockedDest Dest, bool ReportsOriginalValue)
Check a call to an HLSL interlocked builtin.
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool 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)
InterlockedDest
The dest types an interlocked operation accepts. Float is 32-bit only.
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static QualType getVectorOrScalarType(Sema &S, QualType BaseType, unsigned Count)
static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind)
static bool CheckScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckFloatRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyDoubleRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
static StringRef getCurrentResourceMethodName(Sema &S, StringRef DefaultName)
static bool IsDefaultBufferConstantDecl(const ASTContext &Ctx, VarDecl *VD)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool CheckGatherBuiltin(Sema &S, CallExpr *TheCall, bool IsCmp)
static bool isValidWaveSizeValue(unsigned Value)
static bool isResourceRecordTypeOrArrayOf(QualType Ty)
static bool CheckLoadMSBuiltin(Sema &S, CallExpr *TheCall)
static bool AccumulateHLSLResourceSlots(QualType Ty, uint64_t &StartSlot, const uint64_t &Limit, const ResourceClass ResClass, ASTContext &Ctx, uint64_t ArrayCount=1)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns, std::optional< MatrixType::LayoutKind > Layout=std::nullopt) const
Return the unique reference to the matrix type of the specified element type and size.
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
llvm::StringRef backupStr(llvm::StringRef S) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getLocation() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
base_class_iterator bases_end()
void completeDefinition() override
Indicates that the definition of this class is now complete.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
bool isHLSLBuiltinRecord() const
Returns true if the class is a built-in HLSL record.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceLocation getEndLoc() const
static CanQual< Type > CreateUnsafe(QualType Other)
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
llvm::APInt getSize() const
Return the constant array size as an APInt.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
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.
bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount)
Checks that a call expression's argument count is at most the desired number.
ExtVectorDeclsType ExtVectorDecls
ExtVectorDecls - This is a list all the extended vector types.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult TemporaryMaterializationConversion(Expr *E)
If E is a prvalue denoting an unmaterialized temporary, materialize it as an xvalue.
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExternalSemaSource * getExternalSource() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool 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