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;
2769 switch (BuiltinID) {
2770 case Builtin::BI__builtin_hlsl_mul:
2771 case Builtin::BI__builtin_hlsl_transpose:
2779 if (!E || DestType.
isNull())
2791 if (!CallMat || CallMat->getNumRows() != DestMat->getNumRows() ||
2792 CallMat->getNumColumns() != DestMat->getNumColumns())
2841 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2845 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2846 unsigned CurrentShaderStageBit;
2851 bool ReportOnlyShaderStageIssues;
2854 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2855 static_assert(
sizeof(
unsigned) >= 4);
2856 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2857 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2858 "ShaderType is too big for this bitmap");
2861 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2862 CurrentShaderEnvironment = ShaderType;
2863 CurrentShaderStageBit = (1 << bitmapIndex);
2866 void SetUnknownShaderStageContext() {
2867 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2868 CurrentShaderStageBit = (1 << 31);
2871 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2872 return CurrentShaderEnvironment;
2875 bool InUnknownShaderStageContext()
const {
2876 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2880 void AddToScannedFunctions(
const FunctionDecl *FD) {
2881 unsigned &ScannedStages = ScannedDecls[FD];
2882 ScannedStages |= CurrentShaderStageBit;
2885 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2887 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2888 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2891 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2892 return ScannerStages & CurrentShaderStageBit;
2895 static bool NeverBeenScanned(
unsigned ScannedStages) {
2896 return ScannedStages == 0;
2900 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2901 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2903 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2904 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2907 DiagnoseHLSLAvailability(Sema &SemaRef)
2909 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2910 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2913 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2914 void RunOnFunction(
const FunctionDecl *FD);
2916 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2917 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2919 HandleFunctionOrMethodRef(FD, DRE);
2923 bool VisitMemberExpr(MemberExpr *ME)
override {
2924 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2926 HandleFunctionOrMethodRef(FD, ME);
2931void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2934 "expected DeclRefExpr or MemberExpr");
2936 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
2937 CheckDeclAvailability(
2942 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
2943 DeclsToScan.push_back(FDWithBody);
2946void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2951 llvm::Triple::EnvironmentType::Library;
2960 DeclContextsToScan.push_back(TU);
2962 while (!DeclContextsToScan.empty()) {
2963 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2964 for (
auto &D : DC->
decls()) {
2971 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2972 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2977 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2982 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2983 if (!IsLibraryShader && FD->
getName() == EntryName) {
2986 diag::err_hlsl_ambiguous_entry_point)
2988 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
2994 SetShaderStageContext(ShaderAttr->getType());
3003 for (
const auto *Redecl : FD->
redecls()) {
3004 if (Redecl->isInExportDeclContext()) {
3011 SetUnknownShaderStageContext();
3018 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3025void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3026 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3027 DeclsToScan.push_back(FD);
3029 while (!DeclsToScan.empty()) {
3037 const unsigned ScannedStages = GetScannedStages(FD);
3038 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3041 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3043 AddToScannedFunctions(FD);
3048bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3049 const AvailabilityAttr *AA) {
3054 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3055 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3058 llvm::Triple::EnvironmentType AttrEnv =
3059 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3061 return CurrentEnv == AttrEnv;
3064const AvailabilityAttr *
3065DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3066 AvailabilityAttr
const *PartialMatch =
nullptr;
3070 for (
const auto *A : D->
attrs()) {
3071 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3072 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3073 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3074 StringRef TargetPlatform =
3078 if (AttrPlatform == TargetPlatform) {
3080 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3082 PartialMatch = Avail;
3086 return PartialMatch;
3091void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3092 const AvailabilityAttr *AA,
3111 if (ReportOnlyShaderStageIssues)
3117 if (InUnknownShaderStageContext())
3122 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3123 VersionTuple Introduced = AA->getIntroduced();
3132 llvm::StringRef PlatformName(
3135 llvm::StringRef CurrentEnvStr =
3136 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3138 llvm::StringRef AttrEnvStr =
3139 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3140 bool UseEnvironment = !AttrEnvStr.empty();
3142 if (EnvironmentMatches) {
3143 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3144 <<
Range << D << PlatformName << Introduced.getAsString()
3145 << UseEnvironment << CurrentEnvStr;
3147 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3151 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3152 << D << PlatformName << Introduced.getAsString()
3154 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3161 if (!DefaultCBufferDecls.empty()) {
3164 DefaultCBufferDecls);
3167 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3171 for (
const Decl *VD : DefaultCBufferDecls) {
3172 const HLSLResourceBindingAttr *RBA =
3173 VD->
getAttr<HLSLResourceBindingAttr>();
3174 if (RBA && RBA->hasRegisterSlot() &&
3175 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3182 SemaRef.Consumer.HandleTopLevelDecl(DG);
3184 diagnoseAvailabilityViolations(TU);
3193 "expected member expr to have resource record type or array of them");
3199 const Expr *NonConstIndexExpr =
nullptr;
3202 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3203 if (!NonConstIndexExpr)
3211 diag::err_hlsl_resource_member_array_access_not_constant);
3215 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3216 const Expr *IdxExpr = ASE->getIdx();
3218 NonConstIndexExpr = IdxExpr;
3220 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3221 E = SubME->getBase();
3222 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3223 E = ICE->getSubExpr();
3225 llvm_unreachable(
"unexpected expr type in resource member access");
3234 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3237 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3240 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3244 [[maybe_unused]]
bool LookupSucceeded =
3245 SemaRef.LookupQualifiedName(ConvR, RD);
3246 assert(LookupSucceeded);
3255std::optional<ExprResult>
3258 const HLSLAttributedResourceType *ResTy =
3259 HLSLAttributedResourceType::findHandleTypeOnResource(
3260 BaseType.getTypePtr());
3262 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3263 return std::nullopt;
3265 QualType TemplateType = ResTy->getContainedType();
3269 assert(NamedConversionDecl &&
3270 "Could not find conversion function for ConstantBuffer.");
3271 auto *ConversionDecl =
3274 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3286 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3289 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3296 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3299 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3324 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3339 if (!BaseType->isFloat32Type())
3340 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3341 << ArgOrdinal << 5 << 0
3351 BaseType = VT->getElementType();
3353 BaseType = MT->getElementType();
3355 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3356 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3357 << ArgOrdinal << 5 << 0
3371 if (!BaseType->isDoubleType()) {
3374 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3375 << ArgOrdinal << PassedType;
3382 unsigned ArgIndex) {
3383 auto *Arg = TheCall->
getArg(ArgIndex);
3385 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3388 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3402 << (ArgIndex + 1) << LValueTy;
3412 if (VecTy->getElementType()->isDoubleType())
3413 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3414 << ArgOrdinal << 1 << 0 << 1
3424 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3425 << ArgOrdinal << 5 << 1
3434 if (VecTy->getElementType()->isUnsignedIntegerType())
3437 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3438 << ArgOrdinal << 4 << 3 << 0
3447 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3448 << ArgOrdinal << 5 << 3
3454 unsigned ArgOrdinal,
unsigned Width) {
3457 ArgTy = VTy->getElementType();
3459 uint64_t ElementBitCount =
3461 if (ElementBitCount != Width) {
3463 diag::err_integer_incorrect_bit_count)
3464 << Width << ElementBitCount;
3475 else if (
auto *MatTyA =
3478 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3484 unsigned ArgIndex) {
3493 diag::err_typecheck_expect_scalar_or_vector)
3494 << ArgType << Scalar;
3501 QualType Scalar,
unsigned ArgIndex) {
3512 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3525 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3526 << ArgType << Scalar;
3531 unsigned ArgIndex) {
3536 if (!(ArgType->isScalarType() ||
3537 (VTy && VTy->getElementType()->isScalarType()))) {
3539 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3547 unsigned ArgIndex) {
3550 if (ArgType->isDependentType())
3554 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3555 ElementType = VectorTy->getElementType();
3557 ElementType = MatrixTy->getElementType();
3559 if (ElementType->isBooleanType())
3562 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3564 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3569 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3577 unsigned ArgIndex) {
3579 assert(ArgIndex < TheCall->getNumArgs());
3587 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3612 diag::err_typecheck_call_different_arg_types)
3631 Arg1ScalarTy = VTy->getElementType();
3635 Arg2ScalarTy = VTy->getElementType();
3638 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3639 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3649 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3651 diag::err_typecheck_vector_lengths_not_equal)
3657 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3659 diag::err_typecheck_vector_lengths_not_equal)
3676 unsigned ArgIndex) {
3681 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3684 unsigned int ActualDim = 1;
3686 ActualDim = VTy->getNumElements();
3687 IndexTy = VTy->getElementType();
3691 diag::err_typecheck_expect_int)
3697 const HLSLAttributedResourceType *ResTy =
3699 assert(ResTy &&
"Resource argument must be a resource");
3700 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3702 unsigned int ExpectedDim = 1;
3703 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3705 (ResAttrs.IsArray ? 1 : 0);
3707 if (ActualDim != ExpectedDim) {
3709 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3720 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3724 const HLSLAttributedResourceType *ResTy =
3728 diag::err_typecheck_expect_hlsl_resource)
3732 if (Check && Check(ResTy)) {
3734 diag::err_invalid_hlsl_resource_type)
3744 "expected resource handle type");
3745 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3746 auto MainAttrs = MainResType->getAttrs();
3747 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3748 MainAttrs.IsCounter =
true;
3750 MainResType->getContainedType(),
3761 return "SampleBias";
3763 return "SampleGrad";
3765 return "SampleLevel";
3769 return "SampleCmpLevelZero";
3771 llvm_unreachable(
"Invalid SampleKind");
3781 if (!MD || !MD->getDeclName().isIdentifier())
3788 return MD->getName();
3796 return VecTy->getElementType();
3797 return ContainedType;
3805 StringRef DefaultName) {
3810 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
3837 if (SMVersion >= VersionTuple(6, 7))
3840 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
3842 << ContainedType << SMVersion.getAsString();
3847 bool IncludeArraySlice =
true) {
3850 [](
const HLSLAttributedResourceType *ResType) {
3851 return ResType->getAttrs().ResourceDimension ==
3852 llvm::dxil::ResourceDimension::Unknown;
3858 [](
const HLSLAttributedResourceType *ResType) {
3859 return ResType->getAttrs().ResourceClass !=
3860 llvm::hlsl::ResourceClass::Sampler;
3868 unsigned ExpectedDim =
3870 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
3899 unsigned NextIdx = 3;
3911 Expr *ComponentArg = TheCall->
getArg(NextIdx);
3915 std::optional<llvm::APSInt> ComponentOpt =
3918 int64_t ComponentVal = ComponentOpt->getSExtValue();
3919 if (ComponentVal != 0) {
3922 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
3923 "The component is not in the expected range.");
3925 diag::err_hlsl_gathercmp_invalid_component)
3935 const HLSLAttributedResourceType *ResourceTy =
3938 unsigned ExpectedDim =
3941 &S, TheCall->
getArg(NextIdx),
3947 assert(ResourceTy->hasContainedType() &&
3948 "Expecting a contained type for resource with a dimension "
3950 QualType ReturnType = ResourceTy->getContainedType();
3953 IsCmp ?
"GatherCmp" :
"Gather"))
3958 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
3964 ReturnType = VecTy->getElementType();
3977 [](
const HLSLAttributedResourceType *ResType) {
3978 return ResType->getAttrs().ResourceDimension ==
3979 llvm::dxil::ResourceDimension::Unknown;
3989 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
3996 unsigned ResourceDim =
3998 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4014 TheCall->
setType(ResourceTy->getContainedType());
4024 [](
const HLSLAttributedResourceType *ResType) {
4025 return !ResType->isMultiSampled();
4034 unsigned ResourceDim =
4036 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4054 TheCall->
setType(ResourceTy->getContainedType());
4059 unsigned MinArgs, MaxArgs;
4087 const HLSLAttributedResourceType *ResourceTy =
4089 unsigned ExpectedDim =
4092 unsigned NextIdx = 3;
4117 &S, TheCall->
getArg(NextIdx),
4130 assert(ResourceTy->hasContainedType() &&
4131 "Expecting a contained type for resource with a dimension "
4133 QualType ReturnType = ResourceTy->getContainedType();
4144 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4157 switch (BuiltinID) {
4158 case Builtin::BI__builtin_hlsl_adduint64: {
4159 if (
SemaRef.checkArgCount(TheCall, 2))
4173 if (NumElementsArg != 2 && NumElementsArg != 4) {
4175 << 1 << 64 << NumElementsArg * 32;
4189 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4190 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4197 QualType ContainedTy = ResourceTy->getContainedType();
4198 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4201 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4206 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4207 if (
SemaRef.checkArgCount(TheCall, 3) ||
4214 "expected pointer type for second argument");
4221 diag::err_invalid_use_of_array_type);
4225 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4228 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4233 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4234 if (
SemaRef.checkArgCount(TheCall, 2) ||
4236 SemaRef.getASTContext().IntTy))
4243 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4244 if (
SemaRef.checkArgCount(TheCall, 3) ||
4247 SemaRef.getASTContext().UnsignedIntTy) ||
4249 SemaRef.getASTContext().UnsignedIntTy) ||
4255 QualType ReturnType = ResourceTy->getContainedType();
4260 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4261 if (
SemaRef.checkArgCount(TheCall, 4) ||
4264 SemaRef.getASTContext().UnsignedIntTy) ||
4266 SemaRef.getASTContext().UnsignedIntTy) ||
4272 "expected pointer type for second argument");
4279 diag::err_invalid_use_of_array_type);
4285 case Builtin::BI__builtin_hlsl_resource_load_level:
4287 case Builtin::BI__builtin_hlsl_resource_load_ms:
4289 case Builtin::BI__builtin_hlsl_resource_sample:
4291 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4293 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4295 case Builtin::BI__builtin_hlsl_resource_sample_level:
4297 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4299 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4301 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4302 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4304 case Builtin::BI__builtin_hlsl_resource_gather:
4306 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4308 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4309 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4315 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4316 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4322 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4323 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4329 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4330 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4336 TheCall->
setType(CounterHandleTy);
4339 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4340 if (
SemaRef.checkArgCount(TheCall, 2) ||
4343 SemaRef.getASTContext().UnsignedIntTy))
4351 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4352 if (
SemaRef.checkArgCount(TheCall, 1) ||
4360 TheCall->
setType(CounterHandleTy);
4363 case Builtin::BI__builtin_hlsl_and:
4364 case Builtin::BI__builtin_hlsl_or: {
4365 if (
SemaRef.checkArgCount(TheCall, 2))
4379 case Builtin::BI__builtin_hlsl_all:
4380 case Builtin::BI__builtin_hlsl_any: {
4381 if (
SemaRef.checkArgCount(TheCall, 1))
4387 case Builtin::BI__builtin_hlsl_asdouble: {
4388 if (
SemaRef.checkArgCount(TheCall, 2))
4392 SemaRef.Context.UnsignedIntTy,
4397 SemaRef.Context.UnsignedIntTy,
4406 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4407 if (
SemaRef.BuiltinElementwiseTernaryMath(
4413 case Builtin::BI__builtin_hlsl_dot: {
4415 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4421 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4422 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4423 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4433 EltTy = VecTy->getElementType();
4434 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4447 case Builtin::BI__builtin_hlsl_select: {
4448 if (
SemaRef.checkArgCount(TheCall, 3))
4456 if (VTy && VTy->getElementType()->isBooleanType() &&
4461 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4462 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4463 if (
SemaRef.checkArgCount(TheCall, 1))
4469 diag::err_builtin_invalid_arg_type)
4472 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4476 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4477 case Builtin::BI__builtin_hlsl_elementwise_frac:
4478 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4479 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4480 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4481 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4482 if (
SemaRef.checkArgCount(TheCall, 1))
4487 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4491 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4492 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4493 if (
SemaRef.checkArgCount(TheCall, 1))
4498 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4503 case Builtin::BI__builtin_hlsl_mad: {
4504 if (
SemaRef.BuiltinElementwiseTernaryMath(
4510 case Builtin::BI__builtin_hlsl_mul: {
4511 if (
SemaRef.checkArgCount(TheCall, 2))
4521 return VTy->getElementType();
4523 return MTy->getElementType();
4527 QualType EltTy0 = getElemType(Ty0);
4536 if (IsVec0 && IsMat1) {
4539 }
else if (IsMat0 && IsVec1) {
4543 assert(IsMat0 && IsMat1);
4553 case Builtin::BI__builtin_elementwise_fma: {
4554 if (
SemaRef.checkArgCount(TheCall, 3) ||
4569 case Builtin::BI__builtin_hlsl_transpose: {
4570 if (
SemaRef.checkArgCount(TheCall, 1))
4579 << 1 << 3 << 0 << 0 << ArgTy;
4584 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4588 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4589 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4597 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4598 if (
SemaRef.checkArgCount(TheCall, 1))
4612 unsigned NumElts = VecTy->getNumElements();
4622 case Builtin::BI__builtin_hlsl_wave_active_max:
4623 case Builtin::BI__builtin_hlsl_wave_active_min:
4624 case Builtin::BI__builtin_hlsl_wave_active_sum:
4625 case Builtin::BI__builtin_hlsl_wave_active_product: {
4626 if (
SemaRef.checkArgCount(TheCall, 1))
4639 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4640 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4641 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4642 if (
SemaRef.checkArgCount(TheCall, 1))
4657 (VTy && VTy->getElementType()->isIntegerType()))) {
4659 diag::err_builtin_invalid_arg_type)
4660 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4668 case Builtin::BI__builtin_hlsl_interlocked_add:
4669 case Builtin::BI__builtin_hlsl_interlocked_and:
4670 case Builtin::BI__builtin_hlsl_interlocked_exchange:
4671 case Builtin::BI__builtin_hlsl_interlocked_max:
4672 case Builtin::BI__builtin_hlsl_interlocked_min:
4673 case Builtin::BI__builtin_hlsl_interlocked_or:
4674 case Builtin::BI__builtin_hlsl_interlocked_xor: {
4684 if (BuiltinID == Builtin::BI__builtin_hlsl_interlocked_exchange) {
4685 if (
SemaRef.checkArgCount(TheCall, 3))
4690 diag::err_typecheck_call_too_few_args_at_least)
4695 if (
SemaRef.checkArgCountAtMost(TheCall, 3))
4703 const bool AllowsFloat =
4704 BuiltinID == Builtin::BI__builtin_hlsl_interlocked_exchange;
4708 diag::err_builtin_invalid_arg_type)
4710 << (AllowsFloat ? 3 : 0) << DestTy;
4720 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4721 SemaRef.Context.getTypeSize(DestTy) == 64 &&
4750 case Builtin::BI__builtin_elementwise_bitreverse: {
4758 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4759 if (
SemaRef.checkArgCount(TheCall, 1))
4764 if (!(
ArgType->isScalarType())) {
4766 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4771 if (!(
ArgType->isBooleanType())) {
4773 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4780 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4781 if (
SemaRef.checkArgCount(TheCall, 2))
4789 diag::err_typecheck_convert_incompatible)
4790 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4803 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
4804 if (
SemaRef.checkArgCount(TheCall, 1))
4813 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4814 if (
SemaRef.checkArgCount(TheCall, 0))
4818 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4819 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4820 if (
SemaRef.checkArgCount(TheCall, 1))
4833 case Builtin::BI__builtin_hlsl_quad_read_across_x:
4834 case Builtin::BI__builtin_hlsl_quad_read_across_y:
4835 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
4836 if (
SemaRef.checkArgCount(TheCall, 1))
4848 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
4849 if (
SemaRef.checkArgCount(TheCall, 3))
4855 SemaRef.Context.UnsignedIntTy, 1) ||
4857 SemaRef.Context.UnsignedIntTy, 2))
4865 case Builtin::BI__builtin_hlsl_elementwise_clip: {
4866 if (
SemaRef.checkArgCount(TheCall, 1))
4873 case Builtin::BI__builtin_elementwise_acos:
4874 case Builtin::BI__builtin_elementwise_asin:
4875 case Builtin::BI__builtin_elementwise_atan:
4876 case Builtin::BI__builtin_elementwise_atan2:
4877 case Builtin::BI__builtin_elementwise_ceil:
4878 case Builtin::BI__builtin_elementwise_cos:
4879 case Builtin::BI__builtin_elementwise_cosh:
4880 case Builtin::BI__builtin_elementwise_exp:
4881 case Builtin::BI__builtin_elementwise_exp2:
4882 case Builtin::BI__builtin_elementwise_exp10:
4883 case Builtin::BI__builtin_elementwise_floor:
4884 case Builtin::BI__builtin_elementwise_fmod:
4885 case Builtin::BI__builtin_elementwise_log:
4886 case Builtin::BI__builtin_elementwise_log2:
4887 case Builtin::BI__builtin_elementwise_log10:
4888 case Builtin::BI__builtin_elementwise_pow:
4889 case Builtin::BI__builtin_elementwise_roundeven:
4890 case Builtin::BI__builtin_elementwise_sin:
4891 case Builtin::BI__builtin_elementwise_sinh:
4892 case Builtin::BI__builtin_elementwise_sqrt:
4893 case Builtin::BI__builtin_elementwise_tan:
4894 case Builtin::BI__builtin_elementwise_tanh:
4895 case Builtin::BI__builtin_elementwise_trunc: {
4901 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
4902 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
4903 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
4904 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
4905 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
4910 std::optional<llvm::APSInt> Offset =
4912 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
4914 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
4920 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
4921 if (
SemaRef.checkArgCount(TheCall, 1))
4932 ArgTy = VTy->getElementType();
4935 diag::err_builtin_invalid_arg_type)
4944 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
4945 if (
SemaRef.checkArgCount(TheCall, 1))
4960 WorkList.push_back(BaseTy);
4961 while (!WorkList.empty()) {
4963 T =
T.getCanonicalType().getUnqualifiedType();
4964 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
4972 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
4973 llvm::append_range(List, ElementFields);
4978 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
4979 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
4982 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
4983 List.insert(List.end(), MT->getNumElementsFlattened(),
4984 MT->getElementType());
4987 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
4988 if (RD->isStandardLayout())
4989 RD = RD->getStandardLayoutBaseWithFields();
4993 if (RD->
isUnion() || !RD->isAggregate()) {
4999 for (
const auto *FD : RD->
fields())
5000 if (!FD->isUnnamedBitField())
5001 FieldTypes.push_back(FD->
getType());
5003 std::reverse(FieldTypes.begin(), FieldTypes.end());
5004 llvm::append_range(WorkList, FieldTypes);
5008 if (!RD->isStandardLayout()) {
5010 for (
const auto &
Base : RD->bases())
5011 FieldTypes.push_back(
Base.getType());
5012 std::reverse(FieldTypes.begin(), FieldTypes.end());
5013 llvm::append_range(WorkList, FieldTypes);
5048 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5054 int ArraySize = VT->getNumElements();
5059 QualType ElTy = VT->getElementType();
5063 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5079 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5088 return llvm::equal(T1Types, T2Types,
5090 return SemaRef.IsLayoutCompatible(LHS, RHS);
5099 bool HadError =
false;
5101 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5109 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5110 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5111 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5112 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5114 if (NSpellingIdx != OSpellingIdx) {
5116 diag::err_hlsl_param_qualifier_mismatch)
5117 << NDAttr << NewParam;
5133 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5148 llvm_unreachable(
"HLSL doesn't support pointers.");
5151 llvm_unreachable(
"HLSL doesn't support complex types.");
5153 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5155 llvm_unreachable(
"Should have returned before this");
5165 llvm_unreachable(
"HLSL doesn't support complex types.");
5167 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5172 llvm_unreachable(
"HLSL doesn't support pointers.");
5174 llvm_unreachable(
"Should have returned before this");
5180 llvm_unreachable(
"HLSL doesn't support pointers.");
5183 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5187 llvm_unreachable(
"HLSL doesn't support complex types.");
5190 llvm_unreachable(
"Unhandled scalar cast");
5211 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5217 SrcTy = SrcMatTy->getElementType();
5222 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5223 if (DestTypes[I]->isUnionType())
5255 if (SrcTypes.size() < DestTypes.size())
5258 unsigned SrcSize = SrcTypes.size();
5259 unsigned DstSize = DestTypes.size();
5261 for (I = 0; I < DstSize && I < SrcSize; I++) {
5262 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5270 for (; I < SrcSize; I++) {
5271 if (SrcTypes[I]->isUnionType())
5278 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5279 "We should not get here without a parameter modifier expression");
5280 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5287 << Arg << (IsInOut ? 1 : 0);
5293 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5300 << Arg << (IsInOut ? 1 : 0);
5312 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5318 auto *OpV =
new (Ctx)
5324 tok::equal, ArgOpV, OpV);
5340 "Pointer and reference types cannot be inout or out parameters");
5341 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5357 for (
const auto *FD : RD->
fields()) {
5361 assert(RD->getNumBases() <= 1 &&
5362 "HLSL doesn't support multiple inheritance");
5363 return RD->getNumBases()
5368 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5369 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5381 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5386 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5392 if (
Decl->getType().hasAddressSpace())
5395 if (
Decl->getType()->isDependentType())
5407 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5421 llvm::Triple::Vulkan;
5422 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5423 if (HasDeclaredAPushConstant)
5429 HasDeclaredAPushConstant =
true;
5456class StructBindingContext {
5459 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5460 unsigned RegBindingOffset[4];
5463 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5464 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5465 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5466 static_cast<unsigned>(RegisterType::Sampler) == 3,
5467 "unexpected register type values");
5470 HLSLVkBindingAttr *VkBindingAttr;
5471 unsigned VkBindingOffset;
5476 StructBindingContext(
VarDecl *VD) {
5477 for (
unsigned i = 0; i < 4; ++i) {
5478 RegBindingsAttrs[i] =
nullptr;
5479 RegBindingOffset[i] = 0;
5481 VkBindingAttr =
nullptr;
5482 VkBindingOffset = 0;
5488 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5490 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5493 RegBindingsAttrs[RegTypeIdx] = RBA;
5498 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5499 VkBindingAttr = VBA;
5506 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5507 unsigned Range,
bool HasCounter) {
5508 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5510 if (VkBindingAttr) {
5511 unsigned Offset = VkBindingOffset;
5512 VkBindingOffset +=
Range;
5513 return HLSLVkBindingAttr::CreateImplicit(
5514 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5515 VkBindingAttr->getRange());
5518 HLSLResourceBindingAttr *RBA =
5519 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5520 HLSLResourceBindingAttr *NewAttr =
nullptr;
5522 if (RBA && RBA->hasRegisterSlot()) {
5525 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5526 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5528 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5529 StringRef NewSlotNumberStr =
5531 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5532 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5533 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5537 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5538 NewAttr->setBinding(RegType, std::nullopt,
5539 RBA ? RBA->getSpaceNumber() : 0);
5543 NewAttr->setImplicitCounterBindingOrderID(
5552static void createGlobalResourceDeclForStruct(
5554 QualType ResTy, StructBindingContext &BindingCtx) {
5556 "expected resource type or array of resources");
5567 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5568 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5573 const HLSLAttributedResourceType *ResHandleTy =
5574 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5578 Attr *BindingAttr = BindingCtx.createBindingAttr(
5580 ResDecl->
addAttr(BindingAttr);
5581 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5590 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5597static void handleArrayOfStructWithResources(
5599 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5604static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5606 EmbeddedResourceNameBuilder &NameBuilder,
5607 StructBindingContext &BindingCtx) {
5610 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5617 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5631 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5634 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5636 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5638 "resource arrays should have been already handled");
5639 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5648handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5650 EmbeddedResourceNameBuilder &NameBuilder,
5651 StructBindingContext &BindingCtx) {
5659 if (!SubCAT && !ElementRD)
5662 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5665 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5668 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5681void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5682 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5683 StructBindingContext BindingCtx(VD);
5687 "Expected non-resource struct or array type");
5690 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5694 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5695 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5703 if (
SemaRef.RequireCompleteType(
5706 diag::err_typecheck_decl_incomplete_type)) {
5720 DefaultCBufferDecls.push_back(VD);
5725 collectResourceBindingsOnVarDecl(VD);
5727 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5739 processExplicitBindingsOnDecl(VD);
5777 handleGlobalStructOrArrayOfWithResources(VD);
5781 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5790 "expected resource record type");
5806 const char *CreateMethodName;
5808 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5809 :
"__createFromBinding";
5811 CreateMethodName = HasCounter
5812 ?
"__createFromImplicitBindingWithImplicitCounter"
5813 :
"__createFromImplicitBinding";
5818 if (!CreateMethod) {
5823 "create method lookup should always succeed for built-in resource "
5832 Args.push_back(RegSlot);
5840 Args.push_back(OrderId);
5846 Args.push_back(Space);
5850 Args.push_back(RangeSize);
5854 Args.push_back(Index);
5856 StringRef VarName = VD->
getName();
5864 Args.push_back(NameCast);
5872 Args.push_back(CounterId);
5895 SemaRef.CheckCompleteVariableDeclaration(VD);
5901 "expected array of resource records");
5922 lookupMethod(
SemaRef, ResourceDecl,
5923 HasCounter ?
"__createFromBindingWithImplicitCounter"
5924 :
"__createFromBinding",
5928 CreateMethod = lookupMethod(
5930 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
5931 :
"__createFromImplicitBinding",
5974std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
5975 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
5976 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
5977 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
5978 if (!TrueInfo || !FalseInfo)
5979 return std::nullopt;
5980 if (*TrueInfo != *FalseInfo)
5981 return std::nullopt;
5985 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
5994 if (
const auto *AttrResType =
5995 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
5997 return Bindings.getDeclBindingInfo(VD, RC);
6004void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6005 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6008 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6013 if (*ExprBinding ==
nullptr)
6016 auto PrevBinding = Assigns.find(VD);
6017 if (PrevBinding == Assigns.end()) {
6019 Assigns.insert({VD, *ExprBinding});
6024 if (*ExprBinding != PrevBinding->second) {
6026 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6028 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6039 "expected LHS to be a resource record or array of resource records");
6040 if (Opc != BO_Assign)
6045 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6053 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6058 trackLocalResource(VD, RHSExpr);
6075void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6077 "expected global variable that contains HLSL resource");
6080 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6081 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6082 ? ResourceClass::CBuffer
6083 : ResourceClass::SRV);
6096 if (
const HLSLAttributedResourceType *AttrResType =
6097 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6098 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6103 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6104 collectResourceBindingsOnUserRecordDecl(VD, RT);
6110void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6113 bool HasBinding =
false;
6114 for (Attr *A : VD->
attrs()) {
6117 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6118 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6121 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6122 if (!RBA || !RBA->hasRegisterSlot())
6127 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6128 "never have an attribute created");
6130 if (RT == RegisterType::C) {
6131 if (Bindings.hasBindingInfoForDecl(VD))
6133 diag::warn_hlsl_user_defined_type_missing_member)
6134 <<
static_cast<int>(RT);
6142 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6147 diag::warn_hlsl_user_defined_type_missing_member)
6148 <<
static_cast<int>(RT);
6156class InitListTransformer {
6160 QualType *DstIt =
nullptr;
6161 Expr **ArgIt =
nullptr;
6167 bool castInitializer(Expr *E) {
6168 assert(DstIt &&
"This should always be something!");
6169 if (DstIt == DestTypes.end()) {
6171 ArgExprs.push_back(E);
6176 DstIt = DestTypes.begin();
6179 Ctx, *DstIt,
false);
6184 ArgExprs.push_back(
Init);
6189 bool buildInitializerListImpl(Expr *E) {
6191 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6192 for (
auto *SubInit :
Init->inits())
6193 if (!buildInitializerListImpl(SubInit))
6203 return castInitializer(E);
6217 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6222 for (uint64_t I = 0; I <
Size; ++I) {
6224 SizeTy, SourceLocation());
6230 if (!castInitializer(ElExpr.
get()))
6235 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6236 unsigned Rows = MTy->getNumRows();
6237 unsigned Cols = MTy->getNumColumns();
6238 QualType ElemTy = MTy->getElementType();
6240 for (
unsigned R = 0;
R < Rows; ++
R) {
6241 for (
unsigned C = 0;
C < Cols; ++
C) {
6254 if (!castInitializer(ElExpr.
get()))
6262 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6266 for (uint64_t I = 0; I <
Size; ++I) {
6268 SizeTy, SourceLocation());
6273 if (!buildInitializerListImpl(ElExpr.
get()))
6280 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6281 RecordDecls.push_back(RD);
6282 while (RecordDecls.back()->getNumBases()) {
6283 CXXRecordDecl *D = RecordDecls.back();
6285 "HLSL doesn't support multiple inheritance");
6286 RecordDecls.push_back(
6289 while (!RecordDecls.empty()) {
6290 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6291 for (
auto *FD : RD->
fields()) {
6292 if (FD->isUnnamedBitField())
6300 if (!buildInitializerListImpl(Res.
get()))
6308 Expr *generateInitListsImpl(QualType Ty) {
6310 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6315 llvm::SmallVector<Expr *>
Inits;
6320 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6321 ElTy = ATy->getElementType();
6322 Size = ATy->getNumElements();
6323 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6324 ElTy = CMTy->getElementType();
6325 Size = CMTy->getNumElementsFlattened();
6328 ElTy = VTy->getElementType();
6329 Size = VTy->getZExtSize();
6331 for (uint64_t I = 0; I <
Size; ++I)
6332 Inits.push_back(generateInitListsImpl(ElTy));
6335 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6336 RecordDecls.push_back(RD);
6337 while (RecordDecls.back()->getNumBases()) {
6338 CXXRecordDecl *D = RecordDecls.back();
6340 "HLSL doesn't support multiple inheritance");
6341 RecordDecls.push_back(
6344 while (!RecordDecls.empty()) {
6345 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6346 for (
auto *FD : RD->
fields())
6347 if (!FD->isUnnamedBitField())
6352 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6353 Inits.back()->getEndLoc(),
false);
6354 NewInit->setType(Ty);
6359 llvm::SmallVector<QualType, 16> DestTypes;
6360 llvm::SmallVector<Expr *, 16> ArgExprs;
6361 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6362 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6363 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6364 InitTy = Entity.
getType().getNonReferenceType();
6374 DstIt = DestTypes.begin();
6377 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6379 Expr *generateInitLists() {
6380 assert(!ArgExprs.empty() &&
6381 "Call buildInitializerList to generate argument expressions.");
6382 ArgIt = ArgExprs.begin();
6384 return generateInitListsImpl(InitTy);
6385 llvm::SmallVector<Expr *>
Inits;
6386 while (ArgIt != ArgExprs.end())
6387 Inits.push_back(generateInitListsImpl(InitTy));
6390 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6391 Inits.back()->getEndLoc(),
false);
6392 llvm::APInt ArySize(64,
Inits.size());
6394 ArraySizeModifier::Normal, 0));
6406 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6413 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6417 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6437 if (
Init->getType()->isScalarType())
6440 InitListTransformer ILT(
SemaRef, Entity);
6442 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6450 Init->setInit(I, E);
6452 if (!ILT.buildInitializerList(E))
6455 size_t ExpectedSize = ILT.DestTypes.size();
6456 size_t ActualSize = ILT.ArgExprs.size();
6457 if (ExpectedSize == 0 && ActualSize == 0)
6464 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6466 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6467 << (int)(ExpectedSize < ActualSize) << InitTy
6468 << ExpectedSize << ActualSize;
6478 assert(ExpectedSize > 0 &&
6479 "The expected size of an incomplete array type must be at least 1.");
6481 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6489 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6490 if (ExpectedSize != ActualSize) {
6491 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6492 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6493 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6500 Init->resizeInits(Ctx, NewInit->getNumInits());
6501 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6502 Init->updateInit(Ctx, I, NewInit->getInit(I));
6510 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6520 StringRef AccessorName = CompName->
getName();
6521 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6523 unsigned Rows = MT->getNumRows();
6524 unsigned Cols = MT->getNumColumns();
6525 bool IsZeroBasedAccessor =
false;
6526 unsigned ChunkLen = 0;
6527 if (AccessorName.size() < 2)
6529 "length 4 for zero based: \'_mRC\' or "
6530 "length 3 for one-based: \'_RC\' accessor",
6533 if (AccessorName[0] ==
'_') {
6534 if (AccessorName[1] ==
'm') {
6535 IsZeroBasedAccessor =
true;
6542 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6545 if (AccessorName.size() % ChunkLen != 0) {
6546 const llvm::StringRef
Expected = IsZeroBasedAccessor
6547 ?
"zero based: '_mRC' accessor"
6548 :
"one-based: '_RC' accessor";
6553 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6554 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6555 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6557 bool HasRepeated =
false;
6559 unsigned NumComponents = 0;
6560 const char *Begin = AccessorName.data();
6562 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6563 const char *Chunk = Begin + I;
6564 char RowChar = 0, ColChar = 0;
6565 if (IsZeroBasedAccessor) {
6567 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6568 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6570 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6577 if (Chunk[0] !=
'_')
6579 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6586 bool IsDigitsError =
false;
6588 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6592 IsDigitsError =
true;
6596 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6600 IsDigitsError =
true;
6605 unsigned Row = RowChar -
'0';
6606 unsigned Col = ColChar -
'0';
6608 bool HasIndexingError =
false;
6609 if (IsZeroBasedAccessor) {
6611 if (!isZeroBasedIndex(Row)) {
6612 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6614 HasIndexingError =
true;
6616 if (!isZeroBasedIndex(Col)) {
6617 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6619 HasIndexingError =
true;
6623 if (!isOneBasedIndex(Row)) {
6624 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6626 HasIndexingError =
true;
6628 if (!isOneBasedIndex(Col)) {
6629 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6631 HasIndexingError =
true;
6638 if (HasIndexingError)
6644 bool HasBoundsError =
false;
6646 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6648 HasBoundsError =
true;
6651 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6653 HasBoundsError =
true;
6658 unsigned FlatIndex = Row * Cols + Col;
6659 if (Seen[FlatIndex])
6661 Seen[FlatIndex] =
true;
6664 if (NumComponents == 0 || NumComponents > 4) {
6665 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6670 QualType ElemTy = MT->getElementType();
6671 if (NumComponents == 1)
6677 for (Sema::ExtVectorDeclsType::iterator
6681 if ((*I)->getUnderlyingType() == VT)
6692 trackLocalResource(VDecl,
Init);
6694 const HLSLVkConstantIdAttr *ConstIdAttr =
6695 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6702 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
6712 int ConstantID = ConstIdAttr->getId();
6713 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6715 ConstIdAttr->getLocation());
6719 if (
C->getType()->getCanonicalTypeUnqualified() !=
6723 Context.getTrivialTypeSourceInfo(
6724 Init->getType(),
Init->getExprLoc()),
6743 if (!Params || Params->
size() != 1)
6756 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6757 if (TTP->hasDefaultArgument()) {
6758 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6761 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6762 if (NTTP->hasDefaultArgument()) {
6763 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6766 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6767 if (TTPD->hasDefaultArgument()) {
6768 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6775 return SemaRef.CheckTemplateIdType(
6777 TemplateArgs,
nullptr,
false);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool containsIncompleteArrayType(QualType Ty)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static StringRef createRegisterString(ASTContext &AST, RegisterType RegType, unsigned N)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static QualType ReportMatrixInvalidMember(Sema &S, StringRef Name, StringRef Expected, SourceLocation OpLoc, SourceLocation CompLoc)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool CheckScalarFloatOperand(Sema &S, CallExpr *TheCall, unsigned ArgIndex)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckAnyScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool hasConstantBufferLayout(QualType QT)
llvm::dxbc::PSV::SemanticKind SemanticKind
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckIntegerElementTypeShaderModel(Sema &S, CallExpr *TheCall, QualType ContainedType, SampleKind Kind)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckCalculateLodBuiltin(Sema &S, CallExpr *TheCall)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckNoDoubleElementType(Sema &S, CallExpr *TheCall, QualType ContainedType, StringRef DefaultName)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static const Type * createHostLayoutType(Sema &S, const Type *Ty)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool CheckArgAddrSpaceOneOf(Sema *S, CallExpr *TheCall, unsigned ArgIndex, ArrayRef< LangAS > AllowedSpaces)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static StringRef getSampleMethodName(SampleKind Kind)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall)
static RegisterType getRegisterType(ResourceClass RC)
static bool ValidateRegisterNumber(uint64_t SlotNum, Decl *TheDecl, ASTContext &Ctx, RegisterType RegTy)
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static char getRegisterTypeChar(RegisterType RT)
static bool CheckNotBoolScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool isMatrixOrArrayOfMatrix(const ASTContext &Ctx, QualType QT)
static QualType getTypedResourceElementType(QualType ContainedType)
static bool findExistingMatrixLayoutMarker(QualType T, attr::Kind &ExistingKind)
Walks the existing AttributedType sugar of T looking for a previously applied HLSLRowMajor/HLSLColumn...
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckWavePrefix(Sema *S, CallExpr *TheCall)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static LangAS getLangASFromResourceClass(ResourceClass RC)
static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall, bool IncludeArraySlice=true)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static const Type * getHostLayoutFieldType(QualType QT)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static QualType getVectorOrScalarType(Sema &S, QualType BaseType, unsigned Count)
static bool isLayoutAdaptingMatrixBuiltin(unsigned BuiltinID)
static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind)
static bool CheckScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckFloatRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyDoubleRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
static StringRef getCurrentResourceMethodName(Sema &S, StringRef DefaultName)
static bool IsDefaultBufferConstantDecl(const ASTContext &Ctx, VarDecl *VD)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool CheckGatherBuiltin(Sema &S, CallExpr *TheCall, bool IsCmp)
static bool isValidWaveSizeValue(unsigned Value)
static bool isResourceRecordTypeOrArrayOf(QualType Ty)
static bool CheckLoadMSBuiltin(Sema &S, CallExpr *TheCall)
static bool AccumulateHLSLResourceSlots(QualType Ty, uint64_t &StartSlot, const uint64_t &Limit, const ResourceClass ResClass, ASTContext &Ctx, uint64_t ArrayCount=1)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
llvm::StringRef backupStr(llvm::StringRef S) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns) const
Return the unique reference to the matrix type of the specified element type and size.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getLocation() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
base_class_iterator bases_end()
void completeDefinition() override
Indicates that the definition of this class is now complete.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
bool isHLSLBuiltinRecord() const
Returns true if the class is a built-in HLSL record.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceLocation getEndLoc() const
static CanQual< Type > CreateUnsafe(QualType Other)
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
llvm::APInt getSize() const
Return the constant array size as an APInt.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
attr_iterator attr_end() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
attr_iterator attr_begin() const
DeclContext * getNonTransparentDeclContext()
Return the non transparent context.
SourceLocation getLocation() const
void setImplicit(bool I=true)
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
Represents a ValueDecl that came out of a declarator.
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
ExtVectorType - Extended vector type.
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
DeclarationNameInfo getNameInfo() const
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
void addLayoutStruct(CXXRecordDecl *LS)
void setHasValidPackoffset(bool PO)
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
buffer_decl_range buffer_decls() const
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
iterator begin(ExternalSemaSource *source, bool LocalOnly=false)
Represents the results of name lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Represents a matrix type, as defined in the Matrix Types clang extensions.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
NamedDecl * getUnderlyingDecl()
Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
A C++ nested-name-specifier augmented with source location information.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
bool hasParsedType() const
void setInvalid(bool b=true) const
const ParsedType & getTypeArg() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
AttributeCommonInfo::Kind getKind() const
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinitionOrSelf() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
ASTContext & getASTContext() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
void handleVkLocationAttr(Decl *D, const ParsedAttr &AL)
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
void handleSemanticAttr(Decl *D, const ParsedAttr &AL)
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
uint32_t getNextImplicitBindingOrderID()
void CheckEntryPoint(FunctionDecl *FD)
void handleVkExtBuiltinOutputAttr(Decl *D, const ParsedAttr &AL)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
void propagateContextualMatrixLayout(Expr *E, QualType DestType)
T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)
bool initGlobalResourceDecl(VarDecl *VD)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
bool initGlobalResourceArrayDecl(VarDecl *VD)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
Attr * buildMatrixLayoutTypeAttr(QualType T, const ParsedAttr &AL)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool diagnoseIndexType(QualType T, const ParsedAttr &AL)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool ActOnResourceMemberAccessExpr(MemberExpr *ME)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
QualType ActOnTemplateShorthand(TemplateDecl *Template, SourceLocation NameLoc)
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
QualType checkMatrixComponent(Sema &S, QualType baseType, ExprValueKind &VK, SourceLocation OpLoc, const IdentifierInfo *CompName, SourceLocation CompLoc)
bool IsConstantBufferElementCompatible(QualType T1)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
bool ActOnUninitializedVarDecl(VarDecl *D)
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
bool canHaveOverloadedBinOp(QualType Ty, BinaryOperatorKind Opc)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
void handleVkPushConstantAttr(Decl *D, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
NamedDecl * getConstantBufferConversionFunction(QualType Type, CXXRecordDecl *RD)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional< unsigned > Index)
QualType getInoutParameterType(QualType Ty)
bool diagnoseFloatType(QualType T, const ParsedAttr &AL)
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
std::optional< ExprResult > tryPerformConstantBufferConversion(Expr *BaseExpr)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
bool diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T, SourceLocation Loc)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
ExtVectorDeclsType ExtVectorDecls
ExtVectorDecls - This is a list all the extended vector types.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult TemporaryMaterializationConversion(Expr *E)
If E is a prvalue denoting an unmaterialized temporary, materialize it as an xvalue.
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExternalSemaSource * getExternalSource() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
void pushBaseName(llvm::StringRef N)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
Defines the clang::TargetInfo interface.
uint32_t getResourceDimensions(llvm::dxil::ResourceDimension Dim)
bool hasResourceOffset(llvm::dxil::ResourceDimension Dim)
bool hasCounterHandle(const CXXRecordDecl *RD)
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
@ Template
We are parsing a template declaration.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr, Expr *SampleCountExpr=nullptr)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
__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