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"
58using llvm::hlsl::InterpolationModifier;
59using llvm::hlsl::IOType;
60using llvm::hlsl::SemanticStageInfo;
69 return VT->getElementType();
71 return MT->getElementType();
77 case ResourceClass::SRV:
78 return RegisterType::SRV;
79 case ResourceClass::UAV:
80 return RegisterType::UAV;
81 case ResourceClass::CBuffer:
82 return RegisterType::CBuffer;
83 case ResourceClass::Sampler:
84 return RegisterType::Sampler;
86 llvm_unreachable(
"unexpected ResourceClass value");
95 case ResourceClass::SRV:
96 case ResourceClass::UAV:
98 case ResourceClass::CBuffer:
100 case ResourceClass::Sampler:
103 llvm_unreachable(
"unexpected ResourceClass value");
109 assert(RT !=
nullptr);
113 *RT = RegisterType::SRV;
117 *RT = RegisterType::UAV;
121 *RT = RegisterType::CBuffer;
125 *RT = RegisterType::Sampler;
129 *RT = RegisterType::C;
133 *RT = RegisterType::I;
142 case RegisterType::SRV:
144 case RegisterType::UAV:
146 case RegisterType::CBuffer:
148 case RegisterType::Sampler:
150 case RegisterType::C:
152 case RegisterType::I:
155 llvm_unreachable(
"unexpected RegisterType value");
160 case RegisterType::SRV:
161 return ResourceClass::SRV;
162 case RegisterType::UAV:
163 return ResourceClass::UAV;
164 case RegisterType::CBuffer:
165 return ResourceClass::CBuffer;
166 case RegisterType::Sampler:
167 return ResourceClass::Sampler;
168 case RegisterType::C:
169 case RegisterType::I:
173 llvm_unreachable(
"unexpected RegisterType value");
177 const auto *BT = dyn_cast<BuiltinType>(
Type);
181 return Builtin::BI__builtin_get_spirv_spec_constant_int;
184 switch (BT->getKind()) {
185 case BuiltinType::Bool:
186 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
187 case BuiltinType::Short:
188 return Builtin::BI__builtin_get_spirv_spec_constant_short;
189 case BuiltinType::Int:
190 return Builtin::BI__builtin_get_spirv_spec_constant_int;
191 case BuiltinType::LongLong:
192 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
193 case BuiltinType::UShort:
194 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
195 case BuiltinType::UInt:
196 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
197 case BuiltinType::ULongLong:
198 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
199 case BuiltinType::Half:
200 return Builtin::BI__builtin_get_spirv_spec_constant_half;
201 case BuiltinType::Float:
202 return Builtin::BI__builtin_get_spirv_spec_constant_float;
203 case BuiltinType::Double:
204 return Builtin::BI__builtin_get_spirv_spec_constant_double;
213 llvm::raw_svector_ostream OS(Buffer);
220 ResourceClass ResClass) {
222 "DeclBindingInfo already added");
228 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
229 return &BindingsList.emplace_back(VD, ResClass);
233 ResourceClass ResClass) {
234 auto Entry = DeclToBindingListIndex.find(VD);
235 if (Entry != DeclToBindingListIndex.end()) {
236 for (
unsigned Index = Entry->getSecond();
237 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
239 if (BindingsList[Index].ResClass == ResClass)
240 return &BindingsList[Index];
247 return DeclToBindingListIndex.contains(VD);
259 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
262 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
263 : llvm::hlsl::ResourceClass::SRV;
275 if (
T->isArrayType() ||
T->isStructureType() ||
T->isConstantMatrixType())
282 assert(Context.getTypeSize(
T) <= 64 &&
283 "Scalar bit widths larger than 64 not supported");
286 return Context.getTypeSize(
T) / 8;
293 constexpr unsigned CBufferAlign = 16;
294 if (
const auto *RD =
T->getAsRecordDecl()) {
296 for (
const FieldDecl *Field : RD->fields()) {
303 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
304 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
305 FieldAlign = CBufferAlign;
308 Size = llvm::alignTo(Size, FieldAlign);
315 unsigned ElementCount = AT->getSize().getZExtValue();
316 if (ElementCount == 0)
319 unsigned ElementSize =
321 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
322 return AlignedElementSize * (ElementCount - 1) + ElementSize;
326 unsigned ElementCount = VT->getNumElements();
327 unsigned ElementSize =
329 return ElementSize * ElementCount;
332 return Context.getTypeSize(
T) / 8;
343 bool HasPackOffset =
false;
344 bool HasNonPackOffset =
false;
346 VarDecl *Var = dyn_cast<VarDecl>(Field);
349 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
350 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
351 HasPackOffset =
true;
353 HasNonPackOffset =
true;
360 if (HasNonPackOffset)
367 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
368 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
369 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
370 return LHS.second->getOffsetInBytes() <
371 RHS.second->getOffsetInBytes();
373 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
374 VarDecl *Var = PackOffsetVec[i].first;
375 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
377 unsigned Begin =
Attr->getOffsetInBytes();
378 unsigned End = Begin + Size;
379 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
380 if (End > NextBegin) {
381 VarDecl *NextVar = PackOffsetVec[i + 1].first;
393 CAT = dyn_cast<ConstantArrayType>(
395 return CAT !=
nullptr;
406static const HLSLAttributedResourceType *
409 "expected array of resource records");
411 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
413 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
416static const HLSLAttributedResourceType *
430 return RD->isEmpty();
459 Base.getType()->castAsCXXRecordDecl()))
470 assert(RD ==
nullptr &&
471 "there should be at most 1 record by a given name in a scope");
488 Name.append(NameBaseII->
getName());
495 size_t NameLength = Name.size();
504 Name.append(llvm::Twine(suffix).str());
505 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
512 Name.truncate(NameLength);
527 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
529 S, CAT->getElementType()->getUnqualifiedDesugaredType());
534 CAT->getSizeModifier(),
535 CAT->getIndexTypeCVRQualifiers())
584 "struct is already HLSL buffer compatible");
598 LS->
addAttr(PackedAttr::CreateImplicit(AST));
602 if (
unsigned NumBases = StructDecl->
getNumBases()) {
603 assert(NumBases == 1 &&
"HLSL supports only one base type");
653 LS->
addAttr(PackedAttr::CreateImplicit(AST));
658 VarDecl *VD = dyn_cast<VarDecl>(D);
674 "host layout field for $Globals decl failed to be created");
693 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
694 Attr->setBinding(RT, std::nullopt, 0);
695 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
702 BufDecl->setRBraceLoc(RBrace);
719 BufDecl->isCBuffer() ? RegisterType::CBuffer
729 int X,
int Y,
int Z) {
730 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
731 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
732 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
733 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
743 int Min,
int Max,
int Preferred,
744 int SpelledArgsCount) {
745 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
746 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
747 WS->getPreferred() != Preferred ||
748 WS->getSpelledArgsCount() != SpelledArgsCount) {
749 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
750 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
756 Result->setSpelledArgsCount(SpelledArgsCount);
760HLSLVkConstantIdAttr *
766 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
774 Diag(VD->getLocation(), diag::err_specialization_const);
778 if (!VD->getType().isConstQualified()) {
779 Diag(VD->getLocation(), diag::err_specialization_const);
783 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
784 if (CI->getId() != Id) {
785 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
786 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
791 HLSLVkConstantIdAttr *
Result =
798 llvm::Triple::EnvironmentType ShaderType) {
799 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
800 if (NT->getType() != ShaderType) {
801 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
802 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
806 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
809HLSLParamModifierAttr *
811 HLSLParamModifierAttr::Spelling Spelling) {
814 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
815 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
816 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
817 D->
dropAttr<HLSLParamModifierAttr>();
819 return HLSLParamModifierAttr::Create(
821 HLSLParamModifierAttr::Keyword_inout);
823 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
824 Diag(PA->getLocation(), diag::note_conflicting_attribute);
831 InterpolationModifier Modifier;
832 switch (
static_cast<HLSLInterpolationModifierAttr::Spelling
>(
834 case HLSLInterpolationModifierAttr::Keyword_nointerpolation:
835 Modifier = InterpolationModifier::NoInterpolation;
837 case HLSLInterpolationModifierAttr::Keyword_linear:
838 Modifier = InterpolationModifier::Linear;
840 case HLSLInterpolationModifierAttr::Keyword_centroid:
841 Modifier = InterpolationModifier::Centroid;
843 case HLSLInterpolationModifierAttr::Keyword_noperspective:
844 Modifier = InterpolationModifier::NoPerspective;
846 case HLSLInterpolationModifierAttr::Keyword_sample:
847 Modifier = InterpolationModifier::Sample;
849 case HLSLInterpolationModifierAttr::Keyword_center:
850 Modifier = InterpolationModifier::Center;
852 case HLSLInterpolationModifierAttr::SpellingNotCalculated:
853 llvm_unreachable(
"interpolation modifier spelling was not calculated");
856 InterpolationModifier Modifiers = Modifier;
858 auto Old =
static_cast<InterpolationModifier
>(
Previous->getModifiers());
860 if (
any(Old & Modifier)) {
861 Diag(AL.
getLoc(), diag::warn_hlsl_duplicate_interpolation) << AL;
862 }
else if (llvm::hlsl::getInterpolationMode(Modifiers) ==
863 llvm::dxbc::PSV::InterpolationMode::Invalid &&
864 llvm::hlsl::getInterpolationMode(Old) !=
865 llvm::dxbc::PSV::InterpolationMode::Invalid) {
866 Diag(AL.
getLoc(), diag::err_hlsl_interpolation_conflict);
867 Diag(
Previous->getLocation(), diag::note_conflicting_attribute);
870 InterpolationModifier OldLocation =
871 llvm::hlsl::getInterpolationSamplingLocation(Old);
872 InterpolationModifier NewLocation =
873 llvm::hlsl::getInterpolationSamplingLocation(Modifier);
874 if (
any(OldLocation) &&
any(NewLocation)) {
875 Diag(AL.
getLoc(), diag::warn_hlsl_interpolation_override)
876 << (std::max(OldLocation, NewLocation) ==
877 InterpolationModifier::Sample)
878 << (std::min(OldLocation, NewLocation) ==
879 InterpolationModifier::Centroid);
882 D->
dropAttr<HLSLInterpolationModifierAttr>();
884 D->
addAttr(HLSLInterpolationModifierAttr::Create(
888bool SemaHLSL::checkInterpolationModifiers(
889 const DeclaratorDecl *D,
const HLSLInterpolationModifierAttr *Inherited,
890 const HLSLParsedSemanticAttr *Semantic) {
893 const auto *A = D->
getAttr<HLSLInterpolationModifierAttr>();
897 Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
899 const auto *FD = dyn_cast<FunctionDecl>(D);
902 if (
T->isDependentType())
904 if (
const auto *RT =
T->getAs<RecordType>()) {
910 Valid &= checkInterpolationModifiers(Field, A, Semantic);
916 auto Modifiers =
static_cast<InterpolationModifier
>(A->getModifiers());
917 if (Modifiers == InterpolationModifier::NoInterpolation) {
919 Semantic && llvm::hlsl::getSemanticKind(Semantic->getSemanticName()) ==
920 SemanticKind::Position;
923 Diag(A->getLocation(), diag::err_hlsl_interpolation_position);
924 Diag(Semantic->getLocation(), diag::note_conflicting_attribute);
931 Diag(A->getLocation(), diag::err_hlsl_interpolation_type) <<
T;
957 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
958 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
961 if (Shader->getType() != Env) {
962 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
974 case llvm::Triple::UnknownEnvironment:
975 case llvm::Triple::Library:
977 case llvm::Triple::RootSignature:
978 llvm_unreachable(
"rootsig environment has no functions");
980 llvm_unreachable(
"Unhandled environment in triple");
986 HLSLAppliedSemanticAttr *Semantic,
991 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
992 assert(ShaderAttr &&
"Entry point has no shader attribute");
993 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
994 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
997 case SemanticKind::Position:
1001 return (ST == llvm::Triple::Vertex && !IsInput) ||
1002 (ST == llvm::Triple::Pixel && IsInput);
1003 case SemanticKind::VertexID:
1005 case SemanticKind::InstanceID:
1006 return ST == llvm::Triple::Vertex && IsInput;
1012bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1015 SemanticInfo &ActiveSemantic,
1016 SemaHLSL::SemanticContext &SC) {
1017 if (ActiveSemantic.Semantic ==
nullptr) {
1018 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1019 if (ActiveSemantic.Semantic)
1020 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1023 if (!ActiveSemantic.Semantic) {
1029 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1030 ActiveSemantic.Semantic->getAttrName()->getName(),
1031 ActiveSemantic.Index.value_or(0));
1035 checkSemanticAnnotation(FD, D, A, SC);
1036 OutputDecl->addAttr(A);
1038 unsigned Location = ActiveSemantic.Index.value_or(0);
1041 any(SC.CurrentIOType & IOType::In))) {
1042 bool HasVkLocation =
false;
1043 if (
auto *A = D->getAttr<HLSLVkLocationAttr>()) {
1044 HasVkLocation = true;
1045 Location = A->getLocation();
1048 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1049 Diag(D->getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1052 SC.UsesExplicitVkLocations = HasVkLocation;
1055 const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->getType());
1056 unsigned ElementCount = AT ? AT->
getZExtSize() : 1;
1057 ActiveSemantic.Index = Location + ElementCount;
1059 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
1060 for (
unsigned I = 0; I < ElementCount; ++I) {
1061 Twine VariableName = BaseName.concat(Twine(Location + I));
1063 auto [_, Inserted] = SC.ActiveSemantics.insert(VariableName.str());
1065 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
1066 << VariableName.str();
1074bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1077 SemanticInfo &ActiveSemantic,
1078 SemaHLSL::SemanticContext &SC) {
1079 if (ActiveSemantic.Semantic ==
nullptr) {
1080 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1081 if (ActiveSemantic.Semantic)
1082 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1088 const RecordType *RT = dyn_cast<RecordType>(
T);
1090 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1093 const RecordDecl *RD = RT->getDecl();
1094 for (FieldDecl *Field : RD->
fields()) {
1095 SemanticInfo Info = ActiveSemantic;
1096 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1097 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1100 if (ActiveSemantic.Semantic)
1101 ActiveSemantic = Info;
1108 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1109 assert(ShaderAttr &&
"Entry point has no shader attribute");
1110 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1114 case llvm::Triple::Pixel:
1115 case llvm::Triple::Vertex:
1116 case llvm::Triple::Geometry:
1117 case llvm::Triple::Hull:
1118 case llvm::Triple::Domain:
1119 case llvm::Triple::RayGeneration:
1120 case llvm::Triple::Intersection:
1121 case llvm::Triple::AnyHit:
1122 case llvm::Triple::ClosestHit:
1123 case llvm::Triple::Miss:
1124 case llvm::Triple::Callable:
1125 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1126 diagnoseAttrStageMismatch(NT, ST,
1127 {llvm::Triple::Compute,
1128 llvm::Triple::Amplification,
1129 llvm::Triple::Mesh});
1132 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1133 diagnoseAttrStageMismatch(WS, ST,
1134 {llvm::Triple::Compute,
1135 llvm::Triple::Amplification,
1136 llvm::Triple::Mesh});
1141 case llvm::Triple::Compute:
1142 case llvm::Triple::Amplification:
1143 case llvm::Triple::Mesh:
1144 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1146 << llvm::Triple::getEnvironmentTypeName(ST);
1149 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1151 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1152 }
else if (Ver < VersionTuple(6, 6)) {
1153 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1156 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1159 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1160 << WS << WS->getSpelledArgsCount() <<
"6.8";
1165 case llvm::Triple::RootSignature:
1166 llvm_unreachable(
"rootsig environment has no function entry point");
1168 llvm_unreachable(
"Unhandled environment in triple");
1171 SemaHLSL::SemanticContext InputSC = {};
1172 InputSC.CurrentIOType = IOType::In;
1173 SemaHLSL::SemanticContext OutputSC = {};
1174 OutputSC.CurrentIOType = IOType::Out;
1177 SemanticInfo ActiveSemantic;
1178 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1179 if (ActiveSemantic.Semantic)
1180 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1184 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1185 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1189 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1190 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1191 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1194 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1195 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1200 SemanticInfo ActiveSemantic;
1201 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1202 if (ActiveSemantic.Semantic)
1203 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1205 if (ST == llvm::Triple::Vertex &&
1206 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1208 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1212void SemaHLSL::checkSemanticAnnotation(
1214 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC) {
1215 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1216 assert(ShaderAttr &&
"Entry point has no shader attribute");
1217 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1220 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1221 llvm::hlsl::SemanticInterpretation Interpretation =
1222 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1223 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
1224 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1227 case SemanticKind::DispatchThreadID:
1228 case SemanticKind::GroupID:
1229 case SemanticKind::GroupIndex:
1230 case SemanticKind::GroupThreadID:
1231 case SemanticKind::InstanceID:
1232 if (SemanticAttr->getSemanticIndex() != 0) {
1233 std::string PrettyName =
1234 "'" + SemanticAttr->getSemanticName().str() +
"'";
1235 Diag(SemanticAttr->getLoc(),
1236 diag::err_hlsl_semantic_indexing_not_supported)
1245void SemaHLSL::diagnoseAttrStageMismatch(
1246 const Attr *A, llvm::Triple::EnvironmentType Stage,
1247 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1248 SmallVector<StringRef, 8> StageStrings;
1249 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1250 [](llvm::Triple::EnvironmentType ST) {
1252 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1254 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1255 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1256 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1259void SemaHLSL::diagnoseSemanticStageMismatch(
1260 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1263 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1264 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1265 return Info.Stage == Stage;
1268 StringRef CurrentIOTypeName =
"patch constants or primitives";
1269 if (
any(CurrentIOType & IOType::In))
1270 CurrentIOTypeName =
"inputs";
1271 else if (
any(CurrentIOType & IOType::Out))
1272 CurrentIOTypeName =
"outputs";
1275 if (It == Allowed.end()) {
1276 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1277 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1278 << CurrentIOTypeName;
1282 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1283 if (!(AllowedIOTypes & CurrentIOType)) {
1284 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1285 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1286 << CurrentIOTypeName;
1291template <CastKind Kind>
1294 Ty = VTy->getElementType();
1299template <CastKind Kind>
1311 if (LHSFloat && RHSFloat) {
1339 if (LHSSigned == RHSSigned) {
1340 if (IsCompAssign || IntOrder >= 0)
1348 if (IntOrder != (LHSSigned ? 1 : -1)) {
1349 if (IsCompAssign || RHSSigned)
1357 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1358 if (IsCompAssign || LHSSigned)
1374 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1375 QualType NewTy = Ctx.getExtVectorType(
1385 return CK_FloatingCast;
1387 return CK_IntegralCast;
1389 return CK_IntegralToFloating;
1391 return CK_FloatingToIntegral;
1397 bool IsCompAssign) {
1404 if (!LVecTy && IsCompAssign) {
1406 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1408 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1410 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1415 unsigned EndSz = std::numeric_limits<unsigned>::max();
1418 LSz = EndSz = LVecTy->getNumElements();
1421 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1422 "one of the above should have had a value");
1426 if (IsCompAssign && LSz != EndSz) {
1428 diag::err_hlsl_vector_compound_assignment_truncation)
1429 << LHSType << RHSType;
1435 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1440 if (!IsCompAssign && !LVecTy)
1444 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1445 return Ctx.getCommonSugaredType(LHSType, RHSType);
1453 LElTy, RElTy, IsCompAssign);
1456 "HLSL Vectors can only contain integer or floating point types");
1458 LElTy, RElTy, IsCompAssign);
1463 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1464 "Called with non-logical operator");
1466 llvm::raw_svector_ostream OS(Buff);
1468 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1469 OS << NewFnName <<
"(";
1479std::pair<IdentifierInfo *, bool>
1482 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1489 return {DeclIdent,
Found};
1500 for (
auto &RootSigElement : RootElements)
1501 Elements.push_back(RootSigElement.getElement());
1505 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1507 SignatureDecl->setImplicit();
1513 if (RootSigOverrideIdent) {
1516 if (
SemaRef.LookupQualifiedName(R, DC))
1517 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1525struct PerVisibilityBindingChecker {
1528 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1532 llvm::dxbc::ShaderVisibility Vis;
1537 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1539 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1540 llvm::dxil::ResourceClass RC,
uint32_t Space,
1542 const hlsl::RootSignatureElement *Elem) {
1544 assert(BuilderIndex < Builders.size() &&
1545 "Not enough builders for visibility type");
1546 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1547 static_cast<const void *
>(Elem));
1549 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1550 "'All' visibility must come first");
1551 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1552 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1553 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1554 static_cast<const void *
>(Elem));
1556 ElemInfoMap.push_back({Elem,
Visibility,
false});
1559 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1560 auto It = llvm::lower_bound(
1562 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1563 assert(It->Elem == Elem &&
"Element not in map");
1567 bool checkOverlap() {
1568 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1569 return LHS.Elem < RHS.Elem;
1572 bool HadOverlap =
false;
1574 using llvm::hlsl::BindingInfoBuilder;
1575 auto ReportOverlap = [
this,
1576 &HadOverlap](
const BindingInfoBuilder &Builder,
1577 const llvm::hlsl::Binding &Reported) {
1581 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1582 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1583 const auto *PrevElem =
1584 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1586 ElemInfo &Info =
getInfo(Elem);
1591 Info.Diagnosed =
true;
1593 ElemInfo &PrevInfo =
getInfo(PrevElem);
1594 llvm::dxbc::ShaderVisibility CommonVis =
1595 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1598 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1599 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1600 << Reported.isUnbounded() << Reported.UpperBound
1605 this->S->
Diag(PrevElem->getLocation(),
1606 diag::note_hlsl_resource_range_here);
1609 for (BindingInfoBuilder &Builder : Builders)
1610 Builder.calculateBindingInfo(ReportOverlap);
1630 bool HadError =
false;
1631 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1632 uint32_t UpperBound) {
1634 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1635 << LowerBound << UpperBound;
1642 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1643 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1644 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1647 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1648 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1649 ReportError(Loc, 0, 0xfffffffe);
1652 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1653 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1654 ReportError(Loc, 0, 0xffffffef);
1657 const uint32_t Version =
1658 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1659 const uint32_t VersionEnum = Version - 1;
1660 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1662 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1669 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1670 if (
const auto *Descriptor =
1671 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1672 VerifyRegister(Loc, Descriptor->Reg.Number);
1673 VerifySpace(Loc, Descriptor->Space);
1675 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1677 ReportFlagError(Loc);
1678 }
else if (
const auto *Constants =
1679 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1680 VerifyRegister(Loc, Constants->Reg.Number);
1681 VerifySpace(Loc, Constants->Space);
1682 }
else if (
const auto *Sampler =
1683 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1684 VerifyRegister(Loc, Sampler->Reg.Number);
1685 VerifySpace(Loc, Sampler->Space);
1688 "By construction, parseFloatParam can't produce a NaN from a "
1689 "float_literal token");
1691 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1692 ReportError(Loc, 0, 16);
1693 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1694 ReportFloatError(Loc, -16.f, 15.99f);
1695 }
else if (
const auto *Clause =
1696 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1698 VerifyRegister(Loc, Clause->Reg.Number);
1699 VerifySpace(Loc, Clause->Space);
1701 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1705 ReportError(Loc, 1, 0xfffffffe);
1708 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1710 ReportFlagError(Loc);
1714 PerVisibilityBindingChecker BindingChecker(
this);
1715 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1720 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1721 if (
const auto *Descriptor =
1722 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1723 uint32_t LowerBound(Descriptor->Reg.Number);
1724 uint32_t UpperBound(LowerBound);
1726 BindingChecker.trackBinding(
1727 Descriptor->Visibility,
1728 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1729 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1730 }
else if (
const auto *Constants =
1731 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1732 uint32_t LowerBound(Constants->Reg.Number);
1733 uint32_t UpperBound(LowerBound);
1735 BindingChecker.trackBinding(
1736 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1737 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1738 }
else if (
const auto *Sampler =
1739 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1740 uint32_t LowerBound(Sampler->Reg.Number);
1741 uint32_t UpperBound(LowerBound);
1743 BindingChecker.trackBinding(
1744 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1745 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1746 }
else if (
const auto *Clause =
1747 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1750 UnboundClauses.emplace_back(Clause, &RootSigElem);
1751 }
else if (
const auto *Table =
1752 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1753 assert(UnboundClauses.size() == Table->NumClauses &&
1754 "Number of unbound elements must match the number of clauses");
1755 bool HasAnySampler =
false;
1756 bool HasAnyNonSampler =
false;
1757 uint64_t Offset = 0;
1758 bool IsPrevUnbound =
false;
1759 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1761 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1762 HasAnySampler =
true;
1764 HasAnyNonSampler =
true;
1766 if (HasAnySampler && HasAnyNonSampler)
1767 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1772 if (Clause->NumDescriptors == 0)
1776 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1778 Offset = Clause->Offset;
1780 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1781 Offset, Clause->NumDescriptors);
1783 if (IsPrevUnbound && IsAppending)
1784 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1785 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1786 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1789 Offset = RangeBound + 1;
1790 IsPrevUnbound = Clause->NumDescriptors ==
1791 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1794 uint32_t LowerBound(Clause->Reg.Number);
1795 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1796 LowerBound, Clause->NumDescriptors);
1798 BindingChecker.trackBinding(
1800 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1801 LowerBound, UpperBound, ClauseElem);
1803 UnboundClauses.clear();
1807 return BindingChecker.checkOverlap();
1812 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1817 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1818 if (RS->getSignatureIdent() != Ident) {
1819 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1823 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1829 if (
auto *SignatureDecl =
1830 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1837 llvm::VersionTuple SMVersion =
1842 uint32_t ZMax = 1024;
1843 uint32_t ThreadMax = 1024;
1844 if (IsDXIL && SMVersion.getMajor() <= 4) {
1847 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1857 diag::err_hlsl_numthreads_argument_oor)
1866 diag::err_hlsl_numthreads_argument_oor)
1875 diag::err_hlsl_numthreads_argument_oor)
1880 if (
X * Y * Z > ThreadMax) {
1881 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1898 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1906 if (SpelledArgsCount > 1 &&
1910 uint32_t Preferred = 0;
1911 if (SpelledArgsCount > 2 &&
1915 if (SpelledArgsCount > 2) {
1918 diag::err_attribute_power_of_two_in_range)
1919 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1924 if (Preferred < Min || Preferred >
Max) {
1926 diag::err_attribute_power_of_two_in_range)
1927 << AL <<
Min <<
Max << Preferred;
1930 }
else if (SpelledArgsCount > 1) {
1933 diag::err_attribute_power_of_two_in_range)
1934 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1938 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1941 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1946 diag::err_attribute_power_of_two_in_range)
1947 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1952 HLSLWaveSizeAttr *NewAttr =
1989 uint32_t Binding = 0;
2013 if (!
T->hasUnsignedIntegerRepresentation() ||
2014 (VT && VT->getNumElements() > 3)) {
2015 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
2016 << AL <<
"uint/uint2/uint3";
2025 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
2026 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
2027 << AL <<
"float/float1/float2/float3/float4";
2036 std::optional<unsigned> Index) {
2038 QualType ValueType = VD->getType();
2039 if (
auto *FD = dyn_cast<FunctionDecl>(D))
2043 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>())
2048 case SemanticKind::DispatchThreadID:
2049 case SemanticKind::GroupThreadID:
2050 case SemanticKind::GroupID:
2053 case SemanticKind::GroupIndex:
2055 case SemanticKind::Position:
2056 case SemanticKind::Target:
2059 case SemanticKind::VertexID: {
2060 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
2061 if (!ValueType->isUnsignedIntegerType() || SizeInBits != 32)
2062 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
2065 case SemanticKind::InstanceID: {
2066 uint64_t SizeInBits =
SemaRef.Context.getTypeSize(ValueType);
2070 if (!ValueType->isUnsignedIntegerType() ||
2071 !(SizeInBits == 32 || (!IsSPIRV && SizeInBits == 16)))
2072 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type) << AL <<
"uint";
2076 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2084 uint32_t IndexValue(0), ExplicitIndex(0);
2087 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2089 assert(IndexValue > 0 ? ExplicitIndex :
true);
2090 std::optional<unsigned> Index =
2091 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
2094 if (Kind == SemanticKind::Arbitrary)
2102 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2103 << AL <<
"shader constant in a constant buffer";
2107 uint32_t SubComponent;
2117 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2122 if (IsAggregateTy) {
2123 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2127 if ((Component * 32 + Size) > 128) {
2128 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2133 EltTy = VT->getElementType();
2135 if (Align > 32 && Component == 1) {
2138 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2152 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2155 llvm::Triple::EnvironmentType ShaderType;
2156 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2157 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2158 << AL << Str << ArgLoc;
2172 Expr *SampleCountExpr) {
2173 assert(AttrList.size() &&
"expected list of resource attributes");
2180 HLSLAttributedResourceType::Attributes ResAttrs;
2182 bool HasResourceClass =
false;
2183 bool HasResourceDimension =
false;
2184 for (
const Attr *A : AttrList) {
2189 case attr::HLSLResourceClass: {
2191 if (HasResourceClass) {
2193 ? diag::warn_duplicate_attribute_exact
2194 : diag::warn_duplicate_attribute)
2198 ResAttrs.ResourceClass = RC;
2199 HasResourceClass =
true;
2202 case attr::HLSLResourceDimension: {
2203 llvm::dxil::ResourceDimension RD =
2205 if (HasResourceDimension) {
2207 ? diag::warn_duplicate_attribute_exact
2208 : diag::warn_duplicate_attribute)
2212 ResAttrs.ResourceDimension = RD;
2213 HasResourceDimension =
true;
2216 case attr::HLSLIsROV:
2217 if (ResAttrs.IsROV) {
2221 ResAttrs.IsROV =
true;
2223 case attr::HLSLRawBuffer:
2224 if (ResAttrs.RawBuffer) {
2228 ResAttrs.RawBuffer =
true;
2230 case attr::HLSLIsArray:
2231 if (ResAttrs.IsArray) {
2235 ResAttrs.IsArray =
true;
2237 case attr::HLSLIsMultiSampled:
2238 if (ResAttrs.SampleCountExpr) {
2244 ResAttrs.SampleCountExpr =
2250 case attr::HLSLIsCounter:
2251 if (ResAttrs.IsCounter) {
2255 ResAttrs.IsCounter =
true;
2257 case attr::HLSLContainedType: {
2260 if (!ContainedTy.
isNull()) {
2262 ? diag::warn_duplicate_attribute_exact
2263 : diag::warn_duplicate_attribute)
2272 llvm_unreachable(
"unhandled resource attribute type");
2276 if (!HasResourceClass) {
2277 S.
Diag(AttrList.back()->getRange().getEnd(),
2278 diag::err_hlsl_missing_resource_class);
2283 Wrapped, ContainedTy, ResAttrs);
2285 if (LocInfo && ContainedTyInfo) {
2298 if (!
T->isHLSLResourceType()) {
2299 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2314 AttributeCommonInfo::AS_CXX11, 0, false ,
2319 case ParsedAttr::AT_HLSLResourceClass: {
2320 StringRef Identifier;
2322 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2327 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2328 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2329 <<
"ResourceClass" << Identifier;
2332 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2336 case ParsedAttr::AT_HLSLResourceDimension: {
2337 StringRef Identifier;
2339 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2343 llvm::dxil::ResourceDimension RD;
2344 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2346 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2347 <<
"ResourceDimension" << Identifier;
2350 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2354 case ParsedAttr::AT_HLSLIsROV:
2358 case ParsedAttr::AT_HLSLRawBuffer:
2362 case ParsedAttr::AT_HLSLIsCounter:
2366 case ParsedAttr::AT_HLSLIsArray:
2370 case ParsedAttr::AT_HLSLIsMultiSampled:
2374 case ParsedAttr::AT_HLSLContainedType: {
2376 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2382 assert(TSI &&
"no type source info for attribute argument");
2384 diag::err_incomplete_type))
2386 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2391 llvm_unreachable(
"unhandled HLSL attribute");
2394 HLSLResourcesTypeAttrs.emplace_back(A);
2400 if (!HLSLResourcesTypeAttrs.size())
2406 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2407 const HLSLAttributedResourceType *RT =
2414 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2416 HLSLResourcesTypeAttrs.clear();
2424 auto I = LocsForHLSLAttributedResources.find(RT);
2425 if (I != LocsForHLSLAttributedResources.end()) {
2426 LocInfo = I->second;
2427 LocsForHLSLAttributedResources.erase(I);
2436void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2437 const RecordType *RT) {
2445 "incomplete arrays inside user defined types are not supported");
2454 if (
const HLSLAttributedResourceType *AttrResType =
2455 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2460 Bindings.addDeclBindingInfo(VD, RC);
2461 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2467 collectResourceBindingsOnUserRecordDecl(VD, RT);
2479 bool SpecifiedSpace) {
2480 int RegTypeNum =
static_cast<int>(RegType);
2483 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2484 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2489 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2490 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2491 : ResourceClass::SRV;
2501 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2505 if (
const HLSLAttributedResourceType *AttrResType =
2506 HLSLAttributedResourceType::findHandleTypeOnResource(
2523 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2524 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2529 if (RegType == RegisterType::CBuffer)
2530 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2531 else if (RegType != RegisterType::C)
2532 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2536 if (RegType == RegisterType::C)
2537 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2539 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2549 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2557 bool RegisterTypesDetected[5] = {
false};
2558 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2561 if (HLSLResourceBindingAttr *
attr =
2562 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2565 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2566 int otherRegTypeNum =
static_cast<int>(otherRegType);
2568 diag::err_hlsl_duplicate_register_annotation)
2572 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2580 bool SpecifiedSpace) {
2585 "expecting VarDecl or HLSLBufferDecl");
2597 const uint64_t &Limit,
2600 uint64_t ArrayCount = 1) {
2605 if (StartSlot > Limit)
2609 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2612 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2613 Count = CAT->
getSize().getZExtValue();
2617 ArrayCount * Count);
2621 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2624 if (ResTy->getAttrs().ResourceClass != ResClass)
2628 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2629 if (EndSlot > Limit)
2633 StartSlot = EndSlot + 1;
2638 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2641 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2644 ResClass, Ctx, ArrayCount))
2651 ResClass, Ctx, ArrayCount))
2665 const uint64_t Limit = UINT32_MAX;
2666 if (SlotNum > Limit)
2671 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2674 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2675 uint64_t BaseSlot = SlotNum;
2683 return (BaseSlot > Limit);
2690 return (SlotNum > Limit);
2693 llvm_unreachable(
"unexpected decl type");
2697 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2699 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2700 Ty = IAT->getElementType();
2702 diag::err_incomplete_type))
2706 StringRef Slot =
"";
2707 StringRef Space =
"";
2711 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2721 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2727 SpaceLoc = Loc->
getLoc();
2730 if (Str.starts_with(
"space")) {
2732 SpaceLoc = Loc->
getLoc();
2741 std::optional<unsigned> SlotNum;
2742 unsigned SpaceNum = 0;
2745 if (!Slot.empty()) {
2747 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2750 if (RegType == RegisterType::I) {
2751 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2754 const StringRef SlotNumStr = Slot.substr(1);
2759 if (SlotNumStr.getAsInteger(10, N)) {
2760 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2768 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2777 if (!Space.starts_with(
"space")) {
2778 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2781 StringRef SpaceNumStr = Space.substr(5);
2782 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2783 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2788 if (SlotNum.has_value())
2793 HLSLResourceBindingAttr *NewAttr =
2794 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2796 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2820 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2822 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2826 Cur = AT->getModifiedType();
2837 ? attr::HLSLRowMajor
2838 : attr::HLSLColumnMajor;
2842 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2851 if (ExistingKind == AttrK) {
2852 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2854 Diag(AL.
getLoc(), diag::note_previous_attribute);
2858 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2859 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2861 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2866 if (AttrK == attr::HLSLRowMajor)
2867 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2868 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2879 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2881 if (
T.isNull() ||
T->isDependentType())
2886 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2887 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
2935 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2939 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2940 unsigned CurrentShaderStageBit;
2945 bool ReportOnlyShaderStageIssues;
2948 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2949 static_assert(
sizeof(
unsigned) >= 4);
2950 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2951 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2952 "ShaderType is too big for this bitmap");
2955 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2956 CurrentShaderEnvironment = ShaderType;
2957 CurrentShaderStageBit = (1 << bitmapIndex);
2960 void SetUnknownShaderStageContext() {
2961 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2962 CurrentShaderStageBit = (1 << 31);
2965 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2966 return CurrentShaderEnvironment;
2969 bool InUnknownShaderStageContext()
const {
2970 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2974 void AddToScannedFunctions(
const FunctionDecl *FD) {
2975 unsigned &ScannedStages = ScannedDecls[FD];
2976 ScannedStages |= CurrentShaderStageBit;
2979 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2981 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2982 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2985 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2986 return ScannerStages & CurrentShaderStageBit;
2989 static bool NeverBeenScanned(
unsigned ScannedStages) {
2990 return ScannedStages == 0;
2994 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2995 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2997 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2998 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3001 DiagnoseHLSLAvailability(Sema &SemaRef)
3003 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3004 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3007 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3008 void RunOnFunction(
const FunctionDecl *FD);
3010 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3011 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3013 HandleFunctionOrMethodRef(FD, DRE);
3017 bool VisitMemberExpr(MemberExpr *ME)
override {
3018 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3020 HandleFunctionOrMethodRef(FD, ME);
3025void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3028 "expected DeclRefExpr or MemberExpr");
3030 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3031 CheckDeclAvailability(
3036 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3037 DeclsToScan.push_back(FDWithBody);
3040void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3045 llvm::Triple::EnvironmentType::Library;
3054 DeclContextsToScan.push_back(TU);
3056 while (!DeclContextsToScan.empty()) {
3057 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3058 for (
auto &D : DC->
decls()) {
3065 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3066 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3071 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3076 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3077 if (!IsLibraryShader && FD->
getName() == EntryName) {
3080 diag::err_hlsl_ambiguous_entry_point)
3082 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3088 SetShaderStageContext(ShaderAttr->getType());
3097 for (
const auto *Redecl : FD->
redecls()) {
3098 if (Redecl->isInExportDeclContext()) {
3105 SetUnknownShaderStageContext();
3112 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3119void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3120 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3121 DeclsToScan.push_back(FD);
3123 while (!DeclsToScan.empty()) {
3131 const unsigned ScannedStages = GetScannedStages(FD);
3132 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3135 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3137 AddToScannedFunctions(FD);
3142bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3143 const AvailabilityAttr *AA) {
3148 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3149 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3152 llvm::Triple::EnvironmentType AttrEnv =
3153 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3155 return CurrentEnv == AttrEnv;
3158const AvailabilityAttr *
3159DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3160 AvailabilityAttr
const *PartialMatch =
nullptr;
3164 for (
const auto *A : D->
attrs()) {
3165 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3166 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3167 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3168 StringRef TargetPlatform =
3172 if (AttrPlatform == TargetPlatform) {
3174 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3176 PartialMatch = Avail;
3180 return PartialMatch;
3185void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3186 const AvailabilityAttr *AA,
3205 if (ReportOnlyShaderStageIssues)
3211 if (InUnknownShaderStageContext())
3216 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3217 VersionTuple Introduced = AA->getIntroduced();
3226 llvm::StringRef PlatformName(
3229 llvm::StringRef CurrentEnvStr =
3230 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3232 llvm::StringRef AttrEnvStr =
3233 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3234 bool UseEnvironment = !AttrEnvStr.empty();
3236 if (EnvironmentMatches) {
3237 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3238 <<
Range << D << PlatformName << Introduced.getAsString()
3239 << UseEnvironment << CurrentEnvStr;
3241 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3245 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3246 << D << PlatformName << Introduced.getAsString()
3248 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3255 if (!DefaultCBufferDecls.empty()) {
3258 DefaultCBufferDecls);
3261 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3265 for (
const Decl *VD : DefaultCBufferDecls) {
3266 const HLSLResourceBindingAttr *RBA =
3267 VD->
getAttr<HLSLResourceBindingAttr>();
3268 if (RBA && RBA->hasRegisterSlot() &&
3269 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3276 SemaRef.Consumer.HandleTopLevelDecl(DG);
3278 diagnoseAvailabilityViolations(TU);
3287 "expected member expr to have resource record type or array of them");
3293 const Expr *NonConstIndexExpr =
nullptr;
3296 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3297 if (!NonConstIndexExpr)
3305 diag::err_hlsl_resource_member_array_access_not_constant);
3309 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3310 const Expr *IdxExpr = ASE->getIdx();
3312 NonConstIndexExpr = IdxExpr;
3314 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3315 E = SubME->getBase();
3316 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3317 E = ICE->getSubExpr();
3319 llvm_unreachable(
"unexpected expr type in resource member access");
3328 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3331 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3334 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3338 [[maybe_unused]]
bool LookupSucceeded =
3339 SemaRef.LookupQualifiedName(ConvR, RD);
3340 assert(LookupSucceeded);
3349std::optional<ExprResult>
3352 const HLSLAttributedResourceType *ResTy =
3353 HLSLAttributedResourceType::findHandleTypeOnResource(
3354 BaseType.getTypePtr());
3356 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3357 return std::nullopt;
3359 QualType TemplateType = ResTy->getContainedType();
3363 assert(NamedConversionDecl &&
3364 "Could not find conversion function for ConstantBuffer.");
3365 auto *ConversionDecl =
3368 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3380 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
3383 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
3390 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3393 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3418 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3433 if (!BaseType->isFloat32Type())
3434 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3435 << ArgOrdinal << 5 << 0
3445 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3446 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3447 << ArgOrdinal << 5 << 0
3456 if (!BaseType->isDoubleType()) {
3459 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3460 << ArgOrdinal << PassedType;
3467 unsigned ArgIndex) {
3468 auto *Arg = TheCall->
getArg(ArgIndex);
3470 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3473 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3487 << (ArgIndex + 1) << LValueTy;
3497 if (VecTy->getElementType()->isDoubleType())
3498 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3499 << ArgOrdinal << 1 << 0 << 1
3509 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3510 << ArgOrdinal << 5 << 1
3519 if (VecTy->getElementType()->isUnsignedIntegerType())
3522 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3523 << ArgOrdinal << 4 << 3 << 0
3532 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3533 << ArgOrdinal << 5 << 3
3539 unsigned ArgOrdinal,
unsigned Width) {
3542 ArgTy = VTy->getElementType();
3544 uint64_t ElementBitCount =
3546 if (ElementBitCount != Width) {
3548 diag::err_integer_incorrect_bit_count)
3549 << Width << ElementBitCount;
3560 else if (
auto *MatTyA =
3563 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3569 unsigned ArgIndex) {
3578 diag::err_typecheck_expect_scalar_or_vector)
3579 << ArgType << Scalar;
3586 QualType Scalar,
unsigned ArgIndex) {
3597 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3610 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3611 << ArgType << Scalar;
3616 unsigned ArgIndex) {
3621 if (!(ArgType->isScalarType() ||
3622 (VTy && VTy->getElementType()->isScalarType()))) {
3624 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3632 unsigned ArgIndex) {
3635 if (ArgType->isDependentType())
3639 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3640 ElementType = VectorTy->getElementType();
3642 ElementType = MatrixTy->getElementType();
3644 if (ElementType->isBooleanType())
3647 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3649 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3654 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3662 unsigned ArgIndex) {
3664 assert(ArgIndex < TheCall->getNumArgs());
3672 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3697 diag::err_typecheck_call_different_arg_types)
3716 Arg1ScalarTy = VTy->getElementType();
3720 Arg2ScalarTy = VTy->getElementType();
3723 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3724 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3734 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3736 diag::err_typecheck_vector_lengths_not_equal)
3742 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3744 diag::err_typecheck_vector_lengths_not_equal)
3764 Arg1ScalarTy = MTy->getElementType();
3768 Arg2ScalarTy = MTy->getElementType();
3771 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3772 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3777 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
3779 for (
Expr *Arg : {Arg1, Arg2}) {
3782 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
3784 diag::err_typecheck_vector_lengths_not_equal)
3786 << Arg->getSourceRange();
3802 unsigned ArgIndex) {
3807 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
3810 unsigned int ActualDim = 1;
3812 ActualDim = VTy->getNumElements();
3813 IndexTy = VTy->getElementType();
3817 diag::err_typecheck_expect_int)
3823 const HLSLAttributedResourceType *ResTy =
3825 assert(ResTy &&
"Resource argument must be a resource");
3826 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
3828 unsigned int ExpectedDim = 1;
3829 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
3831 (ResAttrs.IsArray ? 1 : 0);
3833 if (ActualDim != ExpectedDim) {
3835 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
3846 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
3850 const HLSLAttributedResourceType *ResTy =
3854 diag::err_typecheck_expect_hlsl_resource)
3858 if (Check && Check(ResTy)) {
3860 diag::err_invalid_hlsl_resource_type)
3870 "expected resource handle type");
3871 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3872 auto MainAttrs = MainResType->getAttrs();
3873 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3874 MainAttrs.IsCounter =
true;
3876 MainResType->getContainedType(),
3887 return "SampleBias";
3889 return "SampleGrad";
3891 return "SampleLevel";
3895 return "SampleCmpLevelZero";
3897 llvm_unreachable(
"Invalid SampleKind");
3907 if (!MD || !MD->getDeclName().isIdentifier())
3914 return MD->getName();
3922 return VecTy->getElementType();
3923 return ContainedType;
3931 StringRef DefaultName) {
3936 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
3963 if (SMVersion >= VersionTuple(6, 7))
3966 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
3968 << ContainedType << SMVersion.getAsString();
3973 bool IncludeArraySlice =
true) {
3976 [](
const HLSLAttributedResourceType *ResType) {
3977 return ResType->getAttrs().ResourceDimension ==
3978 llvm::dxil::ResourceDimension::Unknown;
3984 [](
const HLSLAttributedResourceType *ResType) {
3985 return ResType->getAttrs().ResourceClass !=
3986 llvm::hlsl::ResourceClass::Sampler;
3994 unsigned ExpectedDim =
3996 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4025 unsigned NextIdx = 3;
4037 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4041 std::optional<llvm::APSInt> ComponentOpt =
4044 int64_t ComponentVal = ComponentOpt->getSExtValue();
4045 if (ComponentVal != 0) {
4048 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4049 "The component is not in the expected range.");
4051 diag::err_hlsl_gathercmp_invalid_component)
4061 const HLSLAttributedResourceType *ResourceTy =
4064 unsigned ExpectedDim =
4067 &S, TheCall->
getArg(NextIdx),
4073 assert(ResourceTy->hasContainedType() &&
4074 "Expecting a contained type for resource with a dimension "
4076 QualType ReturnType = ResourceTy->getContainedType();
4079 IsCmp ?
"GatherCmp" :
"Gather"))
4084 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4090 ReturnType = VecTy->getElementType();
4103 [](
const HLSLAttributedResourceType *ResType) {
4104 return ResType->getAttrs().ResourceDimension ==
4105 llvm::dxil::ResourceDimension::Unknown;
4115 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4122 unsigned ResourceDim =
4124 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4140 TheCall->
setType(ResourceTy->getContainedType());
4150 [](
const HLSLAttributedResourceType *ResType) {
4151 return !ResType->isMultiSampled();
4160 unsigned ResourceDim =
4162 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4180 TheCall->
setType(ResourceTy->getContainedType());
4185 unsigned MinArgs, MaxArgs;
4213 const HLSLAttributedResourceType *ResourceTy =
4215 unsigned ExpectedDim =
4218 unsigned NextIdx = 3;
4243 &S, TheCall->
getArg(NextIdx),
4256 assert(ResourceTy->hasContainedType() &&
4257 "Expecting a contained type for resource with a dimension "
4259 QualType ReturnType = ResourceTy->getContainedType();
4270 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4287 unsigned MinArgs,
unsigned MaxArgs,
4289 bool ReportsOriginalValue) {
4290 if (MinArgs == MaxArgs) {
4293 }
else if (TheCall->
getNumArgs() < MinArgs) {
4294 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4304 const bool DestIsOK =
4310 diag::err_builtin_invalid_arg_type)
4324 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4340 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4346 const unsigned NumArgs = TheCall->
getNumArgs();
4347 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4358 switch (BuiltinID) {
4359 case Builtin::BI__builtin_hlsl_adduint64: {
4360 if (
SemaRef.checkArgCount(TheCall, 2))
4374 if (NumElementsArg != 2 && NumElementsArg != 4) {
4376 << 1 << 64 << NumElementsArg * 32;
4390 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4391 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4398 QualType ContainedTy = ResourceTy->getContainedType();
4399 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4402 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4407 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4408 if (
SemaRef.checkArgCount(TheCall, 3) ||
4415 "expected pointer type for second argument");
4422 diag::err_invalid_use_of_array_type);
4426 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4429 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4434 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4435 if (
SemaRef.checkArgCount(TheCall, 2) ||
4437 SemaRef.getASTContext().IntTy))
4444 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4445 if (
SemaRef.checkArgCount(TheCall, 3) ||
4448 SemaRef.getASTContext().UnsignedIntTy) ||
4450 SemaRef.getASTContext().UnsignedIntTy) ||
4456 QualType ReturnType = ResourceTy->getContainedType();
4461 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4462 if (
SemaRef.checkArgCount(TheCall, 4) ||
4465 SemaRef.getASTContext().UnsignedIntTy) ||
4467 SemaRef.getASTContext().UnsignedIntTy) ||
4473 "expected pointer type for second argument");
4480 diag::err_invalid_use_of_array_type);
4486 case Builtin::BI__builtin_hlsl_resource_load_level:
4488 case Builtin::BI__builtin_hlsl_resource_load_ms:
4490 case Builtin::BI__builtin_hlsl_resource_sample:
4492 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4494 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4496 case Builtin::BI__builtin_hlsl_resource_sample_level:
4498 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4500 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4502 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4503 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4505 case Builtin::BI__builtin_hlsl_resource_gather:
4507 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4509 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4510 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4516 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4517 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4523 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4524 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4530 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4531 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4537 TheCall->
setType(CounterHandleTy);
4540 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4541 if (
SemaRef.checkArgCount(TheCall, 2) ||
4544 SemaRef.getASTContext().UnsignedIntTy))
4552 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4553 if (
SemaRef.checkArgCount(TheCall, 1) ||
4561 TheCall->
setType(CounterHandleTy);
4564 case Builtin::BI__builtin_hlsl_and:
4565 case Builtin::BI__builtin_hlsl_or: {
4566 if (
SemaRef.checkArgCount(TheCall, 2))
4580 case Builtin::BI__builtin_hlsl_all:
4581 case Builtin::BI__builtin_hlsl_any: {
4582 if (
SemaRef.checkArgCount(TheCall, 1))
4588 case Builtin::BI__builtin_hlsl_asdouble: {
4589 if (
SemaRef.checkArgCount(TheCall, 2))
4593 SemaRef.Context.UnsignedIntTy,
4598 SemaRef.Context.UnsignedIntTy,
4607 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4608 if (
SemaRef.BuiltinElementwiseTernaryMath(
4614 case Builtin::BI__builtin_hlsl_dot: {
4616 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4622 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4623 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4624 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4634 EltTy = VecTy->getElementType();
4635 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4648 case Builtin::BI__builtin_hlsl_select: {
4649 if (
SemaRef.checkArgCount(TheCall, 3))
4658 if (VTy && VTy->getElementType()->isBooleanType() &&
4662 if (MTy && MTy->getElementType()->isBooleanType() &&
4667 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4668 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4669 if (
SemaRef.checkArgCount(TheCall, 1))
4675 diag::err_builtin_invalid_arg_type)
4678 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4682 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4683 case Builtin::BI__builtin_hlsl_elementwise_frac:
4684 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4685 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4686 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4687 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4688 if (
SemaRef.checkArgCount(TheCall, 1))
4693 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4697 case Builtin::BI__builtin_hlsl_elementwise_isinf:
4698 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
4699 if (
SemaRef.checkArgCount(TheCall, 1))
4704 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4709 case Builtin::BI__builtin_hlsl_mad: {
4710 if (
SemaRef.BuiltinElementwiseTernaryMath(
4716 case Builtin::BI__builtin_hlsl_mul: {
4717 if (
SemaRef.checkArgCount(TheCall, 2))
4727 return VTy->getElementType();
4729 return MTy->getElementType();
4733 QualType EltTy0 = getElemType(Ty0);
4742 if (IsVec0 && IsMat1) {
4745 }
else if (IsMat0 && IsVec1) {
4749 assert(IsMat0 && IsMat1);
4759 case Builtin::BI__builtin_elementwise_fma: {
4760 if (
SemaRef.checkArgCount(TheCall, 3) ||
4775 case Builtin::BI__builtin_hlsl_transpose: {
4776 if (
SemaRef.checkArgCount(TheCall, 1))
4785 << 1 << 3 << 0 << 0 << ArgTy;
4790 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
4794 case Builtin::BI__builtin_hlsl_elementwise_sign: {
4795 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4803 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
4804 if (
SemaRef.checkArgCount(TheCall, 1))
4818 unsigned NumElts = VecTy->getNumElements();
4828 case Builtin::BI__builtin_hlsl_wave_active_max:
4829 case Builtin::BI__builtin_hlsl_wave_active_min:
4830 case Builtin::BI__builtin_hlsl_wave_active_sum:
4831 case Builtin::BI__builtin_hlsl_wave_active_product: {
4832 if (
SemaRef.checkArgCount(TheCall, 1))
4845 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
4846 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
4847 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
4848 if (
SemaRef.checkArgCount(TheCall, 1))
4863 (VTy && VTy->getElementType()->isIntegerType()))) {
4865 diag::err_builtin_invalid_arg_type)
4866 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4874 case Builtin::BI__builtin_hlsl_interlocked_add:
4875 case Builtin::BI__builtin_hlsl_interlocked_and:
4876 case Builtin::BI__builtin_hlsl_interlocked_max:
4877 case Builtin::BI__builtin_hlsl_interlocked_min:
4878 case Builtin::BI__builtin_hlsl_interlocked_or:
4879 case Builtin::BI__builtin_hlsl_interlocked_xor:
4885 case Builtin::BI__builtin_hlsl_interlocked_exchange:
4891 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
4897 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
4903 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
4909 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
4917 case Builtin::BI__builtin_elementwise_bitreverse: {
4925 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
4926 if (
SemaRef.checkArgCount(TheCall, 1))
4931 if (!(
ArgType->isScalarType())) {
4933 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4938 if (!(
ArgType->isBooleanType())) {
4940 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4947 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
4948 if (
SemaRef.checkArgCount(TheCall, 2))
4956 diag::err_typecheck_convert_incompatible)
4957 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
4970 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
4971 if (
SemaRef.checkArgCount(TheCall, 1))
4980 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
4981 if (
SemaRef.checkArgCount(TheCall, 0))
4985 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
4986 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
4987 if (
SemaRef.checkArgCount(TheCall, 1))
5000 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5001 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5002 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5003 if (
SemaRef.checkArgCount(TheCall, 1))
5015 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5016 if (
SemaRef.checkArgCount(TheCall, 3))
5022 SemaRef.Context.UnsignedIntTy, 1) ||
5024 SemaRef.Context.UnsignedIntTy, 2))
5032 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5033 if (
SemaRef.checkArgCount(TheCall, 1))
5040 case Builtin::BI__builtin_elementwise_acos:
5041 case Builtin::BI__builtin_elementwise_asin:
5042 case Builtin::BI__builtin_elementwise_atan:
5043 case Builtin::BI__builtin_elementwise_atan2:
5044 case Builtin::BI__builtin_elementwise_ceil:
5045 case Builtin::BI__builtin_elementwise_cos:
5046 case Builtin::BI__builtin_elementwise_cosh:
5047 case Builtin::BI__builtin_elementwise_exp:
5048 case Builtin::BI__builtin_elementwise_exp2:
5049 case Builtin::BI__builtin_elementwise_exp10:
5050 case Builtin::BI__builtin_elementwise_floor:
5051 case Builtin::BI__builtin_elementwise_fmod:
5052 case Builtin::BI__builtin_elementwise_log:
5053 case Builtin::BI__builtin_elementwise_log2:
5054 case Builtin::BI__builtin_elementwise_log10:
5055 case Builtin::BI__builtin_elementwise_pow:
5056 case Builtin::BI__builtin_elementwise_roundeven:
5057 case Builtin::BI__builtin_elementwise_sin:
5058 case Builtin::BI__builtin_elementwise_sinh:
5059 case Builtin::BI__builtin_elementwise_sqrt:
5060 case Builtin::BI__builtin_elementwise_tan:
5061 case Builtin::BI__builtin_elementwise_tanh:
5062 case Builtin::BI__builtin_elementwise_trunc: {
5068 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5069 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5070 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5071 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5072 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5077 std::optional<llvm::APSInt> Offset =
5079 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5081 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5087 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5088 if (
SemaRef.checkArgCount(TheCall, 1))
5099 ArgTy = VTy->getElementType();
5102 diag::err_builtin_invalid_arg_type)
5111 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5112 if (
SemaRef.checkArgCount(TheCall, 1))
5127 WorkList.push_back(BaseTy);
5128 while (!WorkList.empty()) {
5130 T =
T.getCanonicalType().getUnqualifiedType();
5131 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5139 for (uint64_t Ct = 0; Ct < AT->
getZExtSize(); ++Ct)
5140 llvm::append_range(List, ElementFields);
5145 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5146 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5149 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5150 List.insert(List.end(), MT->getNumElementsFlattened(),
5151 MT->getElementType());
5154 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5155 if (RD->isStandardLayout())
5156 RD = RD->getStandardLayoutBaseWithFields();
5160 if (RD->
isUnion() || !RD->isAggregate()) {
5166 for (
const auto *FD : RD->
fields())
5167 if (!FD->isUnnamedBitField())
5168 FieldTypes.push_back(FD->
getType());
5170 std::reverse(FieldTypes.begin(), FieldTypes.end());
5171 llvm::append_range(WorkList, FieldTypes);
5175 if (!RD->isStandardLayout()) {
5177 for (
const auto &
Base : RD->bases())
5178 FieldTypes.push_back(
Base.getType());
5179 std::reverse(FieldTypes.begin(), FieldTypes.end());
5180 llvm::append_range(WorkList, FieldTypes);
5215 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5221 int ArraySize = VT->getNumElements();
5226 QualType ElTy = VT->getElementType();
5230 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5246 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5255 return llvm::equal(T1Types, T2Types,
5257 return SemaRef.IsLayoutCompatible(LHS, RHS);
5266 bool HadError =
false;
5268 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5276 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5277 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5278 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5279 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5281 if (NSpellingIdx != OSpellingIdx) {
5283 diag::err_hlsl_param_qualifier_mismatch)
5284 << NDAttr << NewParam;
5300 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5315 llvm_unreachable(
"HLSL doesn't support pointers.");
5318 llvm_unreachable(
"HLSL doesn't support complex types.");
5320 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5322 llvm_unreachable(
"Should have returned before this");
5332 llvm_unreachable(
"HLSL doesn't support complex types.");
5334 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5339 llvm_unreachable(
"HLSL doesn't support pointers.");
5341 llvm_unreachable(
"Should have returned before this");
5347 llvm_unreachable(
"HLSL doesn't support pointers.");
5350 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5354 llvm_unreachable(
"HLSL doesn't support complex types.");
5357 llvm_unreachable(
"Unhandled scalar cast");
5378 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5384 SrcTy = SrcMatTy->getElementType();
5389 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5390 if (DestTypes[I]->isUnionType())
5422 if (SrcTypes.size() < DestTypes.size())
5425 unsigned SrcSize = SrcTypes.size();
5426 unsigned DstSize = DestTypes.size();
5428 for (I = 0; I < DstSize && I < SrcSize; I++) {
5429 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5437 for (; I < SrcSize; I++) {
5438 if (SrcTypes[I]->isUnionType())
5458 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5459 "We should not get here without a parameter modifier expression");
5460 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5467 << Arg << (IsInOut ? 1 : 0);
5473 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5480 << Arg << (IsInOut ? 1 : 0);
5492 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5498 auto *OpV =
new (Ctx)
5504 tok::equal, ArgOpV, OpV);
5520 "Pointer and reference types cannot be inout or out parameters");
5521 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5537 for (
const auto *FD : RD->
fields()) {
5541 assert(RD->getNumBases() <= 1 &&
5542 "HLSL doesn't support multiple inheritance");
5543 return RD->getNumBases()
5548 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5549 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5561 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5566 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5572 if (
Decl->getType().hasAddressSpace())
5575 if (
Decl->getType()->isDependentType())
5587 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5601 llvm::Triple::Vulkan;
5602 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5603 if (HasDeclaredAPushConstant)
5609 HasDeclaredAPushConstant =
true;
5636class StructBindingContext {
5639 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5640 unsigned RegBindingOffset[4];
5643 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5644 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5645 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5646 static_cast<unsigned>(RegisterType::Sampler) == 3,
5647 "unexpected register type values");
5650 HLSLVkBindingAttr *VkBindingAttr;
5651 unsigned VkBindingOffset;
5656 StructBindingContext(
VarDecl *VD) {
5657 for (
unsigned i = 0; i < 4; ++i) {
5658 RegBindingsAttrs[i] =
nullptr;
5659 RegBindingOffset[i] = 0;
5661 VkBindingAttr =
nullptr;
5662 VkBindingOffset = 0;
5668 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5670 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5673 RegBindingsAttrs[RegTypeIdx] = RBA;
5678 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5679 VkBindingAttr = VBA;
5686 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5687 unsigned Range,
bool HasCounter) {
5688 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5690 if (VkBindingAttr) {
5691 unsigned Offset = VkBindingOffset;
5692 VkBindingOffset +=
Range;
5693 return HLSLVkBindingAttr::CreateImplicit(
5694 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5695 VkBindingAttr->getRange());
5698 HLSLResourceBindingAttr *RBA =
5699 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
5700 HLSLResourceBindingAttr *NewAttr =
nullptr;
5702 if (RBA && RBA->hasRegisterSlot()) {
5705 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
5706 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
5708 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
5709 StringRef NewSlotNumberStr =
5711 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
5712 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
5713 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
5717 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
5718 NewAttr->setBinding(RegType, std::nullopt,
5719 RBA ? RBA->getSpaceNumber() : 0);
5723 NewAttr->setImplicitCounterBindingOrderID(
5732static void createGlobalResourceDeclForStruct(
5734 QualType ResTy, StructBindingContext &BindingCtx) {
5736 "expected resource type or array of resources");
5747 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
5748 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
5753 const HLSLAttributedResourceType *ResHandleTy =
5754 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
5758 Attr *BindingAttr = BindingCtx.createBindingAttr(
5760 ResDecl->
addAttr(BindingAttr);
5761 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
5770 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
5777static void handleArrayOfStructWithResources(
5779 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
5784static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
5786 EmbeddedResourceNameBuilder &NameBuilder,
5787 StructBindingContext &BindingCtx) {
5790 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
5797 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
5811 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
5814 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
5816 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
5818 "resource arrays should have been already handled");
5819 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
5828handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
5830 EmbeddedResourceNameBuilder &NameBuilder,
5831 StructBindingContext &BindingCtx) {
5839 if (!SubCAT && !ElementRD)
5842 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
5845 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
5848 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
5861void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
5862 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
5863 StructBindingContext BindingCtx(VD);
5867 "Expected non-resource struct or array type");
5870 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
5874 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
5875 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
5883 if (
SemaRef.RequireCompleteType(
5886 diag::err_typecheck_decl_incomplete_type)) {
5900 DefaultCBufferDecls.push_back(VD);
5905 collectResourceBindingsOnVarDecl(VD);
5907 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
5919 processExplicitBindingsOnDecl(VD);
5957 handleGlobalStructOrArrayOfWithResources(VD);
5961 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
5970 "expected resource record type");
5986 const char *CreateMethodName;
5988 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
5989 :
"__createFromBinding";
5991 CreateMethodName = HasCounter
5992 ?
"__createFromImplicitBindingWithImplicitCounter"
5993 :
"__createFromImplicitBinding";
5998 if (!CreateMethod) {
6003 "create method lookup should always succeed for built-in resource "
6012 Args.push_back(RegSlot);
6020 Args.push_back(OrderId);
6026 Args.push_back(Space);
6030 Args.push_back(RangeSize);
6034 Args.push_back(Index);
6036 StringRef VarName = VD->
getName();
6044 Args.push_back(NameCast);
6052 Args.push_back(CounterId);
6075 SemaRef.CheckCompleteVariableDeclaration(VD);
6081 "expected array of resource records");
6102 lookupMethod(
SemaRef, ResourceDecl,
6103 HasCounter ?
"__createFromBindingWithImplicitCounter"
6104 :
"__createFromBinding",
6108 CreateMethod = lookupMethod(
6110 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6111 :
"__createFromImplicitBinding",
6154std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6155 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6156 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6157 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6158 if (!TrueInfo || !FalseInfo)
6159 return std::nullopt;
6160 if (*TrueInfo != *FalseInfo)
6161 return std::nullopt;
6165 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6174 if (
const auto *AttrResType =
6175 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6177 return Bindings.getDeclBindingInfo(VD, RC);
6184void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6185 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6188 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6193 if (*ExprBinding ==
nullptr)
6196 auto PrevBinding = Assigns.find(VD);
6197 if (PrevBinding == Assigns.end()) {
6199 Assigns.insert({VD, *ExprBinding});
6204 if (*ExprBinding != PrevBinding->second) {
6206 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6208 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6219 "expected LHS to be a resource record or array of resource records");
6220 if (Opc != BO_Assign)
6225 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6233 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6238 trackLocalResource(VD, RHSExpr);
6255void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6257 "expected global variable that contains HLSL resource");
6260 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6261 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6262 ? ResourceClass::CBuffer
6263 : ResourceClass::SRV);
6276 if (
const HLSLAttributedResourceType *AttrResType =
6277 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6278 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6283 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6284 collectResourceBindingsOnUserRecordDecl(VD, RT);
6290void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6293 bool HasBinding =
false;
6294 for (Attr *A : VD->
attrs()) {
6297 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6298 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6301 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6302 if (!RBA || !RBA->hasRegisterSlot())
6307 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6308 "never have an attribute created");
6310 if (RT == RegisterType::C) {
6311 if (Bindings.hasBindingInfoForDecl(VD))
6313 diag::warn_hlsl_user_defined_type_missing_member)
6314 <<
static_cast<int>(RT);
6322 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6327 diag::warn_hlsl_user_defined_type_missing_member)
6328 <<
static_cast<int>(RT);
6336class InitListTransformer {
6340 QualType *DstIt =
nullptr;
6341 Expr **ArgIt =
nullptr;
6347 bool castInitializer(Expr *E) {
6348 assert(DstIt &&
"This should always be something!");
6349 if (DstIt == DestTypes.end()) {
6351 ArgExprs.push_back(E);
6356 DstIt = DestTypes.begin();
6359 Ctx, *DstIt,
false);
6364 ArgExprs.push_back(
Init);
6369 bool buildInitializerListImpl(Expr *E) {
6371 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6372 for (
auto *SubInit :
Init->inits())
6373 if (!buildInitializerListImpl(SubInit))
6383 return castInitializer(E);
6397 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6402 for (uint64_t I = 0; I <
Size; ++I) {
6404 SizeTy, SourceLocation());
6410 if (!castInitializer(ElExpr.
get()))
6415 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6416 unsigned Rows = MTy->getNumRows();
6417 unsigned Cols = MTy->getNumColumns();
6418 QualType ElemTy = MTy->getElementType();
6420 for (
unsigned R = 0;
R < Rows; ++
R) {
6421 for (
unsigned C = 0;
C < Cols; ++
C) {
6434 if (!castInitializer(ElExpr.
get()))
6442 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6446 for (uint64_t I = 0; I <
Size; ++I) {
6448 SizeTy, SourceLocation());
6453 if (!buildInitializerListImpl(ElExpr.
get()))
6460 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6461 RecordDecls.push_back(RD);
6462 while (RecordDecls.back()->getNumBases()) {
6463 CXXRecordDecl *D = RecordDecls.back();
6465 "HLSL doesn't support multiple inheritance");
6466 RecordDecls.push_back(
6469 while (!RecordDecls.empty()) {
6470 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6471 for (
auto *FD : RD->
fields()) {
6472 if (FD->isUnnamedBitField())
6480 if (!buildInitializerListImpl(Res.
get()))
6488 Expr *generateInitListsImpl(QualType Ty) {
6490 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6495 llvm::SmallVector<Expr *>
Inits;
6500 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6501 ElTy = ATy->getElementType();
6502 Size = ATy->getNumElements();
6503 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6504 ElTy = CMTy->getElementType();
6505 Size = CMTy->getNumElementsFlattened();
6508 ElTy = VTy->getElementType();
6509 Size = VTy->getZExtSize();
6511 for (uint64_t I = 0; I <
Size; ++I)
6512 Inits.push_back(generateInitListsImpl(ElTy));
6515 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6516 RecordDecls.push_back(RD);
6517 while (RecordDecls.back()->getNumBases()) {
6518 CXXRecordDecl *D = RecordDecls.back();
6520 "HLSL doesn't support multiple inheritance");
6521 RecordDecls.push_back(
6524 while (!RecordDecls.empty()) {
6525 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6526 for (
auto *FD : RD->
fields())
6527 if (!FD->isUnnamedBitField())
6532 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6533 Inits.back()->getEndLoc(),
false);
6534 NewInit->setType(Ty);
6539 llvm::SmallVector<QualType, 16> DestTypes;
6540 llvm::SmallVector<Expr *, 16> ArgExprs;
6541 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6542 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6543 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6544 InitTy = Entity.
getType().getNonReferenceType();
6554 DstIt = DestTypes.begin();
6557 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6559 Expr *generateInitLists() {
6560 assert(!ArgExprs.empty() &&
6561 "Call buildInitializerList to generate argument expressions.");
6562 ArgIt = ArgExprs.begin();
6564 return generateInitListsImpl(InitTy);
6565 llvm::SmallVector<Expr *>
Inits;
6566 while (ArgIt != ArgExprs.end())
6567 Inits.push_back(generateInitListsImpl(InitTy));
6570 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6571 Inits.back()->getEndLoc(),
false);
6572 llvm::APInt ArySize(64,
Inits.size());
6574 ArraySizeModifier::Normal, 0));
6586 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6593 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6597 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6617 if (
Init->getType()->isScalarType())
6620 InitListTransformer ILT(
SemaRef, Entity);
6622 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6630 Init->setInit(I, E);
6632 if (!ILT.buildInitializerList(E))
6635 size_t ExpectedSize = ILT.DestTypes.size();
6636 size_t ActualSize = ILT.ArgExprs.size();
6637 if (ExpectedSize == 0 && ActualSize == 0)
6644 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6646 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6647 << (int)(ExpectedSize < ActualSize) << InitTy
6648 << ExpectedSize << ActualSize;
6658 assert(ExpectedSize > 0 &&
6659 "The expected size of an incomplete array type must be at least 1.");
6661 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6669 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6670 if (ExpectedSize != ActualSize) {
6671 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6672 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6673 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6680 Init->resizeInits(Ctx, NewInit->getNumInits());
6681 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6682 Init->updateInit(Ctx, I, NewInit->getInit(I));
6690 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
6700 StringRef AccessorName = CompName->
getName();
6701 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
6703 unsigned Rows = MT->getNumRows();
6704 unsigned Cols = MT->getNumColumns();
6705 bool IsZeroBasedAccessor =
false;
6706 unsigned ChunkLen = 0;
6707 if (AccessorName.size() < 2)
6709 "length 4 for zero based: \'_mRC\' or "
6710 "length 3 for one-based: \'_RC\' accessor",
6713 if (AccessorName[0] ==
'_') {
6714 if (AccessorName[1] ==
'm') {
6715 IsZeroBasedAccessor =
true;
6722 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
6725 if (AccessorName.size() % ChunkLen != 0) {
6726 const llvm::StringRef
Expected = IsZeroBasedAccessor
6727 ?
"zero based: '_mRC' accessor"
6728 :
"one-based: '_RC' accessor";
6733 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
6734 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
6735 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
6737 bool HasRepeated =
false;
6739 unsigned NumComponents = 0;
6740 const char *Begin = AccessorName.data();
6742 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
6743 const char *Chunk = Begin + I;
6744 char RowChar = 0, ColChar = 0;
6745 if (IsZeroBasedAccessor) {
6747 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
6748 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
6750 S, StringRef(&Bad, 1),
"\'_m\' prefix",
6757 if (Chunk[0] !=
'_')
6759 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
6766 bool IsDigitsError =
false;
6768 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
6772 IsDigitsError =
true;
6776 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
6780 IsDigitsError =
true;
6785 unsigned Row = RowChar -
'0';
6786 unsigned Col = ColChar -
'0';
6788 bool HasIndexingError =
false;
6789 if (IsZeroBasedAccessor) {
6791 if (!isZeroBasedIndex(Row)) {
6792 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6794 HasIndexingError =
true;
6796 if (!isZeroBasedIndex(Col)) {
6797 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6799 HasIndexingError =
true;
6803 if (!isOneBasedIndex(Row)) {
6804 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6806 HasIndexingError =
true;
6808 if (!isOneBasedIndex(Col)) {
6809 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
6811 HasIndexingError =
true;
6818 if (HasIndexingError)
6824 bool HasBoundsError =
false;
6826 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6828 HasBoundsError =
true;
6831 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
6833 HasBoundsError =
true;
6838 unsigned FlatIndex = Row * Cols + Col;
6839 if (Seen[FlatIndex])
6841 Seen[FlatIndex] =
true;
6844 if (NumComponents == 0 || NumComponents > 4) {
6845 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
6850 QualType ElemTy = MT->getElementType();
6851 if (NumComponents == 1)
6857 for (Sema::ExtVectorDeclsType::iterator
6861 if ((*I)->getUnderlyingType() == VT)
6872 trackLocalResource(VDecl,
Init);
6874 const HLSLVkConstantIdAttr *ConstIdAttr =
6875 VDecl->
getAttr<HLSLVkConstantIdAttr>();
6882 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
6892 int ConstantID = ConstIdAttr->getId();
6893 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
6895 ConstIdAttr->getLocation());
6899 if (
C->getType()->getCanonicalTypeUnqualified() !=
6903 Context.getTrivialTypeSourceInfo(
6904 Init->getType(),
Init->getExprLoc()),
6923 if (!Params || Params->
size() != 1)
6936 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
6937 if (TTP->hasDefaultArgument()) {
6938 TemplateArgs.
addArgument(TTP->getDefaultArgument());
6941 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
6942 if (NTTP->hasDefaultArgument()) {
6943 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
6946 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
6947 if (TTPD->hasDefaultArgument()) {
6948 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
6955 return SemaRef.CheckTemplateIdType(
6957 TemplateArgs,
nullptr,
false);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool containsIncompleteArrayType(QualType Ty)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static StringRef createRegisterString(ASTContext &AST, RegisterType RegType, unsigned N)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static QualType ReportMatrixInvalidMember(Sema &S, StringRef Name, StringRef Expected, SourceLocation OpLoc, SourceLocation CompLoc)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool CheckScalarFloatOperand(Sema &S, CallExpr *TheCall, unsigned ArgIndex)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckAnyScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool hasConstantBufferLayout(QualType QT)
llvm::dxbc::PSV::SemanticKind SemanticKind
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckIntegerElementTypeShaderModel(Sema &S, CallExpr *TheCall, QualType ContainedType, SampleKind Kind)
static bool isMatrixType(QualType QT)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckCalculateLodBuiltin(Sema &S, CallExpr *TheCall)
static QualType getScalarComponentType(QualType T)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckNoDoubleElementType(Sema &S, CallExpr *TheCall, QualType ContainedType, StringRef DefaultName)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static const Type * createHostLayoutType(Sema &S, const Type *Ty)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool CheckInterlockedBuiltin(Sema &S, CallExpr *TheCall, unsigned MinArgs, unsigned MaxArgs, InterlockedDest Dest, bool ReportsOriginalValue)
Check a call to an HLSL interlocked builtin.
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool CheckMatrixSelect(Sema *S, CallExpr *TheCall)
static bool CheckArgAddrSpaceOneOf(Sema *S, CallExpr *TheCall, unsigned ArgIndex, ArrayRef< LangAS > AllowedSpaces)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static StringRef getSampleMethodName(SampleKind Kind)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall)
static RegisterType getRegisterType(ResourceClass RC)
static bool ValidateRegisterNumber(uint64_t SlotNum, Decl *TheDecl, ASTContext &Ctx, RegisterType RegTy)
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static char getRegisterTypeChar(RegisterType RT)
static bool CheckNotBoolScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType getTypedResourceElementType(QualType ContainedType)
static bool findExistingMatrixLayoutMarker(QualType T, attr::Kind &ExistingKind)
Walks the existing AttributedType sugar of T looking for a previously applied HLSLRowMajor/HLSLColumn...
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckWavePrefix(Sema *S, CallExpr *TheCall)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static LangAS getLangASFromResourceClass(ResourceClass RC)
static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall, bool IncludeArraySlice=true)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static const Type * getHostLayoutFieldType(QualType QT)
InterlockedDest
The dest types an interlocked operation accepts. Float is 32-bit only.
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static QualType getVectorOrScalarType(Sema &S, QualType BaseType, unsigned Count)
static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind)
static bool CheckScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckFloatRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyDoubleRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
static StringRef getCurrentResourceMethodName(Sema &S, StringRef DefaultName)
static bool IsDefaultBufferConstantDecl(const ASTContext &Ctx, VarDecl *VD)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool CheckGatherBuiltin(Sema &S, CallExpr *TheCall, bool IsCmp)
static bool isValidWaveSizeValue(unsigned Value)
static bool isResourceRecordTypeOrArrayOf(QualType Ty)
static bool CheckLoadMSBuiltin(Sema &S, CallExpr *TheCall)
static bool AccumulateHLSLResourceSlots(QualType Ty, uint64_t &StartSlot, const uint64_t &Limit, const ResourceClass ResClass, ASTContext &Ctx, uint64_t ArrayCount=1)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns, std::optional< MatrixType::LayoutKind > Layout=std::nullopt) const
Return the unique reference to the matrix type of the specified element type and size.
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
llvm::StringRef backupStr(llvm::StringRef S) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getLocation() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
base_class_iterator bases_end()
void completeDefinition() override
Indicates that the definition of this class is now complete.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
bool isHLSLBuiltinRecord() const
Returns true if the class is a built-in HLSL record.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceLocation getEndLoc() const
static CanQual< Type > CreateUnsafe(QualType Other)
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
llvm::APInt getSize() const
Return the constant array size as an APInt.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
unsigned getNumRows() const
Returns the number of rows in the matrix.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
attr_iterator attr_end() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
attr_iterator attr_begin() const
DeclContext * getNonTransparentDeclContext()
Return the non transparent context.
bool isInvalidDecl() const
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 * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
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 handleInterpolationModifierAttr(Decl *D, const ParsedAttr &AL)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
uint32_t getNextImplicitBindingOrderID()
void CheckEntryPoint(FunctionDecl *FD)
void handleVkExtBuiltinOutputAttr(Decl *D, const ParsedAttr &AL)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)
bool initGlobalResourceDecl(VarDecl *VD)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
bool initGlobalResourceArrayDecl(VarDecl *VD)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
Attr * buildMatrixLayoutTypeAttr(QualType T, const ParsedAttr &AL)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool diagnoseIndexType(QualType T, const ParsedAttr &AL)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool ActOnResourceMemberAccessExpr(MemberExpr *ME)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
QualType ActOnTemplateShorthand(TemplateDecl *Template, SourceLocation NameLoc)
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
QualType checkMatrixComponent(Sema &S, QualType baseType, ExprValueKind &VK, SourceLocation OpLoc, const IdentifierInfo *CompName, SourceLocation CompLoc)
bool IsConstantBufferElementCompatible(QualType T1)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
bool ActOnUninitializedVarDecl(VarDecl *D)
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
bool canHaveOverloadedBinOp(QualType Ty, BinaryOperatorKind Opc)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
void handleVkPushConstantAttr(Decl *D, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
NamedDecl * getConstantBufferConversionFunction(QualType Type, CXXRecordDecl *RD)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional< unsigned > Index)
QualType getInoutParameterType(QualType Ty)
bool diagnoseFloatType(QualType T, const ParsedAttr &AL)
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
std::optional< ExprResult > tryPerformConstantBufferConversion(Expr *BaseExpr)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
bool diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T, SourceLocation Loc)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
bool CanPerformPackedTypeCast(Expr *Src, QualType DestTy)
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount)
Checks that a call expression's argument count is at most the desired number.
ExtVectorDeclsType ExtVectorDecls
ExtVectorDecls - This is a list all the extended vector types.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult TemporaryMaterializationConversion(Expr *E)
If E is a prvalue denoting an unmaterialized temporary, materialize it as an xvalue.
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExternalSemaSource * getExternalSource() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isHLSLBuiltinPackedType() const
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
void pushBaseName(llvm::StringRef N)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
Defines the clang::TargetInfo interface.
uint32_t getResourceDimensions(llvm::dxil::ResourceDimension Dim)
bool hasResourceOffset(llvm::dxil::ResourceDimension Dim)
bool hasCounterHandle(const CXXRecordDecl *RD)
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
@ Template
We are parsing a template declaration.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr, Expr *SampleCountExpr=nullptr)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
unsigned getImplicitOrderID() const
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
bool hasImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const