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));
1036 QualType
T = D == FD ? FD->getReturnType() : D->
getType();
1037 const ConstantArrayType *AT =
1040 Diag(A->getLoc(), diag::err_hlsl_semantic_zero_sized_array)
1041 << A->getAttrName();
1046 checkSemanticAnnotation(FD, D, A, SC, ElementCount);
1049 unsigned Location = ActiveSemantic.Index.value_or(0);
1052 any(SC.CurrentIOType & IOType::In))) {
1053 bool HasVkLocation =
false;
1054 if (
auto *A = D->
getAttr<HLSLVkLocationAttr>()) {
1055 HasVkLocation =
true;
1056 Location = A->getLocation();
1059 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1060 Diag(D->
getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1063 SC.UsesExplicitVkLocations = HasVkLocation;
1066 ActiveSemantic.Index = Location + ElementCount;
1068 StringRef BaseName = ActiveSemantic.Semantic->getAttrName()->getName();
1069 std::string LowerName = BaseName.lower();
1070 for (
unsigned I = 0; I < ElementCount; ++I) {
1071 auto [It, Inserted] = SC.ActiveSemantics.try_emplace(
1072 (Twine(LowerName) + Twine(Location + I)).str(), D->
getLocation());
1075 << (BaseName + Twine(Location + I)).str();
1076 Diag(It->second, diag::note_previous_use);
1084bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1087 SemanticInfo &ActiveSemantic,
1088 SemaHLSL::SemanticContext &SC) {
1089 if (ActiveSemantic.Semantic ==
nullptr) {
1090 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1091 if (ActiveSemantic.Semantic)
1092 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1098 const RecordType *RT = dyn_cast<RecordType>(
T);
1100 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1103 const RecordDecl *RD = RT->getDecl();
1104 for (FieldDecl *Field : RD->
fields()) {
1105 SemanticInfo Info = ActiveSemantic;
1106 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1107 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1110 if (ActiveSemantic.Semantic)
1111 ActiveSemantic = Info;
1118 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1119 assert(ShaderAttr &&
"Entry point has no shader attribute");
1120 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1124 case llvm::Triple::Pixel:
1125 case llvm::Triple::Vertex:
1126 case llvm::Triple::Geometry:
1127 case llvm::Triple::Hull:
1128 case llvm::Triple::Domain:
1129 case llvm::Triple::RayGeneration:
1130 case llvm::Triple::Intersection:
1131 case llvm::Triple::AnyHit:
1132 case llvm::Triple::ClosestHit:
1133 case llvm::Triple::Miss:
1134 case llvm::Triple::Callable:
1135 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1136 diagnoseAttrStageMismatch(NT, ST,
1137 {llvm::Triple::Compute,
1138 llvm::Triple::Amplification,
1139 llvm::Triple::Mesh});
1142 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1143 diagnoseAttrStageMismatch(WS, ST,
1144 {llvm::Triple::Compute,
1145 llvm::Triple::Amplification,
1146 llvm::Triple::Mesh});
1151 case llvm::Triple::Compute:
1152 case llvm::Triple::Amplification:
1153 case llvm::Triple::Mesh:
1154 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1156 << llvm::Triple::getEnvironmentTypeName(ST);
1159 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1161 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1162 }
else if (Ver < VersionTuple(6, 6)) {
1163 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1166 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1169 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1170 << WS << WS->getSpelledArgsCount() <<
"6.8";
1175 case llvm::Triple::RootSignature:
1176 llvm_unreachable(
"rootsig environment has no function entry point");
1178 llvm_unreachable(
"Unhandled environment in triple");
1181 SemaHLSL::SemanticContext InputSC = {};
1182 InputSC.CurrentIOType = IOType::In;
1183 SemaHLSL::SemanticContext OutputSC = {};
1184 OutputSC.CurrentIOType = IOType::Out;
1187 SemanticInfo ActiveSemantic;
1188 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1189 if (ActiveSemantic.Semantic)
1190 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1194 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1195 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1199 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1200 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1201 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1204 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1205 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1210 SemanticInfo ActiveSemantic;
1211 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1212 if (ActiveSemantic.Semantic)
1213 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1215 if (ST == llvm::Triple::Vertex &&
1216 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1218 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1222void SemaHLSL::checkSemanticAnnotation(
1224 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC,
1225 unsigned ElementCount) {
1226 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1227 assert(ShaderAttr &&
"Entry point has no shader attribute");
1228 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1231 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1232 llvm::hlsl::SemanticInterpretation Interpretation =
1233 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1234 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid) {
1235 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1241 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary) {
1242 diagnoseSemanticType(Param, SemanticAttr, SemanticKind::Arbitrary);
1246 diagnoseSystemSemanticIndex(SemanticAttr, Kind, ElementCount);
1247 diagnoseSemanticType(Param, SemanticAttr, Kind);
1250void SemaHLSL::diagnoseSystemSemanticIndex(
const HLSLAppliedSemanticAttr *A,
1252 unsigned ElementCount) {
1253 assert(Kind != SemanticKind::Invalid && Kind != SemanticKind::Arbitrary &&
1254 "expected a recognized system semantic");
1255 assert(ElementCount > 0 &&
"a semantic covers at least one element");
1258 uint32_t FirstIndex = A->getSemanticIndex();
1260 constexpr uint32_t MaxSemanticIndex = std::numeric_limits<uint32_t>::max();
1261 if (LastIndex > MaxSemanticIndex) {
1262 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1263 << A->getAttrName() << LastIndex << MaxSemanticIndex;
1271 case SemanticKind::ClipDistance:
1272 case SemanticKind::CullDistance:
1274 case SemanticKind::Target: {
1275 constexpr unsigned MaxTargetIndex = 7;
1276 if (LastIndex > MaxTargetIndex)
1277 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1278 << A->getAttrName() << LastIndex << MaxTargetIndex;
1282 Diag(A->getLoc(), diag::err_hlsl_semantic_indexing_not_supported)
1283 << A->getAttrName();
1290 return VT->getElementType();
1293 return MT->getElementType();
1299 return VT->getNumElements();
1320void SemaHLSL::diagnoseSemanticType(
const Decl *D,
1321 const HLSLAppliedSemanticAttr *A,
1323 assert(Kind != SemanticKind::Invalid &&
"expected a valid semantic");
1327 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
1333 T =
T.getNonReferenceType();
1336 QualType DeclaredTy =
T;
1338 T = AT->getElementType();
1346 case SemanticKind::DispatchThreadID:
1347 case SemanticKind::GroupID:
1348 case SemanticKind::GroupThreadID:
1350 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1351 << A->getAttrName() << 1 << 3
1354 case SemanticKind::GroupIndex:
1356 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1357 << A->getAttrName() << 0 << 1 << 1
1360 case SemanticKind::VertexID:
1362 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1363 << A->getAttrName() << 0 << 1
1366 case SemanticKind::Position:
1367 case SemanticKind::Target:
1369 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1370 << A->getAttrName() << 1 << 4
1373 case SemanticKind::InstanceID:
1379 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1380 << A->getAttrName() << 0 << 1
1382 (IsSPIRV ? 4 : 3) << DeclaredTy;
1395 Diag(A->getLoc(), diag::err_hlsl_semantic_64bit_type)
1396 << A->getAttrName() << DeclaredTy;
1399void SemaHLSL::diagnoseAttrStageMismatch(
1400 const Attr *A, llvm::Triple::EnvironmentType Stage,
1401 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1402 SmallVector<StringRef, 8> StageStrings;
1403 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1404 [](llvm::Triple::EnvironmentType ST) {
1406 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1408 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1409 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1410 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1413void SemaHLSL::diagnoseSemanticStageMismatch(
1414 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1417 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1418 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1419 return Info.Stage == Stage;
1422 StringRef CurrentIOTypeName =
"patch constants or primitives";
1423 if (
any(CurrentIOType & IOType::In))
1424 CurrentIOTypeName =
"inputs";
1425 else if (
any(CurrentIOType & IOType::Out))
1426 CurrentIOTypeName =
"outputs";
1429 if (It == Allowed.end()) {
1430 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1431 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1432 << CurrentIOTypeName;
1436 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1437 if (!(AllowedIOTypes & CurrentIOType)) {
1438 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1439 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1440 << CurrentIOTypeName;
1445template <CastKind Kind>
1448 Ty = VTy->getElementType();
1453template <CastKind Kind>
1465 if (LHSFloat && RHSFloat) {
1493 if (LHSSigned == RHSSigned) {
1494 if (IsCompAssign || IntOrder >= 0)
1502 if (IntOrder != (LHSSigned ? 1 : -1)) {
1503 if (IsCompAssign || RHSSigned)
1512 if (IsCompAssign || LHSSigned)
1539 return CK_FloatingCast;
1541 return CK_IntegralCast;
1543 return CK_IntegralToFloating;
1545 return CK_FloatingToIntegral;
1551 bool IsCompAssign) {
1558 if (!LVecTy && IsCompAssign) {
1560 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1562 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1564 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1569 unsigned EndSz = std::numeric_limits<unsigned>::max();
1572 LSz = EndSz = LVecTy->getNumElements();
1575 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1576 "one of the above should have had a value");
1580 if (IsCompAssign && LSz != EndSz) {
1582 diag::err_hlsl_vector_compound_assignment_truncation)
1583 << LHSType << RHSType;
1589 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1594 if (!IsCompAssign && !LVecTy)
1598 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1599 return Ctx.getCommonSugaredType(LHSType, RHSType);
1607 LElTy, RElTy, IsCompAssign);
1610 "HLSL Vectors can only contain integer or floating point types");
1612 LElTy, RElTy, IsCompAssign);
1617 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1618 "Called with non-logical operator");
1620 llvm::raw_svector_ostream OS(Buff);
1622 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1623 OS << NewFnName <<
"(";
1633std::pair<IdentifierInfo *, bool>
1636 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1643 return {DeclIdent,
Found};
1654 for (
auto &RootSigElement : RootElements)
1655 Elements.push_back(RootSigElement.getElement());
1659 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1661 SignatureDecl->setImplicit();
1667 if (RootSigOverrideIdent) {
1670 if (
SemaRef.LookupQualifiedName(R, DC))
1671 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1679struct PerVisibilityBindingChecker {
1682 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1686 llvm::dxbc::ShaderVisibility Vis;
1691 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1693 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1694 llvm::dxil::ResourceClass RC,
uint32_t Space,
1696 const hlsl::RootSignatureElement *Elem) {
1698 assert(BuilderIndex < Builders.size() &&
1699 "Not enough builders for visibility type");
1700 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1701 static_cast<const void *
>(Elem));
1703 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1704 "'All' visibility must come first");
1705 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1706 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1707 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1708 static_cast<const void *
>(Elem));
1710 ElemInfoMap.push_back({Elem,
Visibility,
false});
1713 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1714 auto It = llvm::lower_bound(
1716 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1717 assert(It->Elem == Elem &&
"Element not in map");
1721 bool checkOverlap() {
1722 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1723 return LHS.Elem < RHS.Elem;
1726 bool HadOverlap =
false;
1728 using llvm::hlsl::BindingInfoBuilder;
1729 auto ReportOverlap = [
this,
1730 &HadOverlap](
const BindingInfoBuilder &Builder,
1731 const llvm::hlsl::Binding &Reported) {
1735 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1736 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1737 const auto *PrevElem =
1738 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1740 ElemInfo &Info =
getInfo(Elem);
1745 Info.Diagnosed =
true;
1747 ElemInfo &PrevInfo =
getInfo(PrevElem);
1748 llvm::dxbc::ShaderVisibility CommonVis =
1749 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1752 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1753 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1754 << Reported.isUnbounded() << Reported.UpperBound
1759 this->S->
Diag(PrevElem->getLocation(),
1760 diag::note_hlsl_resource_range_here);
1763 for (BindingInfoBuilder &Builder : Builders)
1764 Builder.calculateBindingInfo(ReportOverlap);
1784 bool HadError =
false;
1785 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1786 uint32_t UpperBound) {
1788 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1789 << LowerBound << UpperBound;
1796 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1797 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1798 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1801 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1802 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1803 ReportError(Loc, 0, 0xfffffffe);
1806 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1807 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1808 ReportError(Loc, 0, 0xffffffef);
1811 const uint32_t Version =
1812 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1813 const uint32_t VersionEnum = Version - 1;
1814 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1816 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1823 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1824 if (
const auto *Descriptor =
1825 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1826 VerifyRegister(Loc, Descriptor->Reg.Number);
1827 VerifySpace(Loc, Descriptor->Space);
1829 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1831 ReportFlagError(Loc);
1832 }
else if (
const auto *Constants =
1833 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1834 VerifyRegister(Loc, Constants->Reg.Number);
1835 VerifySpace(Loc, Constants->Space);
1836 }
else if (
const auto *Sampler =
1837 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1838 VerifyRegister(Loc, Sampler->Reg.Number);
1839 VerifySpace(Loc, Sampler->Space);
1842 "By construction, parseFloatParam can't produce a NaN from a "
1843 "float_literal token");
1845 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1846 ReportError(Loc, 0, 16);
1847 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1848 ReportFloatError(Loc, -16.f, 15.99f);
1849 }
else if (
const auto *Clause =
1850 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1852 VerifyRegister(Loc, Clause->Reg.Number);
1853 VerifySpace(Loc, Clause->Space);
1855 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1859 ReportError(Loc, 1, 0xfffffffe);
1862 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1864 ReportFlagError(Loc);
1868 PerVisibilityBindingChecker BindingChecker(
this);
1869 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1874 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1875 if (
const auto *Descriptor =
1876 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1877 uint32_t LowerBound(Descriptor->Reg.Number);
1878 uint32_t UpperBound(LowerBound);
1880 BindingChecker.trackBinding(
1881 Descriptor->Visibility,
1882 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1883 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1884 }
else if (
const auto *Constants =
1885 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1886 uint32_t LowerBound(Constants->Reg.Number);
1887 uint32_t UpperBound(LowerBound);
1889 BindingChecker.trackBinding(
1890 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1891 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1892 }
else if (
const auto *Sampler =
1893 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1894 uint32_t LowerBound(Sampler->Reg.Number);
1895 uint32_t UpperBound(LowerBound);
1897 BindingChecker.trackBinding(
1898 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1899 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1900 }
else if (
const auto *Clause =
1901 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1904 UnboundClauses.emplace_back(Clause, &RootSigElem);
1905 }
else if (
const auto *Table =
1906 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1907 assert(UnboundClauses.size() == Table->NumClauses &&
1908 "Number of unbound elements must match the number of clauses");
1909 bool HasAnySampler =
false;
1910 bool HasAnyNonSampler =
false;
1911 uint64_t Offset = 0;
1912 bool IsPrevUnbound =
false;
1913 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1915 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1916 HasAnySampler =
true;
1918 HasAnyNonSampler =
true;
1920 if (HasAnySampler && HasAnyNonSampler)
1921 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1926 if (Clause->NumDescriptors == 0)
1930 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1932 Offset = Clause->Offset;
1934 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1935 Offset, Clause->NumDescriptors);
1937 if (IsPrevUnbound && IsAppending)
1938 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1939 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1940 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1943 Offset = RangeBound + 1;
1944 IsPrevUnbound = Clause->NumDescriptors ==
1945 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1948 uint32_t LowerBound(Clause->Reg.Number);
1949 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1950 LowerBound, Clause->NumDescriptors);
1952 BindingChecker.trackBinding(
1954 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1955 LowerBound, UpperBound, ClauseElem);
1957 UnboundClauses.clear();
1961 return BindingChecker.checkOverlap();
1966 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1971 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1972 if (RS->getSignatureIdent() != Ident) {
1973 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1977 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1983 if (
auto *SignatureDecl =
1984 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
1991 llvm::VersionTuple SMVersion =
1996 uint32_t ZMax = 1024;
1997 uint32_t ThreadMax = 1024;
1998 if (IsDXIL && SMVersion.getMajor() <= 4) {
2001 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
2011 diag::err_hlsl_numthreads_argument_oor)
2020 diag::err_hlsl_numthreads_argument_oor)
2029 diag::err_hlsl_numthreads_argument_oor)
2034 if (
X * Y * Z > ThreadMax) {
2035 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
2052 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
2060 if (SpelledArgsCount > 1 &&
2064 uint32_t Preferred = 0;
2065 if (SpelledArgsCount > 2 &&
2069 if (SpelledArgsCount > 2) {
2072 diag::err_attribute_power_of_two_in_range)
2073 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
2078 if (Preferred < Min || Preferred >
Max) {
2080 diag::err_attribute_power_of_two_in_range)
2081 << AL <<
Min <<
Max << Preferred;
2084 }
else if (SpelledArgsCount > 1) {
2087 diag::err_attribute_power_of_two_in_range)
2088 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
2092 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
2095 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
2100 diag::err_attribute_power_of_two_in_range)
2101 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
2106 HLSLWaveSizeAttr *NewAttr =
2143 uint32_t Binding = 0;
2165 uint32_t IndexValue(0), ExplicitIndex(0);
2168 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2170 assert(IndexValue > 0 ? ExplicitIndex :
true);
2173 if (Kind == SemanticKind::Invalid) {
2174 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2180 case SemanticKind::RenderTargetArrayIndex:
2181 case SemanticKind::ViewPortArrayIndex:
2182 case SemanticKind::ClipDistance:
2183 case SemanticKind::CullDistance:
2184 case SemanticKind::OutputControlPointID:
2185 case SemanticKind::DomainLocation:
2186 case SemanticKind::PrimitiveID:
2187 case SemanticKind::GSInstanceID:
2188 case SemanticKind::SampleIndex:
2189 case SemanticKind::IsFrontFace:
2190 case SemanticKind::Coverage:
2191 case SemanticKind::InnerCoverage:
2192 case SemanticKind::Depth:
2193 case SemanticKind::DepthLessEqual:
2194 case SemanticKind::DepthGreaterEqual:
2195 case SemanticKind::StencilRef:
2196 case SemanticKind::TessFactor:
2197 case SemanticKind::InsideTessFactor:
2198 case SemanticKind::ViewID:
2199 case SemanticKind::Barycentrics:
2200 case SemanticKind::ShadingRate:
2201 case SemanticKind::CullPrimitive:
2202 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2208 D->
addAttr(HLSLParsedSemanticAttr::Create(
2214 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2215 << AL <<
"shader constant in a constant buffer";
2219 uint32_t SubComponent;
2229 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2234 if (IsAggregateTy) {
2235 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2239 if ((Component * 32 + Size) > 128) {
2240 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2245 EltTy = VT->getElementType();
2247 if (Align > 32 && Component == 1) {
2250 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2264 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2267 llvm::Triple::EnvironmentType ShaderType;
2268 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2269 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2270 << AL << Str << ArgLoc;
2284 Expr *SampleCountExpr) {
2285 assert(AttrList.size() &&
"expected list of resource attributes");
2292 HLSLAttributedResourceType::Attributes ResAttrs;
2294 bool HasResourceClass =
false;
2295 bool HasResourceDimension =
false;
2296 for (
const Attr *A : AttrList) {
2301 case attr::HLSLResourceClass: {
2303 if (HasResourceClass) {
2305 ? diag::warn_duplicate_attribute_exact
2306 : diag::warn_duplicate_attribute)
2310 ResAttrs.ResourceClass = RC;
2311 HasResourceClass =
true;
2314 case attr::HLSLResourceDimension: {
2315 llvm::dxil::ResourceDimension RD =
2317 if (HasResourceDimension) {
2319 ? diag::warn_duplicate_attribute_exact
2320 : diag::warn_duplicate_attribute)
2324 ResAttrs.ResourceDimension = RD;
2325 HasResourceDimension =
true;
2328 case attr::HLSLIsROV:
2329 if (ResAttrs.IsROV) {
2333 ResAttrs.IsROV =
true;
2335 case attr::HLSLRawBuffer:
2336 if (ResAttrs.RawBuffer) {
2340 ResAttrs.RawBuffer =
true;
2342 case attr::HLSLIsArray:
2343 if (ResAttrs.IsArray) {
2347 ResAttrs.IsArray =
true;
2349 case attr::HLSLIsMultiSampled:
2350 if (ResAttrs.SampleCountExpr) {
2356 ResAttrs.SampleCountExpr =
2362 case attr::HLSLIsCounter:
2363 if (ResAttrs.IsCounter) {
2367 ResAttrs.IsCounter =
true;
2369 case attr::HLSLContainedType: {
2372 if (!ContainedTy.
isNull()) {
2374 ? diag::warn_duplicate_attribute_exact
2375 : diag::warn_duplicate_attribute)
2384 llvm_unreachable(
"unhandled resource attribute type");
2388 if (!HasResourceClass) {
2389 S.
Diag(AttrList.back()->getRange().getEnd(),
2390 diag::err_hlsl_missing_resource_class);
2395 Wrapped, ContainedTy, ResAttrs);
2397 if (LocInfo && ContainedTyInfo) {
2410 if (!
T->isHLSLResourceType()) {
2411 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2426 AttributeCommonInfo::AS_CXX11, 0, false ,
2431 case ParsedAttr::AT_HLSLResourceClass: {
2432 StringRef Identifier;
2434 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2439 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2440 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2441 <<
"ResourceClass" << Identifier;
2444 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2448 case ParsedAttr::AT_HLSLResourceDimension: {
2449 StringRef Identifier;
2451 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2455 llvm::dxil::ResourceDimension RD;
2456 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2458 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2459 <<
"ResourceDimension" << Identifier;
2462 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2466 case ParsedAttr::AT_HLSLIsROV:
2470 case ParsedAttr::AT_HLSLRawBuffer:
2474 case ParsedAttr::AT_HLSLIsCounter:
2478 case ParsedAttr::AT_HLSLIsArray:
2482 case ParsedAttr::AT_HLSLIsMultiSampled:
2486 case ParsedAttr::AT_HLSLContainedType: {
2488 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2494 assert(TSI &&
"no type source info for attribute argument");
2496 diag::err_incomplete_type))
2498 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2503 llvm_unreachable(
"unhandled HLSL attribute");
2506 HLSLResourcesTypeAttrs.emplace_back(A);
2512 if (!HLSLResourcesTypeAttrs.size())
2518 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2519 const HLSLAttributedResourceType *RT =
2526 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2528 HLSLResourcesTypeAttrs.clear();
2536 auto I = LocsForHLSLAttributedResources.find(RT);
2537 if (I != LocsForHLSLAttributedResources.end()) {
2538 LocInfo = I->second;
2539 LocsForHLSLAttributedResources.erase(I);
2548void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2549 const RecordType *RT) {
2557 "incomplete arrays inside user defined types are not supported");
2566 if (
const HLSLAttributedResourceType *AttrResType =
2567 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2572 Bindings.addDeclBindingInfo(VD, RC);
2573 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2579 collectResourceBindingsOnUserRecordDecl(VD, RT);
2591 bool SpecifiedSpace) {
2592 int RegTypeNum =
static_cast<int>(RegType);
2595 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2596 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2601 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2602 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2603 : ResourceClass::SRV;
2613 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2617 if (
const HLSLAttributedResourceType *AttrResType =
2618 HLSLAttributedResourceType::findHandleTypeOnResource(
2635 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2636 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2641 if (RegType == RegisterType::CBuffer)
2642 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2643 else if (RegType != RegisterType::C)
2644 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2648 if (RegType == RegisterType::C)
2649 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2651 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2661 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2669 bool RegisterTypesDetected[5] = {
false};
2670 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2673 if (HLSLResourceBindingAttr *
attr =
2674 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2677 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2678 int otherRegTypeNum =
static_cast<int>(otherRegType);
2680 diag::err_hlsl_duplicate_register_annotation)
2684 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2692 bool SpecifiedSpace) {
2697 "expecting VarDecl or HLSLBufferDecl");
2709 const uint64_t &Limit,
2712 uint64_t ArrayCount = 1) {
2717 if (StartSlot > Limit)
2721 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2724 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2725 Count = CAT->
getSize().getZExtValue();
2727 QualType ElemTy = AT->getElementType();
2729 ArrayCount * Count);
2733 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2736 if (ResTy->getAttrs().ResourceClass != ResClass)
2740 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2741 if (EndSlot > Limit)
2745 StartSlot = EndSlot + 1;
2750 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2753 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2756 ResClass, Ctx, ArrayCount))
2763 ResClass, Ctx, ArrayCount))
2777 const uint64_t Limit = UINT32_MAX;
2778 if (SlotNum > Limit)
2783 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2786 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2787 uint64_t BaseSlot = SlotNum;
2795 return (BaseSlot > Limit);
2802 return (SlotNum > Limit);
2805 llvm_unreachable(
"unexpected decl type");
2809 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2811 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2812 Ty = IAT->getElementType();
2814 diag::err_incomplete_type))
2818 StringRef Slot =
"";
2819 StringRef Space =
"";
2823 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2833 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2839 SpaceLoc = Loc->
getLoc();
2842 if (Str.starts_with(
"space")) {
2844 SpaceLoc = Loc->
getLoc();
2853 std::optional<unsigned> SlotNum;
2854 unsigned SpaceNum = 0;
2857 if (!Slot.empty()) {
2859 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2862 if (RegType == RegisterType::I) {
2863 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2866 const StringRef SlotNumStr = Slot.substr(1);
2871 if (SlotNumStr.getAsInteger(10, N)) {
2872 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2880 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2889 if (!Space.starts_with(
"space")) {
2890 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2893 StringRef SpaceNumStr = Space.substr(5);
2894 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2895 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2900 if (SlotNum.has_value())
2905 HLSLResourceBindingAttr *NewAttr =
2906 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2908 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2932 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2934 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2938 Cur = AT->getModifiedType();
2949 ? attr::HLSLRowMajor
2950 : attr::HLSLColumnMajor;
2954 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2963 if (ExistingKind == AttrK) {
2964 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2966 Diag(AL.
getLoc(), diag::note_previous_attribute);
2970 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2971 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
2973 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
2978 if (AttrK == attr::HLSLRowMajor)
2979 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
2980 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
2991 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
2993 if (
T.isNull() ||
T->isDependentType())
2998 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2999 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
3007using llvm::dxil::BarrierMemoryTypeFlag;
3008using llvm::dxil::BarrierSemanticFlag;
3010template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
3011 return llvm::to_underlying(Flag);
3025 bool DiagnoseAvailability;
3052 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
3056 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
3057 unsigned CurrentShaderStageBit;
3062 bool ReportOnlyShaderStageIssues;
3065 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
3066 static_assert(
sizeof(
unsigned) >= 4);
3067 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
3068 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
3069 "ShaderType is too big for this bitmap");
3072 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
3073 CurrentShaderEnvironment = ShaderType;
3074 CurrentShaderStageBit = (1 << bitmapIndex);
3077 void SetUnknownShaderStageContext() {
3078 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
3079 CurrentShaderStageBit = (1 << 31);
3082 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
3083 return CurrentShaderEnvironment;
3086 bool InUnknownShaderStageContext()
const {
3087 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
3091 void AddToScannedFunctions(
const FunctionDecl *FD) {
3092 unsigned &ScannedStages = ScannedDecls[FD];
3093 ScannedStages |= CurrentShaderStageBit;
3096 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
3098 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
3099 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
3102 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
3103 return ScannerStages & CurrentShaderStageBit;
3106 static bool NeverBeenScanned(
unsigned ScannedStages) {
3107 return ScannedStages == 0;
3111 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3112 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3114 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3115 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3116 void DiagnoseBarrierCall(CallExpr *CE);
3117 uint64_t DiagnoseBarrierGroupMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3118 bool HasVisibleGroup,
bool IsAllMemory);
3119 uint64_t DiagnoseBarrierNodeMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3120 bool HasKnownStage,
bool IsAllMemory);
3121 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg, uint64_t SemanticFlags,
3122 bool HasVisibleGroup);
3123 void DiagnoseBarrierScope(Expr *SemanticArg, uint64_t MemoryFlags,
3124 uint64_t SemanticFlags);
3127 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3128 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3129 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3130 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3133 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3134 void RunOnFunction(
const FunctionDecl *FD);
3136 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3137 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3139 HandleFunctionOrMethodRef(FD, DRE);
3143 bool VisitMemberExpr(MemberExpr *ME)
override {
3144 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3146 HandleFunctionOrMethodRef(FD, ME);
3150 bool VisitCallExpr(CallExpr *CE)
override {
3151 DiagnoseBarrierCall(CE);
3156uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3157 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasVisibleGroup,
3160 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3161 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3166 diag::err_hlsl_barrier_flag_requires_group)
3171 return MemoryFlags & ~GroupSharedMemory;
3174uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3175 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasKnownStage,
3178 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3179 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3184 diag::err_hlsl_barrier_node_memory_requires_node);
3188 return MemoryFlags & ~NodeMemory;
3191void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3192 Expr *SemanticArg, uint64_t SemanticFlags,
bool HasVisibleGroup) {
3193 if (HasVisibleGroup ||
3194 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3198 diag::err_hlsl_barrier_flag_requires_group)
3199 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3205void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3206 uint64_t MemoryFlags,
3207 uint64_t SemanticFlags) {
3208 if (ReportOnlyShaderStageIssues)
3212 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3213 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3214 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3216 (MemoryFlags & DeviceScopeMemory) == 0)
3218 diag::err_hlsl_barrier_scope_requires_memory)
3220 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3224 diag::err_hlsl_barrier_scope_requires_memory)
3228void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3230 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3233 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3234 const bool HasKnownStage = !InUnknownShaderStageContext();
3235 const bool HasVisibleGroup =
3236 !HasKnownStage || Stage == llvm::Triple::Compute ||
3237 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3239 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3242 std::optional<llvm::APSInt>
Value =
3246 MemoryFlags =
Value->getZExtValue();
3247 const bool IsAllMemory =
3248 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3250 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3251 HasVisibleGroup, IsAllMemory);
3252 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3253 HasKnownStage, IsAllMemory);
3254 }
else if (!HasVisibleGroup) {
3256 diag::err_hlsl_barrier_resource_requires_group);
3261 std::optional<llvm::APSInt>
Value =
3267 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3270 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3273void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3276 "expected DeclRefExpr or MemberExpr");
3278 if (DiagnoseAvailability)
3279 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3280 CheckDeclAvailability(
3285 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3286 DeclsToScan.push_back(FDWithBody);
3289void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3294 llvm::Triple::EnvironmentType::Library;
3303 DeclContextsToScan.push_back(TU);
3305 while (!DeclContextsToScan.empty()) {
3306 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3307 for (
auto &D : DC->
decls()) {
3314 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3315 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3320 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3325 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3326 if (!IsLibraryShader && FD->
getName() == EntryName) {
3329 diag::err_hlsl_ambiguous_entry_point)
3331 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3337 SetShaderStageContext(ShaderAttr->getType());
3346 for (
const auto *Redecl : FD->
redecls()) {
3347 if (Redecl->isInExportDeclContext()) {
3354 SetUnknownShaderStageContext();
3361 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3368void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3369 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3370 DeclsToScan.push_back(FD);
3372 while (!DeclsToScan.empty()) {
3380 const unsigned ScannedStages = GetScannedStages(FD);
3381 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3384 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3386 AddToScannedFunctions(FD);
3391bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3392 const AvailabilityAttr *AA) {
3397 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3398 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3401 llvm::Triple::EnvironmentType AttrEnv =
3402 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3404 return CurrentEnv == AttrEnv;
3407const AvailabilityAttr *
3408DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3409 AvailabilityAttr
const *PartialMatch =
nullptr;
3413 for (
const auto *A : D->
attrs()) {
3414 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3415 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3416 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3417 StringRef TargetPlatform =
3421 if (AttrPlatform == TargetPlatform) {
3423 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3425 PartialMatch = Avail;
3429 return PartialMatch;
3434void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3435 const AvailabilityAttr *AA,
3454 if (ReportOnlyShaderStageIssues)
3460 if (InUnknownShaderStageContext())
3465 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3466 VersionTuple Introduced = AA->getIntroduced();
3475 llvm::StringRef PlatformName(
3478 llvm::StringRef CurrentEnvStr =
3479 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3481 llvm::StringRef AttrEnvStr =
3482 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3483 bool UseEnvironment = !AttrEnvStr.empty();
3485 if (EnvironmentMatches) {
3486 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3487 <<
Range << D << PlatformName << Introduced.getAsString()
3488 << UseEnvironment << CurrentEnvStr;
3490 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3494 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3495 << D << PlatformName << Introduced.getAsString()
3497 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3504 if (!DefaultCBufferDecls.empty()) {
3507 DefaultCBufferDecls);
3510 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3514 for (
const Decl *VD : DefaultCBufferDecls) {
3515 const HLSLResourceBindingAttr *RBA =
3516 VD->
getAttr<HLSLResourceBindingAttr>();
3517 if (RBA && RBA->hasRegisterSlot() &&
3518 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3525 SemaRef.Consumer.HandleTopLevelDecl(DG);
3527 diagnoseAvailabilityViolations(TU);
3536 "expected member expr to have resource record type or array of them");
3542 const Expr *NonConstIndexExpr =
nullptr;
3545 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3546 if (!NonConstIndexExpr)
3554 diag::err_hlsl_resource_member_array_access_not_constant);
3558 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3559 const Expr *IdxExpr = ASE->getIdx();
3561 NonConstIndexExpr = IdxExpr;
3563 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3564 E = SubME->getBase();
3565 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3566 E = ICE->getSubExpr();
3568 llvm_unreachable(
"unexpected expr type in resource member access");
3577 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3580 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3583 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3587 [[maybe_unused]]
bool LookupSucceeded =
3588 SemaRef.LookupQualifiedName(ConvR, RD);
3589 assert(LookupSucceeded);
3598std::optional<ExprResult>
3601 const HLSLAttributedResourceType *ResTy =
3602 HLSLAttributedResourceType::findHandleTypeOnResource(
3603 BaseType.getTypePtr());
3605 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3606 return std::nullopt;
3608 QualType TemplateType = ResTy->getContainedType();
3612 assert(NamedConversionDecl &&
3613 "Could not find conversion function for ConstantBuffer.");
3614 auto *ConversionDecl =
3617 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3627 const bool DiagnoseAvailability =
3629 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3630 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3631 .RunOnTranslationUnit(TU);
3638 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3641 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3666 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3679 if (!BaseType->isFloat32Type())
3680 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3681 << ArgOrdinal << 5 << 0
3691 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3692 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3693 << ArgOrdinal << 5 << 0
3702 if (!BaseType->isDoubleType()) {
3705 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3706 << ArgOrdinal << PassedType;
3713 unsigned ArgIndex) {
3714 auto *Arg = TheCall->
getArg(ArgIndex);
3716 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3719 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3733 << (ArgIndex + 1) << LValueTy;
3743 if (VecTy->getElementType()->isDoubleType())
3744 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3745 << ArgOrdinal << 1 << 0 << 1
3755 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3756 << ArgOrdinal << 5 << 1
3765 if (VecTy->getElementType()->isUnsignedIntegerType())
3768 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3769 << ArgOrdinal << 4 << 3 << 0
3778 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3779 << ArgOrdinal << 5 << 3
3785 unsigned ArgOrdinal,
unsigned Width) {
3788 ArgTy = VTy->getElementType();
3790 uint64_t ElementBitCount =
3792 if (ElementBitCount != Width) {
3794 diag::err_integer_incorrect_bit_count)
3795 << Width << ElementBitCount;
3806 else if (
auto *MatTyA =
3809 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3815 unsigned ArgIndex) {
3824 diag::err_typecheck_expect_scalar_or_vector)
3825 << ArgType << Scalar;
3832 QualType Scalar,
unsigned ArgIndex) {
3843 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3856 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3857 << ArgType << Scalar;
3862 unsigned ArgIndex) {
3867 if (!(ArgType->isScalarType() ||
3868 (VTy && VTy->getElementType()->isScalarType()))) {
3870 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3878 unsigned ArgIndex) {
3881 if (ArgType->isDependentType())
3885 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3886 ElementType = VectorTy->getElementType();
3888 ElementType = MatrixTy->getElementType();
3890 if (ElementType->isBooleanType())
3893 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3895 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3900 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3908 unsigned ArgIndex) {
3910 assert(ArgIndex < TheCall->getNumArgs());
3918 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3943 diag::err_typecheck_call_different_arg_types)
3962 Arg1ScalarTy = VTy->getElementType();
3966 Arg2ScalarTy = VTy->getElementType();
3969 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3970 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
3980 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3982 diag::err_typecheck_vector_lengths_not_equal)
3988 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3990 diag::err_typecheck_vector_lengths_not_equal)
4010 Arg1ScalarTy = MTy->getElementType();
4014 Arg2ScalarTy = MTy->getElementType();
4017 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4018 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4023 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
4025 for (
Expr *Arg : {Arg1, Arg2}) {
4028 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
4030 diag::err_typecheck_vector_lengths_not_equal)
4032 << Arg->getSourceRange();
4048 unsigned ArgIndex) {
4053 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
4056 unsigned int ActualDim = 1;
4058 ActualDim = VTy->getNumElements();
4059 IndexTy = VTy->getElementType();
4063 diag::err_typecheck_expect_int)
4069 const HLSLAttributedResourceType *ResTy =
4071 assert(ResTy &&
"Resource argument must be a resource");
4072 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
4074 unsigned int ExpectedDim = 1;
4075 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
4077 (ResAttrs.IsArray ? 1 : 0);
4079 if (ActualDim != ExpectedDim) {
4081 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
4092 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
4096 const HLSLAttributedResourceType *ResTy =
4100 diag::err_typecheck_expect_hlsl_resource)
4104 if (Check && Check(ResTy)) {
4106 diag::err_invalid_hlsl_resource_type)
4116 "expected resource handle type");
4117 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4118 auto MainAttrs = MainResType->getAttrs();
4119 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4120 MainAttrs.IsCounter =
true;
4122 MainResType->getContainedType(),
4133 return "SampleBias";
4135 return "SampleGrad";
4137 return "SampleLevel";
4141 return "SampleCmpLevelZero";
4143 llvm_unreachable(
"Invalid SampleKind");
4153 if (!MD || !MD->getDeclName().isIdentifier())
4160 return MD->getName();
4168 StringRef DefaultName) {
4173 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4200 if (SMVersion >= VersionTuple(6, 7))
4203 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4205 << ContainedType << SMVersion.getAsString();
4210 bool IncludeArraySlice =
true) {
4213 [](
const HLSLAttributedResourceType *ResType) {
4214 return ResType->getAttrs().ResourceDimension ==
4215 llvm::dxil::ResourceDimension::Unknown;
4221 [](
const HLSLAttributedResourceType *ResType) {
4222 return ResType->getAttrs().ResourceClass !=
4223 llvm::hlsl::ResourceClass::Sampler;
4231 unsigned ExpectedDim =
4233 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4262 unsigned NextIdx = 3;
4274 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4278 std::optional<llvm::APSInt> ComponentOpt =
4281 int64_t ComponentVal = ComponentOpt->getSExtValue();
4282 if (ComponentVal != 0) {
4285 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4286 "The component is not in the expected range.");
4288 diag::err_hlsl_gathercmp_invalid_component)
4298 const HLSLAttributedResourceType *ResourceTy =
4301 unsigned ExpectedDim =
4304 &S, TheCall->
getArg(NextIdx),
4310 assert(ResourceTy->hasContainedType() &&
4311 "Expecting a contained type for resource with a dimension "
4313 QualType ReturnType = ResourceTy->getContainedType();
4316 IsCmp ?
"GatherCmp" :
"Gather"))
4321 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4327 ReturnType = VecTy->getElementType();
4340 [](
const HLSLAttributedResourceType *ResType) {
4341 return ResType->getAttrs().ResourceDimension ==
4342 llvm::dxil::ResourceDimension::Unknown;
4352 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4359 unsigned ResourceDim =
4361 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4377 TheCall->
setType(ResourceTy->getContainedType());
4387 [](
const HLSLAttributedResourceType *ResType) {
4388 return !ResType->isMultiSampled();
4397 unsigned ResourceDim =
4399 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4417 TheCall->
setType(ResourceTy->getContainedType());
4422 unsigned MinArgs, MaxArgs;
4450 const HLSLAttributedResourceType *ResourceTy =
4452 unsigned ExpectedDim =
4455 unsigned NextIdx = 3;
4480 &S, TheCall->
getArg(NextIdx),
4493 assert(ResourceTy->hasContainedType() &&
4494 "Expecting a contained type for resource with a dimension "
4496 QualType ReturnType = ResourceTy->getContainedType();
4507 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4524 unsigned MinArgs,
unsigned MaxArgs,
4526 bool ReportsOriginalValue) {
4527 if (MinArgs == MaxArgs) {
4530 }
else if (TheCall->
getNumArgs() < MinArgs) {
4531 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4541 const bool DestIsOK =
4547 diag::err_builtin_invalid_arg_type)
4561 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4577 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4583 const unsigned NumArgs = TheCall->
getNumArgs();
4584 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4595 switch (BuiltinID) {
4596 case Builtin::BI__builtin_hlsl_barrier: {
4597 if (
SemaRef.checkArgCount(TheCall, 2))
4600 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4601 llvm::Triple::dxil) {
4609 std::optional<llvm::APSInt> MemoryFlags =
4613 diag::err_constant_integer_arg_type)
4617 if ((MemoryFlags->getZExtValue() &
4618 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4620 diag::err_hlsl_invalid_barrier_memory_flags);
4624 const HLSLAttributedResourceType *ResTy =
4625 HLSLAttributedResourceType::findHandleTypeOnResource(
4629 diag::err_typecheck_expect_hlsl_resource)
4633 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4635 diag::err_invalid_hlsl_resource_type)
4642 std::optional<llvm::APSInt> SemanticFlags =
4644 if (!SemanticFlags) {
4646 diag::err_constant_integer_arg_type)
4650 if ((SemanticFlags->getZExtValue() &
4651 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4653 diag::err_hlsl_invalid_barrier_semantic_flags);
4660 case Builtin::BI__builtin_hlsl_adduint64: {
4661 if (
SemaRef.checkArgCount(TheCall, 2))
4675 if (NumElementsArg != 2 && NumElementsArg != 4) {
4677 << 1 << 64 << NumElementsArg * 32;
4691 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4692 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4699 QualType ContainedTy = ResourceTy->getContainedType();
4700 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4703 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4708 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4709 if (
SemaRef.checkArgCount(TheCall, 3) ||
4716 "expected pointer type for second argument");
4723 diag::err_invalid_use_of_array_type);
4727 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4730 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4735 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4736 if (
SemaRef.checkArgCount(TheCall, 2) ||
4738 SemaRef.getASTContext().IntTy))
4745 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4746 if (
SemaRef.checkArgCount(TheCall, 3) ||
4749 SemaRef.getASTContext().UnsignedIntTy) ||
4751 SemaRef.getASTContext().UnsignedIntTy) ||
4757 QualType ReturnType = ResourceTy->getContainedType();
4762 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4763 if (
SemaRef.checkArgCount(TheCall, 4) ||
4766 SemaRef.getASTContext().UnsignedIntTy) ||
4768 SemaRef.getASTContext().UnsignedIntTy) ||
4774 "expected pointer type for second argument");
4781 diag::err_invalid_use_of_array_type);
4787 case Builtin::BI__builtin_hlsl_resource_load_level:
4789 case Builtin::BI__builtin_hlsl_resource_load_ms:
4791 case Builtin::BI__builtin_hlsl_resource_sample:
4793 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4795 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4797 case Builtin::BI__builtin_hlsl_resource_sample_level:
4799 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4801 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4803 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4804 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4806 case Builtin::BI__builtin_hlsl_resource_gather:
4808 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4810 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4811 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4817 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4818 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4824 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4825 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4831 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4832 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4838 TheCall->
setType(CounterHandleTy);
4841 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4842 if (
SemaRef.checkArgCount(TheCall, 2) ||
4845 SemaRef.getASTContext().UnsignedIntTy))
4853 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4854 if (
SemaRef.checkArgCount(TheCall, 1) ||
4862 TheCall->
setType(CounterHandleTy);
4865 case Builtin::BI__builtin_hlsl_and:
4866 case Builtin::BI__builtin_hlsl_or: {
4867 if (
SemaRef.checkArgCount(TheCall, 2))
4881 case Builtin::BI__builtin_hlsl_all:
4882 case Builtin::BI__builtin_hlsl_any: {
4883 if (
SemaRef.checkArgCount(TheCall, 1))
4889 case Builtin::BI__builtin_hlsl_asdouble: {
4890 if (
SemaRef.checkArgCount(TheCall, 2))
4894 SemaRef.Context.UnsignedIntTy,
4899 SemaRef.Context.UnsignedIntTy,
4908 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4909 if (
SemaRef.BuiltinElementwiseTernaryMath(
4915 case Builtin::BI__builtin_hlsl_dot: {
4917 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4923 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4924 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4925 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4935 EltTy = VecTy->getElementType();
4936 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4949 case Builtin::BI__builtin_hlsl_select: {
4950 if (
SemaRef.checkArgCount(TheCall, 3))
4959 if (VTy && VTy->getElementType()->isBooleanType() &&
4963 if (MTy && MTy->getElementType()->isBooleanType() &&
4968 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4969 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4970 if (
SemaRef.checkArgCount(TheCall, 1))
4976 diag::err_builtin_invalid_arg_type)
4979 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4983 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
4984 case Builtin::BI__builtin_hlsl_elementwise_frac:
4985 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
4986 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
4987 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
4988 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
4989 if (
SemaRef.checkArgCount(TheCall, 1))
4994 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4998 case Builtin::BI__builtin_hlsl_elementwise_isfinite:
4999 case Builtin::BI__builtin_hlsl_elementwise_isinf:
5000 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
5001 if (
SemaRef.checkArgCount(TheCall, 1))
5006 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5011 case Builtin::BI__builtin_hlsl_mad: {
5012 if (
SemaRef.BuiltinElementwiseTernaryMath(
5018 case Builtin::BI__builtin_hlsl_mul: {
5019 if (
SemaRef.checkArgCount(TheCall, 2))
5029 return VTy->getElementType();
5031 return MTy->getElementType();
5035 QualType EltTy0 = getElemType(Ty0);
5044 if (IsVec0 && IsMat1) {
5047 }
else if (IsMat0 && IsVec1) {
5051 assert(IsMat0 && IsMat1);
5061 case Builtin::BI__builtin_elementwise_fma: {
5062 if (
SemaRef.checkArgCount(TheCall, 3) ||
5077 case Builtin::BI__builtin_hlsl_transpose: {
5078 if (
SemaRef.checkArgCount(TheCall, 1))
5087 << 1 << 3 << 0 << 0 << ArgTy;
5092 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
5096 case Builtin::BI__builtin_hlsl_elementwise_sign: {
5097 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5105 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5106 if (
SemaRef.checkArgCount(TheCall, 1))
5120 unsigned NumElts = VecTy->getNumElements();
5130 case Builtin::BI__builtin_hlsl_wave_active_max:
5131 case Builtin::BI__builtin_hlsl_wave_active_min:
5132 case Builtin::BI__builtin_hlsl_wave_active_sum:
5133 case Builtin::BI__builtin_hlsl_wave_active_product: {
5134 if (
SemaRef.checkArgCount(TheCall, 1))
5147 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5148 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5149 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5150 if (
SemaRef.checkArgCount(TheCall, 1))
5165 (VTy && VTy->getElementType()->isIntegerType()))) {
5167 diag::err_builtin_invalid_arg_type)
5168 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5176 case Builtin::BI__builtin_hlsl_interlocked_add:
5177 case Builtin::BI__builtin_hlsl_interlocked_and:
5178 case Builtin::BI__builtin_hlsl_interlocked_max:
5179 case Builtin::BI__builtin_hlsl_interlocked_min:
5180 case Builtin::BI__builtin_hlsl_interlocked_or:
5181 case Builtin::BI__builtin_hlsl_interlocked_xor:
5187 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5193 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5199 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5205 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5211 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5219 case Builtin::BI__builtin_elementwise_bitreverse: {
5227 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
5228 if (
SemaRef.checkArgCount(TheCall, 1))
5233 if (!(
ArgType->isScalarType())) {
5235 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5240 if (!(
ArgType->isBooleanType())) {
5242 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5249 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5250 if (
SemaRef.checkArgCount(TheCall, 2))
5258 diag::err_typecheck_convert_incompatible)
5259 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5272 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5273 if (
SemaRef.checkArgCount(TheCall, 1))
5282 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5283 if (
SemaRef.checkArgCount(TheCall, 0))
5287 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5288 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5289 if (
SemaRef.checkArgCount(TheCall, 1))
5302 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5303 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5304 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5305 if (
SemaRef.checkArgCount(TheCall, 1))
5317 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5318 if (
SemaRef.checkArgCount(TheCall, 3))
5324 SemaRef.Context.UnsignedIntTy, 1) ||
5326 SemaRef.Context.UnsignedIntTy, 2))
5334 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5335 if (
SemaRef.checkArgCount(TheCall, 1))
5342 case Builtin::BI__builtin_elementwise_acos:
5343 case Builtin::BI__builtin_elementwise_asin:
5344 case Builtin::BI__builtin_elementwise_atan:
5345 case Builtin::BI__builtin_elementwise_atan2:
5346 case Builtin::BI__builtin_elementwise_ceil:
5347 case Builtin::BI__builtin_elementwise_cos:
5348 case Builtin::BI__builtin_elementwise_cosh:
5349 case Builtin::BI__builtin_elementwise_exp:
5350 case Builtin::BI__builtin_elementwise_exp2:
5351 case Builtin::BI__builtin_elementwise_exp10:
5352 case Builtin::BI__builtin_elementwise_floor:
5353 case Builtin::BI__builtin_elementwise_fmod:
5354 case Builtin::BI__builtin_elementwise_log:
5355 case Builtin::BI__builtin_elementwise_log2:
5356 case Builtin::BI__builtin_elementwise_log10:
5357 case Builtin::BI__builtin_elementwise_pow:
5358 case Builtin::BI__builtin_elementwise_roundeven:
5359 case Builtin::BI__builtin_elementwise_sin:
5360 case Builtin::BI__builtin_elementwise_sinh:
5361 case Builtin::BI__builtin_elementwise_sqrt:
5362 case Builtin::BI__builtin_elementwise_tan:
5363 case Builtin::BI__builtin_elementwise_tanh:
5364 case Builtin::BI__builtin_elementwise_trunc: {
5370 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5371 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5372 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5373 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5374 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5379 std::optional<llvm::APSInt> Offset =
5381 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5383 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5389 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5390 if (
SemaRef.checkArgCount(TheCall, 1))
5401 ArgTy = VTy->getElementType();
5404 diag::err_builtin_invalid_arg_type)
5413 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5414 if (
SemaRef.checkArgCount(TheCall, 1))
5429 WorkList.push_back(BaseTy);
5430 while (!WorkList.empty()) {
5432 T =
T.getCanonicalType().getUnqualifiedType();
5433 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5441 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5442 llvm::append_range(List, ElementFields);
5447 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5448 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5451 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5452 List.insert(List.end(), MT->getNumElementsFlattened(),
5453 MT->getElementType());
5456 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5457 if (RD->isStandardLayout())
5458 RD = RD->getStandardLayoutBaseWithFields();
5462 if (RD->
isUnion() || !RD->isAggregate()) {
5468 for (
const auto *FD : RD->
fields())
5469 if (!FD->isUnnamedBitField())
5470 FieldTypes.push_back(FD->
getType());
5472 std::reverse(FieldTypes.begin(), FieldTypes.end());
5473 llvm::append_range(WorkList, FieldTypes);
5477 if (!RD->isStandardLayout()) {
5479 for (
const auto &
Base : RD->bases())
5480 FieldTypes.push_back(
Base.getType());
5481 std::reverse(FieldTypes.begin(), FieldTypes.end());
5482 llvm::append_range(WorkList, FieldTypes);
5517 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5523 int ArraySize = VT->getNumElements();
5528 QualType ElTy = VT->getElementType();
5532 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5548 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5557 return llvm::equal(T1Types, T2Types,
5559 return SemaRef.IsLayoutCompatible(LHS, RHS);
5568 bool HadError =
false;
5570 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5578 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5579 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5580 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5581 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5583 if (NSpellingIdx != OSpellingIdx) {
5585 diag::err_hlsl_param_qualifier_mismatch)
5586 << NDAttr << NewParam;
5602 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5617 llvm_unreachable(
"HLSL doesn't support pointers.");
5620 llvm_unreachable(
"HLSL doesn't support complex types.");
5622 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5624 llvm_unreachable(
"Should have returned before this");
5634 llvm_unreachable(
"HLSL doesn't support complex types.");
5636 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5641 llvm_unreachable(
"HLSL doesn't support pointers.");
5643 llvm_unreachable(
"Should have returned before this");
5649 llvm_unreachable(
"HLSL doesn't support pointers.");
5652 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5656 llvm_unreachable(
"HLSL doesn't support complex types.");
5659 llvm_unreachable(
"Unhandled scalar cast");
5680 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5686 SrcTy = SrcMatTy->getElementType();
5691 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5692 if (DestTypes[I]->isUnionType())
5724 if (SrcTypes.size() < DestTypes.size())
5727 unsigned SrcSize = SrcTypes.size();
5728 unsigned DstSize = DestTypes.size();
5730 for (I = 0; I < DstSize && I < SrcSize; I++) {
5731 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5739 for (; I < SrcSize; I++) {
5740 if (SrcTypes[I]->isUnionType())
5760 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5761 "We should not get here without a parameter modifier expression");
5762 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5769 << Arg << (IsInOut ? 1 : 0);
5775 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5782 << Arg << (IsInOut ? 1 : 0);
5794 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
5800 auto *OpV =
new (Ctx)
5806 tok::equal, ArgOpV, OpV);
5822 "Pointer and reference types cannot be inout or out parameters");
5823 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5839 for (
const auto *FD : RD->
fields()) {
5843 assert(RD->getNumBases() <= 1 &&
5844 "HLSL doesn't support multiple inheritance");
5845 return RD->getNumBases()
5850 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5851 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5863 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5868 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5874 if (
Decl->getType().hasAddressSpace())
5877 if (
Decl->getType()->isDependentType())
5889 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5903 llvm::Triple::Vulkan;
5904 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5905 if (HasDeclaredAPushConstant)
5911 HasDeclaredAPushConstant =
true;
5938class StructBindingContext {
5941 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5942 unsigned RegBindingOffset[4];
5945 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5946 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5947 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5948 static_cast<unsigned>(RegisterType::Sampler) == 3,
5949 "unexpected register type values");
5952 HLSLVkBindingAttr *VkBindingAttr;
5953 unsigned VkBindingOffset;
5958 StructBindingContext(
VarDecl *VD) {
5959 for (
unsigned i = 0; i < 4; ++i) {
5960 RegBindingsAttrs[i] =
nullptr;
5961 RegBindingOffset[i] = 0;
5963 VkBindingAttr =
nullptr;
5964 VkBindingOffset = 0;
5970 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
5972 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
5975 RegBindingsAttrs[RegTypeIdx] = RBA;
5980 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
5981 VkBindingAttr = VBA;
5988 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
5989 unsigned Range,
bool HasCounter) {
5990 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
5992 if (VkBindingAttr) {
5993 unsigned Offset = VkBindingOffset;
5994 VkBindingOffset +=
Range;
5995 return HLSLVkBindingAttr::CreateImplicit(
5996 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
5997 VkBindingAttr->getRange());
6000 HLSLResourceBindingAttr *RBA =
6001 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6002 HLSLResourceBindingAttr *NewAttr =
nullptr;
6004 if (RBA && RBA->hasRegisterSlot()) {
6007 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6008 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6010 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6011 StringRef NewSlotNumberStr =
6013 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6014 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6015 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6019 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6020 NewAttr->setBinding(RegType, std::nullopt,
6021 RBA ? RBA->getSpaceNumber() : 0);
6025 NewAttr->setImplicitCounterBindingOrderID(
6034static void createGlobalResourceDeclForStruct(
6036 QualType ResTy, StructBindingContext &BindingCtx) {
6038 "expected resource type or array of resources");
6049 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6050 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6055 const HLSLAttributedResourceType *ResHandleTy =
6056 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6060 Attr *BindingAttr = BindingCtx.createBindingAttr(
6062 ResDecl->
addAttr(BindingAttr);
6063 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6072 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6079static void handleArrayOfStructWithResources(
6081 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6086static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6088 EmbeddedResourceNameBuilder &NameBuilder,
6089 StructBindingContext &BindingCtx) {
6092 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6099 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6113 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6116 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6118 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6120 "resource arrays should have been already handled");
6121 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6130handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6132 EmbeddedResourceNameBuilder &NameBuilder,
6133 StructBindingContext &BindingCtx) {
6141 if (!SubCAT && !ElementRD)
6144 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6147 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6150 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6163void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6164 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6165 StructBindingContext BindingCtx(VD);
6169 "Expected non-resource struct or array type");
6172 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6176 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6177 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6185 if (
SemaRef.RequireCompleteType(
6188 diag::err_typecheck_decl_incomplete_type)) {
6202 DefaultCBufferDecls.push_back(VD);
6207 collectResourceBindingsOnVarDecl(VD);
6209 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6221 processExplicitBindingsOnDecl(VD);
6259 handleGlobalStructOrArrayOfWithResources(VD);
6263 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6272 "expected resource record type");
6288 const char *CreateMethodName;
6290 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6291 :
"__createFromBinding";
6293 CreateMethodName = HasCounter
6294 ?
"__createFromImplicitBindingWithImplicitCounter"
6295 :
"__createFromImplicitBinding";
6300 if (!CreateMethod) {
6305 "create method lookup should always succeed for built-in resource "
6314 Args.push_back(RegSlot);
6322 Args.push_back(OrderId);
6328 Args.push_back(Space);
6332 Args.push_back(RangeSize);
6336 Args.push_back(Index);
6338 StringRef VarName = VD->
getName();
6346 Args.push_back(NameCast);
6354 Args.push_back(CounterId);
6377 SemaRef.CheckCompleteVariableDeclaration(VD);
6383 "expected array of resource records");
6404 lookupMethod(
SemaRef, ResourceDecl,
6405 HasCounter ?
"__createFromBindingWithImplicitCounter"
6406 :
"__createFromBinding",
6410 CreateMethod = lookupMethod(
6412 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6413 :
"__createFromImplicitBinding",
6456std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6457 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6458 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6459 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6460 if (!TrueInfo || !FalseInfo)
6461 return std::nullopt;
6462 if (*TrueInfo != *FalseInfo)
6463 return std::nullopt;
6467 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6476 if (
const auto *AttrResType =
6477 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6479 return Bindings.getDeclBindingInfo(VD, RC);
6486void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6487 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6490 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6495 if (*ExprBinding ==
nullptr)
6498 auto PrevBinding = Assigns.find(VD);
6499 if (PrevBinding == Assigns.end()) {
6501 Assigns.insert({VD, *ExprBinding});
6506 if (*ExprBinding != PrevBinding->second) {
6508 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6510 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6521 "expected LHS to be a resource record or array of resource records");
6522 if (Opc != BO_Assign)
6527 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6535 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6540 trackLocalResource(VD, RHSExpr);
6557void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6559 "expected global variable that contains HLSL resource");
6562 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6563 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6564 ? ResourceClass::CBuffer
6565 : ResourceClass::SRV);
6578 if (
const HLSLAttributedResourceType *AttrResType =
6579 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6580 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6585 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6586 collectResourceBindingsOnUserRecordDecl(VD, RT);
6592void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6595 bool HasBinding =
false;
6596 for (Attr *A : VD->
attrs()) {
6599 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6600 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6603 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6604 if (!RBA || !RBA->hasRegisterSlot())
6609 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6610 "never have an attribute created");
6612 if (RT == RegisterType::C) {
6613 if (Bindings.hasBindingInfoForDecl(VD))
6615 diag::warn_hlsl_user_defined_type_missing_member)
6616 <<
static_cast<int>(RT);
6624 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6629 diag::warn_hlsl_user_defined_type_missing_member)
6630 <<
static_cast<int>(RT);
6638class InitListTransformer {
6642 QualType *DstIt =
nullptr;
6643 Expr **ArgIt =
nullptr;
6649 bool castInitializer(Expr *E) {
6650 assert(DstIt &&
"This should always be something!");
6651 if (DstIt == DestTypes.end()) {
6653 ArgExprs.push_back(E);
6658 DstIt = DestTypes.begin();
6661 Ctx, *DstIt,
false);
6666 ArgExprs.push_back(
Init);
6671 bool buildInitializerListImpl(Expr *E) {
6673 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6674 for (
auto *SubInit :
Init->inits())
6675 if (!buildInitializerListImpl(SubInit))
6685 return castInitializer(E);
6699 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6704 for (uint64_t I = 0; I <
Size; ++I) {
6706 SizeTy, SourceLocation());
6712 if (!castInitializer(ElExpr.
get()))
6717 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6718 unsigned Rows = MTy->getNumRows();
6719 unsigned Cols = MTy->getNumColumns();
6720 QualType ElemTy = MTy->getElementType();
6722 for (
unsigned R = 0;
R < Rows; ++
R) {
6723 for (
unsigned C = 0;
C < Cols; ++
C) {
6736 if (!castInitializer(ElExpr.
get()))
6744 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6748 for (uint64_t I = 0; I <
Size; ++I) {
6750 SizeTy, SourceLocation());
6755 if (!buildInitializerListImpl(ElExpr.
get()))
6762 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6763 RecordDecls.push_back(RD);
6764 while (RecordDecls.back()->getNumBases()) {
6765 CXXRecordDecl *D = RecordDecls.back();
6767 "HLSL doesn't support multiple inheritance");
6768 RecordDecls.push_back(
6771 while (!RecordDecls.empty()) {
6772 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6773 for (
auto *FD : RD->
fields()) {
6774 if (FD->isUnnamedBitField())
6782 if (!buildInitializerListImpl(Res.
get()))
6790 Expr *generateInitListsImpl(QualType Ty) {
6792 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6797 llvm::SmallVector<Expr *>
Inits;
6802 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6803 ElTy = ATy->getElementType();
6804 Size = ATy->getNumElements();
6805 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6806 ElTy = CMTy->getElementType();
6807 Size = CMTy->getNumElementsFlattened();
6810 ElTy = VTy->getElementType();
6811 Size = VTy->getZExtSize();
6813 for (uint64_t I = 0; I <
Size; ++I)
6814 Inits.push_back(generateInitListsImpl(ElTy));
6817 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6818 RecordDecls.push_back(RD);
6819 while (RecordDecls.back()->getNumBases()) {
6820 CXXRecordDecl *D = RecordDecls.back();
6822 "HLSL doesn't support multiple inheritance");
6823 RecordDecls.push_back(
6826 while (!RecordDecls.empty()) {
6827 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6828 for (
auto *FD : RD->
fields())
6829 if (!FD->isUnnamedBitField())
6834 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6835 Inits.back()->getEndLoc(),
false);
6836 NewInit->setType(Ty);
6841 llvm::SmallVector<QualType, 16> DestTypes;
6842 llvm::SmallVector<Expr *, 16> ArgExprs;
6843 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6844 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6845 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6846 InitTy = Entity.
getType().getNonReferenceType();
6856 DstIt = DestTypes.begin();
6859 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6861 Expr *generateInitLists() {
6862 assert(!ArgExprs.empty() &&
6863 "Call buildInitializerList to generate argument expressions.");
6864 ArgIt = ArgExprs.begin();
6866 return generateInitListsImpl(InitTy);
6867 llvm::SmallVector<Expr *>
Inits;
6868 while (ArgIt != ArgExprs.end())
6869 Inits.push_back(generateInitListsImpl(InitTy));
6872 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6873 Inits.back()->getEndLoc(),
false);
6874 llvm::APInt ArySize(64,
Inits.size());
6876 ArraySizeModifier::Normal, 0));
6888 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6895 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6899 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6919 if (
Init->getType()->isScalarType())
6922 InitListTransformer ILT(
SemaRef, Entity);
6924 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6932 Init->setInit(I, E);
6934 if (!ILT.buildInitializerList(E))
6937 size_t ExpectedSize = ILT.DestTypes.size();
6938 size_t ActualSize = ILT.ArgExprs.size();
6939 if (ExpectedSize == 0 && ActualSize == 0)
6946 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6948 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6949 << (int)(ExpectedSize < ActualSize) << InitTy
6950 << ExpectedSize << ActualSize;
6960 assert(ExpectedSize > 0 &&
6961 "The expected size of an incomplete array type must be at least 1.");
6963 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
6971 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6972 if (ExpectedSize != ActualSize) {
6973 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
6974 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6975 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
6982 Init->resizeInits(Ctx, NewInit->getNumInits());
6983 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
6984 Init->updateInit(Ctx, I, NewInit->getInit(I));
6992 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7002 StringRef AccessorName = CompName->
getName();
7003 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7005 unsigned Rows = MT->getNumRows();
7006 unsigned Cols = MT->getNumColumns();
7007 bool IsZeroBasedAccessor =
false;
7008 unsigned ChunkLen = 0;
7009 if (AccessorName.size() < 2)
7011 "length 4 for zero based: \'_mRC\' or "
7012 "length 3 for one-based: \'_RC\' accessor",
7015 if (AccessorName[0] ==
'_') {
7016 if (AccessorName[1] ==
'm') {
7017 IsZeroBasedAccessor =
true;
7024 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7027 if (AccessorName.size() % ChunkLen != 0) {
7028 const llvm::StringRef
Expected = IsZeroBasedAccessor
7029 ?
"zero based: '_mRC' accessor"
7030 :
"one-based: '_RC' accessor";
7035 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7036 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7037 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7039 bool HasRepeated =
false;
7041 unsigned NumComponents = 0;
7042 const char *Begin = AccessorName.data();
7044 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7045 const char *Chunk = Begin + I;
7046 char RowChar = 0, ColChar = 0;
7047 if (IsZeroBasedAccessor) {
7049 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7050 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7052 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7059 if (Chunk[0] !=
'_')
7061 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7068 bool IsDigitsError =
false;
7070 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7074 IsDigitsError =
true;
7078 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7082 IsDigitsError =
true;
7087 unsigned Row = RowChar -
'0';
7088 unsigned Col = ColChar -
'0';
7090 bool HasIndexingError =
false;
7091 if (IsZeroBasedAccessor) {
7093 if (!isZeroBasedIndex(Row)) {
7094 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7096 HasIndexingError =
true;
7098 if (!isZeroBasedIndex(Col)) {
7099 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7101 HasIndexingError =
true;
7105 if (!isOneBasedIndex(Row)) {
7106 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7108 HasIndexingError =
true;
7110 if (!isOneBasedIndex(Col)) {
7111 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7113 HasIndexingError =
true;
7120 if (HasIndexingError)
7126 bool HasBoundsError =
false;
7128 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7130 HasBoundsError =
true;
7133 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7135 HasBoundsError =
true;
7140 unsigned FlatIndex = Row * Cols + Col;
7141 if (Seen[FlatIndex])
7143 Seen[FlatIndex] =
true;
7146 if (NumComponents == 0 || NumComponents > 4) {
7147 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7152 QualType ElemTy = MT->getElementType();
7153 if (NumComponents == 1)
7159 for (Sema::ExtVectorDeclsType::iterator
7163 if ((*I)->getUnderlyingType() == VT)
7174 trackLocalResource(VDecl,
Init);
7176 const HLSLVkConstantIdAttr *ConstIdAttr =
7177 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7184 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7194 int ConstantID = ConstIdAttr->getId();
7195 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7197 ConstIdAttr->getLocation());
7201 if (
C->getType()->getCanonicalTypeUnqualified() !=
7205 Context.getTrivialTypeSourceInfo(
7206 Init->getType(),
Init->getExprLoc()),
7225 if (!Params || Params->
size() != 1)
7238 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7239 if (TTP->hasDefaultArgument()) {
7240 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7243 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7244 if (NTTP->hasDefaultArgument()) {
7245 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7248 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7249 if (TTPD->hasDefaultArgument()) {
7250 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7257 return SemaRef.CheckTemplateIdType(
7259 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 bool isIntUpTo32Element(const ASTContext &Ctx, QualType Elem)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool CheckScalarFloatOperand(Sema &S, CallExpr *TheCall, unsigned ArgIndex)
static bool isIntElementOfWidth(const ASTContext &Ctx, QualType Elem, uint64_t Width)
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 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 unsigned getComponentCountOf(QualType T)
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 QualType getElementTypeOf(QualType T, bool IncludeMatrix)
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)
static bool isFloatOrHalfElement(QualType Elem)
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 ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
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.
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
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 getCorrespondingUnsignedType(QualType T) 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.
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 ...
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
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)
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 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)
QualType getInoutParameterType(QualType Ty)
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
bool isFloat16Type() 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.
bool isFloat32Type() const
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
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
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