38#include "llvm/ADT/ArrayRef.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/SmallVector.h"
41#include "llvm/ADT/StringExtras.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ADT/Twine.h"
44#include "llvm/Frontend/HLSL/HLSLBinding.h"
45#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
46#include "llvm/Support/Casting.h"
47#include "llvm/Support/DXILABI.h"
48#include "llvm/Support/ErrorHandling.h"
49#include "llvm/Support/FormatVariadic.h"
50#include "llvm/TargetParser/Triple.h"
59using llvm::hlsl::InterpolationModifier;
60using llvm::hlsl::IOType;
61using llvm::hlsl::SemanticStageInfo;
70 return VT->getElementType();
72 return MT->getElementType();
78 case ResourceClass::SRV:
79 return RegisterType::SRV;
80 case ResourceClass::UAV:
81 return RegisterType::UAV;
82 case ResourceClass::CBuffer:
83 return RegisterType::CBuffer;
84 case ResourceClass::Sampler:
85 return RegisterType::Sampler;
87 llvm_unreachable(
"unexpected ResourceClass value");
96 case ResourceClass::SRV:
97 case ResourceClass::UAV:
99 case ResourceClass::CBuffer:
101 case ResourceClass::Sampler:
104 llvm_unreachable(
"unexpected ResourceClass value");
110 assert(RT !=
nullptr);
114 *RT = RegisterType::SRV;
118 *RT = RegisterType::UAV;
122 *RT = RegisterType::CBuffer;
126 *RT = RegisterType::Sampler;
130 *RT = RegisterType::C;
134 *RT = RegisterType::I;
143 case RegisterType::SRV:
145 case RegisterType::UAV:
147 case RegisterType::CBuffer:
149 case RegisterType::Sampler:
151 case RegisterType::C:
153 case RegisterType::I:
156 llvm_unreachable(
"unexpected RegisterType value");
161 case RegisterType::SRV:
162 return ResourceClass::SRV;
163 case RegisterType::UAV:
164 return ResourceClass::UAV;
165 case RegisterType::CBuffer:
166 return ResourceClass::CBuffer;
167 case RegisterType::Sampler:
168 return ResourceClass::Sampler;
169 case RegisterType::C:
170 case RegisterType::I:
174 llvm_unreachable(
"unexpected RegisterType value");
178 const auto *BT = dyn_cast<BuiltinType>(
Type);
182 return Builtin::BI__builtin_get_spirv_spec_constant_int;
185 switch (BT->getKind()) {
186 case BuiltinType::Bool:
187 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
188 case BuiltinType::Short:
189 return Builtin::BI__builtin_get_spirv_spec_constant_short;
190 case BuiltinType::Int:
191 return Builtin::BI__builtin_get_spirv_spec_constant_int;
192 case BuiltinType::LongLong:
193 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
194 case BuiltinType::UShort:
195 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
196 case BuiltinType::UInt:
197 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
198 case BuiltinType::ULongLong:
199 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
200 case BuiltinType::Half:
201 return Builtin::BI__builtin_get_spirv_spec_constant_half;
202 case BuiltinType::Float:
203 return Builtin::BI__builtin_get_spirv_spec_constant_float;
204 case BuiltinType::Double:
205 return Builtin::BI__builtin_get_spirv_spec_constant_double;
214 llvm::raw_svector_ostream OS(Buffer);
221 ResourceClass ResClass) {
223 "DeclBindingInfo already added");
229 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
230 return &BindingsList.emplace_back(VD, ResClass);
234 ResourceClass ResClass) {
235 auto Entry = DeclToBindingListIndex.find(VD);
236 if (Entry != DeclToBindingListIndex.end()) {
237 for (
unsigned Index = Entry->getSecond();
238 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
240 if (BindingsList[Index].ResClass == ResClass)
241 return &BindingsList[Index];
248 return DeclToBindingListIndex.contains(VD);
260 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
263 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
264 : llvm::hlsl::ResourceClass::SRV;
276 if (
T->isArrayType() ||
T->isStructureType() ||
T->isConstantMatrixType())
283 assert(Context.getTypeSize(
T) <= 64 &&
284 "Scalar bit widths larger than 64 not supported");
287 return Context.getTypeSize(
T) / 8;
294 constexpr unsigned CBufferAlign = 16;
295 if (
const auto *RD =
T->getAsRecordDecl()) {
297 for (
const FieldDecl *Field : RD->fields()) {
304 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
305 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
306 FieldAlign = CBufferAlign;
309 Size = llvm::alignTo(Size, FieldAlign);
316 unsigned ElementCount = AT->getSize().getZExtValue();
317 if (ElementCount == 0)
320 unsigned ElementSize =
322 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
323 return AlignedElementSize * (ElementCount - 1) + ElementSize;
327 unsigned ElementCount = VT->getNumElements();
328 unsigned ElementSize =
330 return ElementSize * ElementCount;
333 return Context.getTypeSize(
T) / 8;
344 bool HasPackOffset =
false;
345 bool HasNonPackOffset =
false;
347 VarDecl *Var = dyn_cast<VarDecl>(Field);
350 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
351 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
352 HasPackOffset =
true;
354 HasNonPackOffset =
true;
361 if (HasNonPackOffset)
368 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
369 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
370 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
371 return LHS.second->getOffsetInBytes() <
372 RHS.second->getOffsetInBytes();
374 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
375 VarDecl *Var = PackOffsetVec[i].first;
376 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
378 unsigned Begin =
Attr->getOffsetInBytes();
379 unsigned End = Begin + Size;
380 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
381 if (End > NextBegin) {
382 VarDecl *NextVar = PackOffsetVec[i + 1].first;
394 CAT = dyn_cast<ConstantArrayType>(
396 return CAT !=
nullptr;
407static const HLSLAttributedResourceType *
410 "expected array of resource records");
412 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
414 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
417static const HLSLAttributedResourceType *
431 return RD->isEmpty();
460 Base.getType()->castAsCXXRecordDecl()))
471 assert(RD ==
nullptr &&
472 "there should be at most 1 record by a given name in a scope");
489 Name.append(NameBaseII->
getName());
496 size_t NameLength = Name.size();
505 Name.append(llvm::Twine(suffix).str());
506 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
513 Name.truncate(NameLength);
528 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
530 S, CAT->getElementType()->getUnqualifiedDesugaredType());
535 CAT->getSizeModifier(),
536 CAT->getIndexTypeCVRQualifiers())
585 "struct is already HLSL buffer compatible");
599 LS->
addAttr(PackedAttr::CreateImplicit(AST));
603 if (
unsigned NumBases = StructDecl->
getNumBases()) {
604 assert(NumBases == 1 &&
"HLSL supports only one base type");
654 LS->
addAttr(PackedAttr::CreateImplicit(AST));
659 VarDecl *VD = dyn_cast<VarDecl>(D);
675 "host layout field for $Globals decl failed to be created");
694 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
695 Attr->setBinding(RT, std::nullopt, 0);
696 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
703 BufDecl->setRBraceLoc(RBrace);
720 BufDecl->isCBuffer() ? RegisterType::CBuffer
730 int X,
int Y,
int Z) {
731 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
732 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
733 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
734 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
744 int Min,
int Max,
int Preferred,
745 int SpelledArgsCount) {
746 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
747 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
748 WS->getPreferred() != Preferred ||
749 WS->getSpelledArgsCount() != SpelledArgsCount) {
750 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
751 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
757 Result->setSpelledArgsCount(SpelledArgsCount);
761HLSLVkConstantIdAttr *
767 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
775 Diag(VD->getLocation(), diag::err_specialization_const);
779 if (!VD->getType().isConstQualified()) {
780 Diag(VD->getLocation(), diag::err_specialization_const);
784 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
785 if (CI->getId() != Id) {
786 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
787 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
792 HLSLVkConstantIdAttr *
Result =
799 llvm::Triple::EnvironmentType ShaderType) {
800 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
801 if (NT->getType() != ShaderType) {
802 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
803 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
807 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
810HLSLParamModifierAttr *
812 HLSLParamModifierAttr::Spelling Spelling) {
815 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
816 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
817 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
818 D->
dropAttr<HLSLParamModifierAttr>();
820 return HLSLParamModifierAttr::Create(
822 HLSLParamModifierAttr::Keyword_inout);
824 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
825 Diag(PA->getLocation(), diag::note_conflicting_attribute);
832 InterpolationModifier Modifier;
833 switch (
static_cast<HLSLInterpolationModifierAttr::Spelling
>(
835 case HLSLInterpolationModifierAttr::Keyword_nointerpolation:
836 Modifier = InterpolationModifier::NoInterpolation;
838 case HLSLInterpolationModifierAttr::Keyword_linear:
839 Modifier = InterpolationModifier::Linear;
841 case HLSLInterpolationModifierAttr::Keyword_centroid:
842 Modifier = InterpolationModifier::Centroid;
844 case HLSLInterpolationModifierAttr::Keyword_noperspective:
845 Modifier = InterpolationModifier::NoPerspective;
847 case HLSLInterpolationModifierAttr::Keyword_sample:
848 Modifier = InterpolationModifier::Sample;
850 case HLSLInterpolationModifierAttr::Keyword_center:
851 Modifier = InterpolationModifier::Center;
853 case HLSLInterpolationModifierAttr::SpellingNotCalculated:
854 llvm_unreachable(
"interpolation modifier spelling was not calculated");
857 InterpolationModifier Modifiers = Modifier;
859 auto Old =
static_cast<InterpolationModifier
>(
Previous->getModifiers());
861 if (
any(Old & Modifier)) {
862 Diag(AL.
getLoc(), diag::warn_hlsl_duplicate_interpolation) << AL;
863 }
else if (llvm::hlsl::getInterpolationMode(Modifiers) ==
864 llvm::dxbc::PSV::InterpolationMode::Invalid &&
865 llvm::hlsl::getInterpolationMode(Old) !=
866 llvm::dxbc::PSV::InterpolationMode::Invalid) {
867 Diag(AL.
getLoc(), diag::err_hlsl_interpolation_conflict);
868 Diag(
Previous->getLocation(), diag::note_conflicting_attribute);
871 InterpolationModifier OldLocation =
872 llvm::hlsl::getInterpolationSamplingLocation(Old);
873 InterpolationModifier NewLocation =
874 llvm::hlsl::getInterpolationSamplingLocation(Modifier);
875 if (
any(OldLocation) &&
any(NewLocation)) {
876 Diag(AL.
getLoc(), diag::warn_hlsl_interpolation_override)
877 << (std::max(OldLocation, NewLocation) ==
878 InterpolationModifier::Sample)
879 << (std::min(OldLocation, NewLocation) ==
880 InterpolationModifier::Centroid);
883 D->
dropAttr<HLSLInterpolationModifierAttr>();
885 D->
addAttr(HLSLInterpolationModifierAttr::Create(
889bool SemaHLSL::checkInterpolationModifiers(
890 const DeclaratorDecl *D,
const HLSLInterpolationModifierAttr *Inherited,
891 const HLSLParsedSemanticAttr *Semantic) {
894 const auto *A = D->
getAttr<HLSLInterpolationModifierAttr>();
898 Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
900 const auto *FD = dyn_cast<FunctionDecl>(D);
903 if (
T->isDependentType())
905 if (
const auto *RT =
T->getAs<RecordType>()) {
911 Valid &= checkInterpolationModifiers(Field, A, Semantic);
917 auto Modifiers =
static_cast<InterpolationModifier
>(A->getModifiers());
918 if (Modifiers == InterpolationModifier::NoInterpolation) {
922 llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
923 if (Kind != SemanticKind::Position && Kind != SemanticKind::Barycentrics)
925 Diag(A->getLocation(), diag::err_hlsl_interpolation_semantic)
926 << Semantic->getSemanticName();
927 Diag(Semantic->getLocation(), diag::note_conflicting_attribute);
934 Diag(A->getLocation(), diag::err_hlsl_interpolation_type) <<
T;
960 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
961 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
964 if (Shader->getType() != Env) {
965 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
977 case llvm::Triple::UnknownEnvironment:
978 case llvm::Triple::Library:
980 case llvm::Triple::RootSignature:
981 llvm_unreachable(
"rootsig environment has no functions");
983 llvm_unreachable(
"Unhandled environment in triple");
989 HLSLAppliedSemanticAttr *Semantic,
994 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
995 assert(ShaderAttr &&
"Entry point has no shader attribute");
996 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
997 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
1000 case SemanticKind::Position:
1004 return (ST == llvm::Triple::Vertex && !IsInput) ||
1005 (ST == llvm::Triple::Pixel && IsInput);
1006 case SemanticKind::VertexID:
1008 case SemanticKind::InstanceID:
1009 return ST == llvm::Triple::Vertex && IsInput;
1010 case SemanticKind::ShadingRate:
1015 return (ST == llvm::Triple::Pixel && IsInput) ||
1016 (ST == llvm::Triple::Vertex && !IsInput);
1017 case SemanticKind::Barycentrics:
1018 case SemanticKind::SampleIndex:
1019 case SemanticKind::PrimitiveID:
1020 return ST == llvm::Triple::Pixel && IsInput;
1021 case SemanticKind::StartVertexLocation:
1022 case SemanticKind::StartInstanceLocation:
1023 return ST == llvm::Triple::Vertex && IsInput;
1024 case SemanticKind::ViewID:
1031bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1034 SemanticInfo &ActiveSemantic,
1035 SemaHLSL::SemanticContext &SC) {
1036 if (ActiveSemantic.Semantic ==
nullptr) {
1037 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1038 if (ActiveSemantic.Semantic)
1039 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1042 if (!ActiveSemantic.Semantic) {
1048 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1049 ActiveSemantic.Semantic->getAttrName()->getName(),
1050 ActiveSemantic.Index.value_or(0));
1055 QualType
T = D == FD ? FD->getReturnType() : D->
getType();
1056 const ConstantArrayType *AT =
1059 Diag(A->getLoc(), diag::err_hlsl_semantic_zero_sized_array)
1060 << A->getAttrName();
1068 if (
const auto *MT = BaseTy->
getAs<ConstantMatrixType>())
1071 : MT->getNumColumns();
1073 checkSemanticAnnotation(FD, D, A, SC, ElementCount);
1076 unsigned Location = ActiveSemantic.Index.value_or(0);
1079 any(SC.CurrentIOType & IOType::In))) {
1080 bool HasVkLocation =
false;
1081 if (
auto *A = D->
getAttr<HLSLVkLocationAttr>()) {
1082 HasVkLocation =
true;
1083 Location = A->getLocation();
1086 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1087 Diag(D->
getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1090 SC.UsesExplicitVkLocations = HasVkLocation;
1093 ActiveSemantic.Index = Location + ElementCount;
1095 StringRef BaseName = ActiveSemantic.Semantic->getAttrName()->getName();
1096 std::string LowerName = BaseName.lower();
1097 for (
unsigned I = 0; I < ElementCount; ++I) {
1098 auto [It, Inserted] = SC.ActiveSemantics.try_emplace(
1099 (Twine(LowerName) + Twine(Location + I)).str(), D->
getLocation());
1102 << (BaseName + Twine(Location + I)).str();
1103 Diag(It->second, diag::note_previous_use);
1111bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1114 SemanticInfo &ActiveSemantic,
1115 SemaHLSL::SemanticContext &SC) {
1116 if (ActiveSemantic.Semantic ==
nullptr) {
1117 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1118 if (ActiveSemantic.Semantic)
1119 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1125 const RecordType *RT = dyn_cast<RecordType>(
T);
1127 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1130 const RecordDecl *RD = RT->getDecl();
1131 for (FieldDecl *Field : RD->
fields()) {
1132 SemanticInfo Info = ActiveSemantic;
1133 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1134 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1137 if (ActiveSemantic.Semantic)
1138 ActiveSemantic = Info;
1145 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1146 assert(ShaderAttr &&
"Entry point has no shader attribute");
1147 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1151 case llvm::Triple::Pixel:
1152 case llvm::Triple::Vertex:
1153 case llvm::Triple::Geometry:
1154 case llvm::Triple::Hull:
1155 case llvm::Triple::Domain:
1156 case llvm::Triple::RayGeneration:
1157 case llvm::Triple::Intersection:
1158 case llvm::Triple::AnyHit:
1159 case llvm::Triple::ClosestHit:
1160 case llvm::Triple::Miss:
1161 case llvm::Triple::Callable:
1162 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1163 diagnoseAttrStageMismatch(NT, ST,
1164 {llvm::Triple::Compute,
1165 llvm::Triple::Amplification,
1166 llvm::Triple::Mesh});
1169 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1170 diagnoseAttrStageMismatch(WS, ST,
1171 {llvm::Triple::Compute,
1172 llvm::Triple::Amplification,
1173 llvm::Triple::Mesh});
1178 case llvm::Triple::Compute:
1179 case llvm::Triple::Amplification:
1180 case llvm::Triple::Mesh:
1181 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1183 << llvm::Triple::getEnvironmentTypeName(ST);
1186 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1188 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1189 }
else if (Ver < VersionTuple(6, 6)) {
1190 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1193 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1196 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1197 << WS << WS->getSpelledArgsCount() <<
"6.8";
1202 case llvm::Triple::RootSignature:
1203 llvm_unreachable(
"rootsig environment has no function entry point");
1205 llvm_unreachable(
"Unhandled environment in triple");
1208 SemaHLSL::SemanticContext InputSC = {};
1209 InputSC.CurrentIOType = IOType::In;
1210 SemaHLSL::SemanticContext OutputSC = {};
1211 OutputSC.CurrentIOType = IOType::Out;
1214 SemanticInfo ActiveSemantic;
1215 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1216 if (ActiveSemantic.Semantic)
1217 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1221 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1222 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1226 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1227 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1228 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1231 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1232 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1237 SemanticInfo ActiveSemantic;
1238 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1239 if (ActiveSemantic.Semantic)
1240 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1242 if (ST == llvm::Triple::Vertex &&
1243 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1245 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1249void SemaHLSL::checkSemanticAnnotation(
1251 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC,
1252 unsigned ElementCount) {
1253 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1254 assert(ShaderAttr &&
"Entry point has no shader attribute");
1255 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1258 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1259 llvm::hlsl::SemanticInterpretation Interpretation =
1260 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1261 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid) {
1262 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1268 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary) {
1269 diagnoseSemanticType(Param, SemanticAttr, SemanticKind::Arbitrary);
1273 diagnoseSystemSemanticIndex(SemanticAttr, Kind, ElementCount);
1274 diagnoseSemanticType(Param, SemanticAttr, Kind);
1275 diagnoseSemanticShaderModel(SemanticAttr, Kind);
1278void SemaHLSL::diagnoseSemanticShaderModel(
const HLSLAppliedSemanticAttr *A,
1281 if (!Triple.isDXIL())
1285 case SemanticKind::Barycentrics:
1286 case SemanticKind::ViewID:
1287 if (Triple.getOSVersion() < VersionTuple(6, 1))
1288 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1289 << A->getAttrName() <<
"6.1";
1291 case SemanticKind::ShadingRate:
1292 if (Triple.getOSVersion() < VersionTuple(6, 4))
1293 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1294 << A->getAttrName() <<
"6.4";
1296 case SemanticKind::StartVertexLocation:
1297 case SemanticKind::StartInstanceLocation:
1298 if (Triple.getOSVersion() < VersionTuple(6, 8))
1299 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1300 << A->getAttrName() <<
"6.8";
1307void SemaHLSL::diagnoseSystemSemanticIndex(
const HLSLAppliedSemanticAttr *A,
1309 unsigned ElementCount) {
1310 assert(Kind != SemanticKind::Invalid && Kind != SemanticKind::Arbitrary &&
1311 "expected a recognized system semantic");
1312 assert(ElementCount > 0 &&
"a semantic covers at least one element");
1315 uint32_t FirstIndex = A->getSemanticIndex();
1317 constexpr uint32_t MaxSemanticIndex = std::numeric_limits<uint32_t>::max();
1318 if (LastIndex > MaxSemanticIndex) {
1319 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1320 << A->getAttrName() << LastIndex << MaxSemanticIndex;
1328 case SemanticKind::ClipDistance:
1329 case SemanticKind::CullDistance:
1331 case SemanticKind::Target: {
1332 constexpr unsigned MaxTargetIndex = 7;
1333 if (LastIndex > MaxTargetIndex)
1334 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1335 << A->getAttrName() << LastIndex << MaxTargetIndex;
1339 Diag(A->getLoc(), diag::err_hlsl_semantic_indexing_not_supported)
1340 << A->getAttrName();
1347 return VT->getElementType();
1350 return MT->getElementType();
1356 return VT->getNumElements();
1377void SemaHLSL::diagnoseSemanticType(
const Decl *D,
1378 const HLSLAppliedSemanticAttr *A,
1380 assert(Kind != SemanticKind::Invalid &&
"expected a valid semantic");
1384 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
1390 T =
T.getNonReferenceType();
1393 QualType DeclaredTy =
T;
1395 T = AT->getElementType();
1403 case SemanticKind::Barycentrics:
1405 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1406 << A->getAttrName() << 2 << 3
1409 case SemanticKind::DispatchThreadID:
1410 case SemanticKind::GroupID:
1411 case SemanticKind::GroupThreadID:
1413 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1414 << A->getAttrName() << 1 << 3
1417 case SemanticKind::StartVertexLocation:
1418 case SemanticKind::StartInstanceLocation:
1419 case SemanticKind::ViewID:
1422 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1423 << A->getAttrName() << 0 << 1 << 1
1426 case SemanticKind::GroupIndex:
1428 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1429 << A->getAttrName() << 0 << 1 << 1
1432 case SemanticKind::VertexID:
1434 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1435 << A->getAttrName() << 0 << 1
1438 case SemanticKind::Position:
1439 case SemanticKind::Target:
1441 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1442 << A->getAttrName() << 1 << 4
1445 case SemanticKind::SampleIndex:
1446 case SemanticKind::PrimitiveID:
1450 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1451 << A->getAttrName() << 0 << 1
1454 case SemanticKind::InstanceID:
1455 case SemanticKind::ShadingRate:
1462 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1463 << A->getAttrName() << 0 << 1
1465 (IsSPIRV ? 4 : 3) << DeclaredTy;
1478 Diag(A->getLoc(), diag::err_hlsl_semantic_64bit_type)
1479 << A->getAttrName() << DeclaredTy;
1482void SemaHLSL::diagnoseAttrStageMismatch(
1483 const Attr *A, llvm::Triple::EnvironmentType Stage,
1484 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1485 SmallVector<StringRef, 8> StageStrings;
1486 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1487 [](llvm::Triple::EnvironmentType ST) {
1489 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1491 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1492 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1493 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1496void SemaHLSL::diagnoseSemanticStageMismatch(
1497 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1500 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1501 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1502 return Info.Stage == Stage;
1505 StringRef CurrentIOTypeName =
"patch constants or primitives";
1506 if (
any(CurrentIOType & IOType::In))
1507 CurrentIOTypeName =
"inputs";
1508 else if (
any(CurrentIOType & IOType::Out))
1509 CurrentIOTypeName =
"outputs";
1512 if (It == Allowed.end()) {
1513 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1514 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1515 << CurrentIOTypeName;
1519 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1520 if (!(AllowedIOTypes & CurrentIOType)) {
1521 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1522 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1523 << CurrentIOTypeName;
1528template <CastKind Kind>
1531 Ty = VTy->getElementType();
1536template <CastKind Kind>
1548 if (LHSFloat && RHSFloat) {
1576 if (LHSSigned == RHSSigned) {
1577 if (IsCompAssign || IntOrder >= 0)
1585 if (IntOrder != (LHSSigned ? 1 : -1)) {
1586 if (IsCompAssign || RHSSigned)
1595 if (IsCompAssign || LHSSigned)
1622 return CK_FloatingCast;
1624 return CK_IntegralCast;
1626 return CK_IntegralToFloating;
1628 return CK_FloatingToIntegral;
1634 bool IsCompAssign) {
1641 if (!LVecTy && IsCompAssign) {
1643 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1645 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1647 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1652 unsigned EndSz = std::numeric_limits<unsigned>::max();
1655 LSz = EndSz = LVecTy->getNumElements();
1658 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1659 "one of the above should have had a value");
1663 if (IsCompAssign && LSz != EndSz) {
1665 diag::err_hlsl_vector_compound_assignment_truncation)
1666 << LHSType << RHSType;
1672 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1677 if (!IsCompAssign && !LVecTy)
1681 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1682 return Ctx.getCommonSugaredType(LHSType, RHSType);
1690 LElTy, RElTy, IsCompAssign);
1693 "HLSL Vectors can only contain integer or floating point types");
1695 LElTy, RElTy, IsCompAssign);
1700 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1701 "Called with non-logical operator");
1703 llvm::raw_svector_ostream OS(Buff);
1705 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1706 OS << NewFnName <<
"(";
1716std::pair<IdentifierInfo *, bool>
1719 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1726 return {DeclIdent,
Found};
1737 for (
auto &RootSigElement : RootElements)
1738 Elements.push_back(RootSigElement.getElement());
1742 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1744 SignatureDecl->setImplicit();
1750 if (RootSigOverrideIdent) {
1753 if (
SemaRef.LookupQualifiedName(R, DC))
1754 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1762struct PerVisibilityBindingChecker {
1765 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1769 llvm::dxbc::ShaderVisibility Vis;
1774 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1776 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1777 llvm::dxil::ResourceClass RC,
uint32_t Space,
1779 const hlsl::RootSignatureElement *Elem) {
1781 assert(BuilderIndex < Builders.size() &&
1782 "Not enough builders for visibility type");
1783 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1784 static_cast<const void *
>(Elem));
1786 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1787 "'All' visibility must come first");
1788 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1789 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1790 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1791 static_cast<const void *
>(Elem));
1793 ElemInfoMap.push_back({Elem,
Visibility,
false});
1796 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1797 auto It = llvm::lower_bound(
1799 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1800 assert(It->Elem == Elem &&
"Element not in map");
1804 bool checkOverlap() {
1805 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1806 return LHS.Elem < RHS.Elem;
1809 bool HadOverlap =
false;
1811 using llvm::hlsl::BindingInfoBuilder;
1812 auto ReportOverlap = [
this,
1813 &HadOverlap](
const BindingInfoBuilder &Builder,
1814 const llvm::hlsl::Binding &Reported) {
1818 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1819 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1820 const auto *PrevElem =
1821 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1823 ElemInfo &Info =
getInfo(Elem);
1828 Info.Diagnosed =
true;
1830 ElemInfo &PrevInfo =
getInfo(PrevElem);
1831 llvm::dxbc::ShaderVisibility CommonVis =
1832 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1835 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1836 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1837 << Reported.isUnbounded() << Reported.UpperBound
1842 this->S->
Diag(PrevElem->getLocation(),
1843 diag::note_hlsl_resource_range_here);
1846 for (BindingInfoBuilder &Builder : Builders)
1847 Builder.calculateBindingInfo(ReportOverlap);
1867 bool HadError =
false;
1868 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1869 uint32_t UpperBound) {
1871 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1872 << LowerBound << UpperBound;
1879 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1880 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1881 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1884 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1885 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1886 ReportError(Loc, 0, 0xfffffffe);
1889 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1890 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1891 ReportError(Loc, 0, 0xffffffef);
1894 const uint32_t Version =
1895 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1896 const uint32_t VersionEnum = Version - 1;
1897 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1899 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1906 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1907 if (
const auto *Descriptor =
1908 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1909 VerifyRegister(Loc, Descriptor->Reg.Number);
1910 VerifySpace(Loc, Descriptor->Space);
1912 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1914 ReportFlagError(Loc);
1915 }
else if (
const auto *Constants =
1916 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1917 VerifyRegister(Loc, Constants->Reg.Number);
1918 VerifySpace(Loc, Constants->Space);
1919 }
else if (
const auto *Sampler =
1920 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1921 VerifyRegister(Loc, Sampler->Reg.Number);
1922 VerifySpace(Loc, Sampler->Space);
1925 "By construction, parseFloatParam can't produce a NaN from a "
1926 "float_literal token");
1928 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1929 ReportError(Loc, 0, 16);
1930 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1931 ReportFloatError(Loc, -16.f, 15.99f);
1932 }
else if (
const auto *Clause =
1933 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1935 VerifyRegister(Loc, Clause->Reg.Number);
1936 VerifySpace(Loc, Clause->Space);
1938 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1942 ReportError(Loc, 1, 0xfffffffe);
1945 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1947 ReportFlagError(Loc);
1951 PerVisibilityBindingChecker BindingChecker(
this);
1952 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1957 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1958 if (
const auto *Descriptor =
1959 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1960 uint32_t LowerBound(Descriptor->Reg.Number);
1961 uint32_t UpperBound(LowerBound);
1963 BindingChecker.trackBinding(
1964 Descriptor->Visibility,
1965 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1966 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1967 }
else if (
const auto *Constants =
1968 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1969 uint32_t LowerBound(Constants->Reg.Number);
1970 uint32_t UpperBound(LowerBound);
1972 BindingChecker.trackBinding(
1973 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1974 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1975 }
else if (
const auto *Sampler =
1976 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1977 uint32_t LowerBound(Sampler->Reg.Number);
1978 uint32_t UpperBound(LowerBound);
1980 BindingChecker.trackBinding(
1981 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1982 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1983 }
else if (
const auto *Clause =
1984 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1987 UnboundClauses.emplace_back(Clause, &RootSigElem);
1988 }
else if (
const auto *Table =
1989 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1990 assert(UnboundClauses.size() == Table->NumClauses &&
1991 "Number of unbound elements must match the number of clauses");
1992 bool HasAnySampler =
false;
1993 bool HasAnyNonSampler =
false;
1994 uint64_t Offset = 0;
1995 bool IsPrevUnbound =
false;
1996 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1998 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1999 HasAnySampler =
true;
2001 HasAnyNonSampler =
true;
2003 if (HasAnySampler && HasAnyNonSampler)
2004 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
2009 if (Clause->NumDescriptors == 0)
2013 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
2015 Offset = Clause->Offset;
2017 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
2018 Offset, Clause->NumDescriptors);
2020 if (IsPrevUnbound && IsAppending)
2021 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
2022 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
2023 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
2026 Offset = RangeBound + 1;
2027 IsPrevUnbound = Clause->NumDescriptors ==
2028 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
2031 uint32_t LowerBound(Clause->Reg.Number);
2032 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
2033 LowerBound, Clause->NumDescriptors);
2035 BindingChecker.trackBinding(
2037 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
2038 LowerBound, UpperBound, ClauseElem);
2040 UnboundClauses.clear();
2044 return BindingChecker.checkOverlap();
2049 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2054 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
2055 if (RS->getSignatureIdent() != Ident) {
2056 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
2060 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
2066 if (
auto *SignatureDecl =
2067 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
2074 llvm::VersionTuple SMVersion =
2079 uint32_t ZMax = 1024;
2080 uint32_t ThreadMax = 1024;
2081 if (IsDXIL && SMVersion.getMajor() <= 4) {
2084 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
2094 diag::err_hlsl_numthreads_argument_oor)
2103 diag::err_hlsl_numthreads_argument_oor)
2112 diag::err_hlsl_numthreads_argument_oor)
2117 if (
X * Y * Z > ThreadMax) {
2118 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
2135 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
2143 if (SpelledArgsCount > 1 &&
2147 uint32_t Preferred = 0;
2148 if (SpelledArgsCount > 2 &&
2152 if (SpelledArgsCount > 2) {
2155 diag::err_attribute_power_of_two_in_range)
2156 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
2161 if (Preferred < Min || Preferred >
Max) {
2163 diag::err_attribute_power_of_two_in_range)
2164 << AL <<
Min <<
Max << Preferred;
2167 }
else if (SpelledArgsCount > 1) {
2170 diag::err_attribute_power_of_two_in_range)
2171 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
2175 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
2178 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
2183 diag::err_attribute_power_of_two_in_range)
2184 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
2189 HLSLWaveSizeAttr *NewAttr =
2226 uint32_t Binding = 0;
2248 uint32_t IndexValue(0), ExplicitIndex(0);
2251 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2253 assert(IndexValue > 0 ? ExplicitIndex :
true);
2256 if (Kind == SemanticKind::Invalid) {
2257 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2263 case SemanticKind::RenderTargetArrayIndex:
2264 case SemanticKind::ViewPortArrayIndex:
2265 case SemanticKind::ClipDistance:
2266 case SemanticKind::CullDistance:
2267 case SemanticKind::OutputControlPointID:
2268 case SemanticKind::DomainLocation:
2269 case SemanticKind::GSInstanceID:
2270 case SemanticKind::IsFrontFace:
2271 case SemanticKind::Coverage:
2272 case SemanticKind::InnerCoverage:
2273 case SemanticKind::Depth:
2274 case SemanticKind::DepthLessEqual:
2275 case SemanticKind::DepthGreaterEqual:
2276 case SemanticKind::StencilRef:
2277 case SemanticKind::TessFactor:
2278 case SemanticKind::InsideTessFactor:
2279 case SemanticKind::CullPrimitive:
2280 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2286 D->
addAttr(HLSLParsedSemanticAttr::Create(
2292 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2293 << AL <<
"shader constant in a constant buffer";
2297 uint32_t SubComponent;
2307 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2312 if (IsAggregateTy) {
2313 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2317 if ((Component * 32 + Size) > 128) {
2318 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2323 EltTy = VT->getElementType();
2325 if (Align > 32 && Component == 1) {
2328 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2342 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2345 llvm::Triple::EnvironmentType ShaderType;
2346 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2347 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2348 << AL << Str << ArgLoc;
2362 Expr *SampleCountExpr) {
2363 assert(AttrList.size() &&
"expected list of resource attributes");
2370 HLSLAttributedResourceType::Attributes ResAttrs;
2372 bool HasResourceClass =
false;
2373 bool HasResourceDimension =
false;
2374 for (
const Attr *A : AttrList) {
2379 case attr::HLSLResourceClass: {
2381 if (HasResourceClass) {
2383 ? diag::warn_duplicate_attribute_exact
2384 : diag::warn_duplicate_attribute)
2388 ResAttrs.ResourceClass = RC;
2389 HasResourceClass =
true;
2392 case attr::HLSLResourceDimension: {
2393 llvm::dxil::ResourceDimension RD =
2395 if (HasResourceDimension) {
2397 ? diag::warn_duplicate_attribute_exact
2398 : diag::warn_duplicate_attribute)
2402 ResAttrs.ResourceDimension = RD;
2403 HasResourceDimension =
true;
2406 case attr::HLSLIsROV:
2407 if (ResAttrs.IsROV) {
2411 ResAttrs.IsROV =
true;
2413 case attr::HLSLRawBuffer:
2414 if (ResAttrs.RawBuffer) {
2418 ResAttrs.RawBuffer =
true;
2420 case attr::HLSLIsArray:
2421 if (ResAttrs.IsArray) {
2425 ResAttrs.IsArray =
true;
2427 case attr::HLSLIsMultiSampled:
2428 if (ResAttrs.SampleCountExpr) {
2434 ResAttrs.SampleCountExpr =
2440 case attr::HLSLIsCounter:
2441 if (ResAttrs.IsCounter) {
2445 ResAttrs.IsCounter =
true;
2447 case attr::HLSLContainedType: {
2450 if (!ContainedTy.
isNull()) {
2452 ? diag::warn_duplicate_attribute_exact
2453 : diag::warn_duplicate_attribute)
2462 llvm_unreachable(
"unhandled resource attribute type");
2466 if (!HasResourceClass) {
2467 S.
Diag(AttrList.back()->getRange().getEnd(),
2468 diag::err_hlsl_missing_resource_class);
2473 Wrapped, ContainedTy, ResAttrs);
2475 if (LocInfo && ContainedTyInfo) {
2488 if (!
T->isHLSLResourceType()) {
2489 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2504 AttributeCommonInfo::AS_CXX11, 0, false ,
2509 case ParsedAttr::AT_HLSLResourceClass: {
2510 StringRef Identifier;
2512 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2517 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2518 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2519 <<
"ResourceClass" << Identifier;
2522 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2526 case ParsedAttr::AT_HLSLResourceDimension: {
2527 StringRef Identifier;
2529 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2533 llvm::dxil::ResourceDimension RD;
2534 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2536 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2537 <<
"ResourceDimension" << Identifier;
2540 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2544 case ParsedAttr::AT_HLSLIsROV:
2548 case ParsedAttr::AT_HLSLRawBuffer:
2552 case ParsedAttr::AT_HLSLIsCounter:
2556 case ParsedAttr::AT_HLSLIsArray:
2560 case ParsedAttr::AT_HLSLIsMultiSampled:
2564 case ParsedAttr::AT_HLSLContainedType: {
2566 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2572 assert(TSI &&
"no type source info for attribute argument");
2574 diag::err_incomplete_type))
2576 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2581 llvm_unreachable(
"unhandled HLSL attribute");
2584 HLSLResourcesTypeAttrs.emplace_back(A);
2590 if (!HLSLResourcesTypeAttrs.size())
2596 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2597 const HLSLAttributedResourceType *RT =
2604 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2606 HLSLResourcesTypeAttrs.clear();
2614 auto I = LocsForHLSLAttributedResources.find(RT);
2615 if (I != LocsForHLSLAttributedResources.end()) {
2616 LocInfo = I->second;
2617 LocsForHLSLAttributedResources.erase(I);
2626void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2627 const RecordType *RT) {
2635 "incomplete arrays inside user defined types are not supported");
2644 if (
const HLSLAttributedResourceType *AttrResType =
2645 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2650 Bindings.addDeclBindingInfo(VD, RC);
2651 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2657 collectResourceBindingsOnUserRecordDecl(VD, RT);
2669 bool SpecifiedSpace) {
2670 int RegTypeNum =
static_cast<int>(RegType);
2673 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2674 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2679 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2680 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2681 : ResourceClass::SRV;
2691 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2695 if (
const HLSLAttributedResourceType *AttrResType =
2696 HLSLAttributedResourceType::findHandleTypeOnResource(
2713 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2714 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2719 if (RegType == RegisterType::CBuffer)
2720 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2721 else if (RegType != RegisterType::C)
2722 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2726 if (RegType == RegisterType::C)
2727 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2729 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2739 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2747 bool RegisterTypesDetected[5] = {
false};
2748 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2751 if (HLSLResourceBindingAttr *
attr =
2752 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2755 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2756 int otherRegTypeNum =
static_cast<int>(otherRegType);
2758 diag::err_hlsl_duplicate_register_annotation)
2762 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2770 bool SpecifiedSpace) {
2775 "expecting VarDecl or HLSLBufferDecl");
2787 const uint64_t &Limit,
2790 uint64_t ArrayCount = 1) {
2795 if (StartSlot > Limit)
2799 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2802 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2803 Count = CAT->
getSize().getZExtValue();
2805 QualType ElemTy = AT->getElementType();
2807 ArrayCount * Count);
2811 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2814 if (ResTy->getAttrs().ResourceClass != ResClass)
2818 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2819 if (EndSlot > Limit)
2823 StartSlot = EndSlot + 1;
2828 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2831 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2834 ResClass, Ctx, ArrayCount))
2841 ResClass, Ctx, ArrayCount))
2855 const uint64_t Limit = UINT32_MAX;
2856 if (SlotNum > Limit)
2861 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2864 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2865 uint64_t BaseSlot = SlotNum;
2873 return (BaseSlot > Limit);
2880 return (SlotNum > Limit);
2883 llvm_unreachable(
"unexpected decl type");
2887 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2889 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2890 Ty = IAT->getElementType();
2892 diag::err_incomplete_type))
2896 StringRef Slot =
"";
2897 StringRef Space =
"";
2901 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2911 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2917 SpaceLoc = Loc->
getLoc();
2920 if (Str.starts_with(
"space")) {
2922 SpaceLoc = Loc->
getLoc();
2931 std::optional<unsigned> SlotNum;
2932 unsigned SpaceNum = 0;
2935 if (!Slot.empty()) {
2937 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2940 if (RegType == RegisterType::I) {
2941 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2944 const StringRef SlotNumStr = Slot.substr(1);
2949 if (SlotNumStr.getAsInteger(10, N)) {
2950 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2958 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2967 if (!Space.starts_with(
"space")) {
2968 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2971 StringRef SpaceNumStr = Space.substr(5);
2972 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2973 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2978 if (SlotNum.has_value())
2983 HLSLResourceBindingAttr *NewAttr =
2984 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2986 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
3010 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
3012 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
3016 Cur = AT->getModifiedType();
3027 ? attr::HLSLRowMajor
3028 : attr::HLSLColumnMajor;
3032 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
3041 if (ExistingKind == AttrK) {
3042 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
3044 Diag(AL.
getLoc(), diag::note_previous_attribute);
3048 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3049 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
3051 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
3056 if (AttrK == attr::HLSLRowMajor)
3057 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
3058 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
3069 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
3071 if (
T.isNull() ||
T->isDependentType())
3076 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3077 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
3085using llvm::dxil::BarrierMemoryTypeFlag;
3086using llvm::dxil::BarrierSemanticFlag;
3088template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
3089 return llvm::to_underlying(Flag);
3103 bool DiagnoseAvailability;
3130 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
3134 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
3135 unsigned CurrentShaderStageBit;
3140 bool ReportOnlyShaderStageIssues;
3143 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
3144 static_assert(
sizeof(
unsigned) >= 4);
3145 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
3146 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
3147 "ShaderType is too big for this bitmap");
3150 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
3151 CurrentShaderEnvironment = ShaderType;
3152 CurrentShaderStageBit = (1 << bitmapIndex);
3155 void SetUnknownShaderStageContext() {
3156 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
3157 CurrentShaderStageBit = (1 << 31);
3160 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
3161 return CurrentShaderEnvironment;
3164 bool InUnknownShaderStageContext()
const {
3165 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
3169 void AddToScannedFunctions(
const FunctionDecl *FD) {
3170 unsigned &ScannedStages = ScannedDecls[FD];
3171 ScannedStages |= CurrentShaderStageBit;
3174 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
3176 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
3177 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
3180 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
3181 return ScannerStages & CurrentShaderStageBit;
3184 static bool NeverBeenScanned(
unsigned ScannedStages) {
3185 return ScannedStages == 0;
3189 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3190 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3192 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3193 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3194 void DiagnoseBarrierCall(CallExpr *CE);
3195 uint64_t DiagnoseBarrierGroupMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3196 bool HasVisibleGroup,
bool IsAllMemory);
3197 uint64_t DiagnoseBarrierNodeMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3198 bool HasKnownStage,
bool IsAllMemory);
3199 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg, uint64_t SemanticFlags,
3200 bool HasVisibleGroup);
3201 void DiagnoseBarrierScope(Expr *SemanticArg, uint64_t MemoryFlags,
3202 uint64_t SemanticFlags);
3205 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3206 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3207 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3208 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3211 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3212 void RunOnFunction(
const FunctionDecl *FD);
3214 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3215 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3217 HandleFunctionOrMethodRef(FD, DRE);
3221 bool VisitMemberExpr(MemberExpr *ME)
override {
3222 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3224 HandleFunctionOrMethodRef(FD, ME);
3228 bool VisitCallExpr(CallExpr *CE)
override {
3229 DiagnoseBarrierCall(CE);
3234uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3235 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasVisibleGroup,
3238 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3239 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3244 diag::err_hlsl_barrier_flag_requires_group)
3249 return MemoryFlags & ~GroupSharedMemory;
3252uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3253 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasKnownStage,
3256 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3257 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3262 diag::err_hlsl_barrier_node_memory_requires_node);
3266 return MemoryFlags & ~NodeMemory;
3269void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3270 Expr *SemanticArg, uint64_t SemanticFlags,
bool HasVisibleGroup) {
3271 if (HasVisibleGroup ||
3272 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3276 diag::err_hlsl_barrier_flag_requires_group)
3277 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3283void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3284 uint64_t MemoryFlags,
3285 uint64_t SemanticFlags) {
3286 if (ReportOnlyShaderStageIssues)
3290 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3291 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3292 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3294 (MemoryFlags & DeviceScopeMemory) == 0)
3296 diag::err_hlsl_barrier_scope_requires_memory)
3298 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3302 diag::err_hlsl_barrier_scope_requires_memory)
3306void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3308 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3311 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3312 const bool HasKnownStage = !InUnknownShaderStageContext();
3313 const bool HasVisibleGroup =
3314 !HasKnownStage || Stage == llvm::Triple::Compute ||
3315 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3317 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3320 std::optional<llvm::APSInt>
Value =
3324 MemoryFlags =
Value->getZExtValue();
3325 const bool IsAllMemory =
3326 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3328 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3329 HasVisibleGroup, IsAllMemory);
3330 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3331 HasKnownStage, IsAllMemory);
3332 }
else if (!HasVisibleGroup) {
3334 diag::err_hlsl_barrier_resource_requires_group);
3339 std::optional<llvm::APSInt>
Value =
3345 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3348 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3351void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3354 "expected DeclRefExpr or MemberExpr");
3356 if (DiagnoseAvailability)
3357 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3358 CheckDeclAvailability(
3363 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3364 DeclsToScan.push_back(FDWithBody);
3367void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3372 llvm::Triple::EnvironmentType::Library;
3381 DeclContextsToScan.push_back(TU);
3383 while (!DeclContextsToScan.empty()) {
3384 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3385 for (
auto &D : DC->
decls()) {
3392 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3393 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3398 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3403 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3404 if (!IsLibraryShader && FD->
getName() == EntryName) {
3407 diag::err_hlsl_ambiguous_entry_point)
3409 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3415 SetShaderStageContext(ShaderAttr->getType());
3424 for (
const auto *Redecl : FD->
redecls()) {
3425 if (Redecl->isInExportDeclContext()) {
3432 SetUnknownShaderStageContext();
3439 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3446void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3447 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3448 DeclsToScan.push_back(FD);
3450 while (!DeclsToScan.empty()) {
3458 const unsigned ScannedStages = GetScannedStages(FD);
3459 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3462 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3464 AddToScannedFunctions(FD);
3469bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3470 const AvailabilityAttr *AA) {
3475 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3476 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3479 llvm::Triple::EnvironmentType AttrEnv =
3480 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3482 return CurrentEnv == AttrEnv;
3485const AvailabilityAttr *
3486DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3487 AvailabilityAttr
const *PartialMatch =
nullptr;
3491 for (
const auto *A : D->
attrs()) {
3492 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3493 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3494 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3495 StringRef TargetPlatform =
3499 if (AttrPlatform == TargetPlatform) {
3501 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3503 PartialMatch = Avail;
3507 return PartialMatch;
3512void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3513 const AvailabilityAttr *AA,
3532 if (ReportOnlyShaderStageIssues)
3538 if (InUnknownShaderStageContext())
3543 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3544 VersionTuple Introduced = AA->getIntroduced();
3553 llvm::StringRef PlatformName(
3556 llvm::StringRef CurrentEnvStr =
3557 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3559 llvm::StringRef AttrEnvStr =
3560 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3561 bool UseEnvironment = !AttrEnvStr.empty();
3563 if (EnvironmentMatches) {
3564 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3565 <<
Range << D << PlatformName << Introduced.getAsString()
3566 << UseEnvironment << CurrentEnvStr;
3568 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3572 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3573 << D << PlatformName << Introduced.getAsString()
3575 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3582 if (!DefaultCBufferDecls.empty()) {
3585 DefaultCBufferDecls);
3588 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3592 for (
const Decl *VD : DefaultCBufferDecls) {
3593 const HLSLResourceBindingAttr *RBA =
3594 VD->
getAttr<HLSLResourceBindingAttr>();
3595 if (RBA && RBA->hasRegisterSlot() &&
3596 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3603 SemaRef.Consumer.HandleTopLevelDecl(DG);
3605 diagnoseAvailabilityViolations(TU);
3614 "expected member expr to have resource record type or array of them");
3620 const Expr *NonConstIndexExpr =
nullptr;
3623 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3624 if (!NonConstIndexExpr)
3632 diag::err_hlsl_resource_member_array_access_not_constant);
3636 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3637 const Expr *IdxExpr = ASE->getIdx();
3639 NonConstIndexExpr = IdxExpr;
3641 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3642 E = SubME->getBase();
3643 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3644 E = ICE->getSubExpr();
3646 llvm_unreachable(
"unexpected expr type in resource member access");
3655 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3658 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3661 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3665 [[maybe_unused]]
bool LookupSucceeded =
3666 SemaRef.LookupQualifiedName(ConvR, RD);
3667 assert(LookupSucceeded);
3676std::optional<ExprResult>
3679 const HLSLAttributedResourceType *ResTy =
3680 HLSLAttributedResourceType::findHandleTypeOnResource(
3681 BaseType.getTypePtr());
3683 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3684 return std::nullopt;
3686 QualType TemplateType = ResTy->getContainedType();
3690 assert(NamedConversionDecl &&
3691 "Could not find conversion function for ConstantBuffer.");
3692 auto *ConversionDecl =
3695 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3705 const bool DiagnoseAvailability =
3707 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3708 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3709 .RunOnTranslationUnit(TU);
3716 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3719 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3744 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3757 if (!BaseType->isFloat32Type())
3758 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3759 << ArgOrdinal << 5 << 0
3769 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3770 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3771 << ArgOrdinal << 5 << 0
3780 if (!BaseType->isDoubleType()) {
3783 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3784 << ArgOrdinal << PassedType;
3791 unsigned ArgIndex) {
3792 auto *Arg = TheCall->
getArg(ArgIndex);
3794 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3797 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3811 << (ArgIndex + 1) << LValueTy;
3821 if (VecTy->getElementType()->isDoubleType())
3822 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3823 << ArgOrdinal << 1 << 0 << 1
3833 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3834 << ArgOrdinal << 5 << 1
3843 if (VecTy->getElementType()->isUnsignedIntegerType())
3846 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3847 << ArgOrdinal << 4 << 3 << 0
3856 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3857 << ArgOrdinal << 5 << 3
3863 unsigned ArgOrdinal,
unsigned Width) {
3866 ArgTy = VTy->getElementType();
3868 uint64_t ElementBitCount =
3870 if (ElementBitCount != Width) {
3872 diag::err_integer_incorrect_bit_count)
3873 << Width << ElementBitCount;
3884 else if (
auto *MatTyA =
3887 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3893 unsigned ArgIndex) {
3902 diag::err_typecheck_expect_scalar_or_vector)
3903 << ArgType << Scalar;
3910 QualType Scalar,
unsigned ArgIndex) {
3921 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3934 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3935 << ArgType << Scalar;
3940 unsigned ArgIndex) {
3945 if (!(ArgType->isScalarType() ||
3946 (VTy && VTy->getElementType()->isScalarType()))) {
3948 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3956 unsigned ArgIndex) {
3959 if (ArgType->isDependentType())
3963 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3964 ElementType = VectorTy->getElementType();
3966 ElementType = MatrixTy->getElementType();
3968 if (ElementType->isBooleanType())
3971 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3973 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3978 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3986 unsigned ArgIndex) {
3988 assert(ArgIndex < TheCall->getNumArgs());
3996 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4021 diag::err_typecheck_call_different_arg_types)
4040 Arg1ScalarTy = VTy->getElementType();
4044 Arg2ScalarTy = VTy->getElementType();
4047 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4048 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4058 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
4060 diag::err_typecheck_vector_lengths_not_equal)
4066 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
4068 diag::err_typecheck_vector_lengths_not_equal)
4088 Arg1ScalarTy = MTy->getElementType();
4092 Arg2ScalarTy = MTy->getElementType();
4095 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4096 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4101 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
4103 for (
Expr *Arg : {Arg1, Arg2}) {
4106 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
4108 diag::err_typecheck_vector_lengths_not_equal)
4110 << Arg->getSourceRange();
4126 unsigned ArgIndex) {
4131 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
4134 unsigned int ActualDim = 1;
4136 ActualDim = VTy->getNumElements();
4137 IndexTy = VTy->getElementType();
4141 diag::err_typecheck_expect_int)
4147 const HLSLAttributedResourceType *ResTy =
4149 assert(ResTy &&
"Resource argument must be a resource");
4150 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
4152 unsigned int ExpectedDim = 1;
4153 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
4155 (ResAttrs.IsArray ? 1 : 0);
4157 if (ActualDim != ExpectedDim) {
4159 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
4170 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
4174 const HLSLAttributedResourceType *ResTy =
4178 diag::err_typecheck_expect_hlsl_resource)
4182 if (Check && Check(ResTy)) {
4184 diag::err_invalid_hlsl_resource_type)
4194 "expected resource handle type");
4195 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4196 auto MainAttrs = MainResType->getAttrs();
4197 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4198 MainAttrs.IsCounter =
true;
4200 MainResType->getContainedType(),
4211 return "SampleBias";
4213 return "SampleGrad";
4215 return "SampleLevel";
4219 return "SampleCmpLevelZero";
4221 llvm_unreachable(
"Invalid SampleKind");
4231 if (!MD || !MD->getDeclName().isIdentifier())
4238 return MD->getName();
4246 StringRef DefaultName) {
4251 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4278 if (SMVersion >= VersionTuple(6, 7))
4281 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4283 << ContainedType << SMVersion.getAsString();
4288 bool IncludeArraySlice =
true) {
4291 [](
const HLSLAttributedResourceType *ResType) {
4292 return ResType->getAttrs().ResourceDimension ==
4293 llvm::dxil::ResourceDimension::Unknown;
4299 [](
const HLSLAttributedResourceType *ResType) {
4300 return ResType->getAttrs().ResourceClass !=
4301 llvm::hlsl::ResourceClass::Sampler;
4309 unsigned ExpectedDim =
4311 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4340 unsigned NextIdx = 3;
4352 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4356 std::optional<llvm::APSInt> ComponentOpt =
4359 int64_t ComponentVal = ComponentOpt->getSExtValue();
4360 if (ComponentVal != 0) {
4363 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4364 "The component is not in the expected range.");
4366 diag::err_hlsl_gathercmp_invalid_component)
4376 const HLSLAttributedResourceType *ResourceTy =
4379 unsigned ExpectedDim =
4382 &S, TheCall->
getArg(NextIdx),
4388 assert(ResourceTy->hasContainedType() &&
4389 "Expecting a contained type for resource with a dimension "
4391 QualType ReturnType = ResourceTy->getContainedType();
4394 IsCmp ?
"GatherCmp" :
"Gather"))
4399 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4405 ReturnType = VecTy->getElementType();
4418 [](
const HLSLAttributedResourceType *ResType) {
4419 return ResType->getAttrs().ResourceDimension ==
4420 llvm::dxil::ResourceDimension::Unknown;
4430 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4437 unsigned ResourceDim =
4439 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4455 TheCall->
setType(ResourceTy->getContainedType());
4465 [](
const HLSLAttributedResourceType *ResType) {
4466 return !ResType->isMultiSampled();
4475 unsigned ResourceDim =
4477 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4495 TheCall->
setType(ResourceTy->getContainedType());
4500 unsigned MinArgs, MaxArgs;
4528 const HLSLAttributedResourceType *ResourceTy =
4530 unsigned ExpectedDim =
4533 unsigned NextIdx = 3;
4558 &S, TheCall->
getArg(NextIdx),
4571 assert(ResourceTy->hasContainedType() &&
4572 "Expecting a contained type for resource with a dimension "
4574 QualType ReturnType = ResourceTy->getContainedType();
4585 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4602 unsigned MinArgs,
unsigned MaxArgs,
4604 bool ReportsOriginalValue) {
4605 if (MinArgs == MaxArgs) {
4608 }
else if (TheCall->
getNumArgs() < MinArgs) {
4609 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4619 const bool DestIsOK =
4625 diag::err_builtin_invalid_arg_type)
4639 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4655 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4661 const unsigned NumArgs = TheCall->
getNumArgs();
4662 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4673 switch (BuiltinID) {
4674 case Builtin::BI__builtin_hlsl_barrier: {
4675 if (
SemaRef.checkArgCount(TheCall, 2))
4678 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4679 llvm::Triple::dxil) {
4687 std::optional<llvm::APSInt> MemoryFlags =
4691 diag::err_constant_integer_arg_type)
4695 if ((MemoryFlags->getZExtValue() &
4696 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4698 diag::err_hlsl_invalid_barrier_memory_flags);
4702 const HLSLAttributedResourceType *ResTy =
4703 HLSLAttributedResourceType::findHandleTypeOnResource(
4707 diag::err_typecheck_expect_hlsl_resource)
4711 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4713 diag::err_invalid_hlsl_resource_type)
4720 std::optional<llvm::APSInt> SemanticFlags =
4722 if (!SemanticFlags) {
4724 diag::err_constant_integer_arg_type)
4728 if ((SemanticFlags->getZExtValue() &
4729 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4731 diag::err_hlsl_invalid_barrier_semantic_flags);
4738 case Builtin::BI__builtin_hlsl_adduint64: {
4739 if (
SemaRef.checkArgCount(TheCall, 2))
4753 if (NumElementsArg != 2 && NumElementsArg != 4) {
4755 << 1 << 64 << NumElementsArg * 32;
4769 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4770 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4777 QualType ContainedTy = ResourceTy->getContainedType();
4778 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4781 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4786 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4787 if (
SemaRef.checkArgCount(TheCall, 3) ||
4794 "expected pointer type for second argument");
4801 diag::err_invalid_use_of_array_type);
4805 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4808 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4813 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4814 if (
SemaRef.checkArgCount(TheCall, 2) ||
4816 SemaRef.getASTContext().IntTy))
4823 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4824 if (
SemaRef.checkArgCount(TheCall, 3) ||
4827 SemaRef.getASTContext().UnsignedIntTy) ||
4829 SemaRef.getASTContext().UnsignedIntTy) ||
4835 QualType ReturnType = ResourceTy->getContainedType();
4840 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4841 if (
SemaRef.checkArgCount(TheCall, 4) ||
4844 SemaRef.getASTContext().UnsignedIntTy) ||
4846 SemaRef.getASTContext().UnsignedIntTy) ||
4852 "expected pointer type for second argument");
4859 diag::err_invalid_use_of_array_type);
4865 case Builtin::BI__builtin_hlsl_resource_load_level:
4867 case Builtin::BI__builtin_hlsl_resource_load_ms:
4869 case Builtin::BI__builtin_hlsl_resource_sample:
4871 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4873 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4875 case Builtin::BI__builtin_hlsl_resource_sample_level:
4877 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4879 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4881 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4882 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4884 case Builtin::BI__builtin_hlsl_resource_gather:
4886 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4888 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4889 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4895 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4896 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4902 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4903 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4909 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4910 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4916 TheCall->
setType(CounterHandleTy);
4919 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4920 if (
SemaRef.checkArgCount(TheCall, 2) ||
4923 SemaRef.getASTContext().UnsignedIntTy))
4931 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4932 if (
SemaRef.checkArgCount(TheCall, 1) ||
4940 TheCall->
setType(CounterHandleTy);
4943 case Builtin::BI__builtin_hlsl_and:
4944 case Builtin::BI__builtin_hlsl_or: {
4945 if (
SemaRef.checkArgCount(TheCall, 2))
4959 case Builtin::BI__builtin_hlsl_all:
4960 case Builtin::BI__builtin_hlsl_any: {
4961 if (
SemaRef.checkArgCount(TheCall, 1))
4967 case Builtin::BI__builtin_hlsl_asdouble: {
4968 if (
SemaRef.checkArgCount(TheCall, 2))
4972 SemaRef.Context.UnsignedIntTy,
4977 SemaRef.Context.UnsignedIntTy,
4986 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4987 if (
SemaRef.BuiltinElementwiseTernaryMath(
4993 case Builtin::BI__builtin_hlsl_dot: {
4995 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
5001 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
5002 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
5003 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5013 EltTy = VecTy->getElementType();
5014 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
5027 case Builtin::BI__builtin_hlsl_select: {
5028 if (
SemaRef.checkArgCount(TheCall, 3))
5037 if (VTy && VTy->getElementType()->isBooleanType() &&
5041 if (MTy && MTy->getElementType()->isBooleanType() &&
5046 case Builtin::BI__builtin_hlsl_elementwise_saturate:
5047 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
5048 if (
SemaRef.checkArgCount(TheCall, 1))
5054 diag::err_builtin_invalid_arg_type)
5057 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5061 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
5062 case Builtin::BI__builtin_hlsl_elementwise_frac:
5063 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
5064 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
5065 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
5066 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
5067 if (
SemaRef.checkArgCount(TheCall, 1))
5072 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5076 case Builtin::BI__builtin_hlsl_elementwise_isfinite:
5077 case Builtin::BI__builtin_hlsl_elementwise_isinf:
5078 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
5079 if (
SemaRef.checkArgCount(TheCall, 1))
5084 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5089 case Builtin::BI__builtin_hlsl_mad: {
5090 if (
SemaRef.BuiltinElementwiseTernaryMath(
5096 case Builtin::BI__builtin_hlsl_mul: {
5097 if (
SemaRef.checkArgCount(TheCall, 2))
5107 return VTy->getElementType();
5109 return MTy->getElementType();
5113 QualType EltTy0 = getElemType(Ty0);
5122 if (IsVec0 && IsMat1) {
5125 }
else if (IsMat0 && IsVec1) {
5129 assert(IsMat0 && IsMat1);
5139 case Builtin::BI__builtin_elementwise_fma: {
5140 if (
SemaRef.checkArgCount(TheCall, 3) ||
5155 case Builtin::BI__builtin_hlsl_transpose: {
5156 if (
SemaRef.checkArgCount(TheCall, 1))
5165 << 1 << 3 << 0 << 0 << ArgTy;
5170 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
5174 case Builtin::BI__builtin_hlsl_elementwise_sign: {
5175 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5183 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5184 if (
SemaRef.checkArgCount(TheCall, 1))
5198 unsigned NumElts = VecTy->getNumElements();
5208 case Builtin::BI__builtin_hlsl_wave_active_max:
5209 case Builtin::BI__builtin_hlsl_wave_active_min:
5210 case Builtin::BI__builtin_hlsl_wave_active_sum:
5211 case Builtin::BI__builtin_hlsl_wave_active_product: {
5212 if (
SemaRef.checkArgCount(TheCall, 1))
5225 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5226 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5227 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5228 if (
SemaRef.checkArgCount(TheCall, 1))
5243 (VTy && VTy->getElementType()->isIntegerType()))) {
5245 diag::err_builtin_invalid_arg_type)
5246 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5254 case Builtin::BI__builtin_hlsl_interlocked_add:
5255 case Builtin::BI__builtin_hlsl_interlocked_and:
5256 case Builtin::BI__builtin_hlsl_interlocked_max:
5257 case Builtin::BI__builtin_hlsl_interlocked_min:
5258 case Builtin::BI__builtin_hlsl_interlocked_or:
5259 case Builtin::BI__builtin_hlsl_interlocked_xor:
5265 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5271 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5277 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5283 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5289 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5297 case Builtin::BI__builtin_elementwise_bitreverse: {
5305 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
5306 if (
SemaRef.checkArgCount(TheCall, 1))
5311 if (!(
ArgType->isScalarType())) {
5313 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5318 if (!(
ArgType->isBooleanType())) {
5320 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5327 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5328 if (
SemaRef.checkArgCount(TheCall, 2))
5336 diag::err_typecheck_convert_incompatible)
5337 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5350 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5351 if (
SemaRef.checkArgCount(TheCall, 1))
5360 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5361 if (
SemaRef.checkArgCount(TheCall, 0))
5365 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5366 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5367 if (
SemaRef.checkArgCount(TheCall, 1))
5380 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5381 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5382 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5383 if (
SemaRef.checkArgCount(TheCall, 1))
5395 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5396 if (
SemaRef.checkArgCount(TheCall, 3))
5402 SemaRef.Context.UnsignedIntTy, 1) ||
5404 SemaRef.Context.UnsignedIntTy, 2))
5412 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5413 if (
SemaRef.checkArgCount(TheCall, 1))
5420 case Builtin::BI__builtin_elementwise_acos:
5421 case Builtin::BI__builtin_elementwise_asin:
5422 case Builtin::BI__builtin_elementwise_atan:
5423 case Builtin::BI__builtin_elementwise_atan2:
5424 case Builtin::BI__builtin_elementwise_ceil:
5425 case Builtin::BI__builtin_elementwise_cos:
5426 case Builtin::BI__builtin_elementwise_cosh:
5427 case Builtin::BI__builtin_elementwise_exp:
5428 case Builtin::BI__builtin_elementwise_exp2:
5429 case Builtin::BI__builtin_elementwise_exp10:
5430 case Builtin::BI__builtin_elementwise_floor:
5431 case Builtin::BI__builtin_elementwise_fmod:
5432 case Builtin::BI__builtin_elementwise_log:
5433 case Builtin::BI__builtin_elementwise_log2:
5434 case Builtin::BI__builtin_elementwise_log10:
5435 case Builtin::BI__builtin_elementwise_pow:
5436 case Builtin::BI__builtin_elementwise_roundeven:
5437 case Builtin::BI__builtin_elementwise_sin:
5438 case Builtin::BI__builtin_elementwise_sinh:
5439 case Builtin::BI__builtin_elementwise_sqrt:
5440 case Builtin::BI__builtin_elementwise_tan:
5441 case Builtin::BI__builtin_elementwise_tanh:
5442 case Builtin::BI__builtin_elementwise_trunc: {
5448 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5449 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5450 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5451 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5452 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5457 std::optional<llvm::APSInt> Offset =
5459 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5461 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5467 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5468 if (
SemaRef.checkArgCount(TheCall, 1))
5479 ArgTy = VTy->getElementType();
5482 diag::err_builtin_invalid_arg_type)
5491 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5492 if (
SemaRef.checkArgCount(TheCall, 1))
5507 WorkList.push_back(BaseTy);
5508 while (!WorkList.empty()) {
5510 T =
T.getCanonicalType().getUnqualifiedType();
5511 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5519 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5520 llvm::append_range(List, ElementFields);
5525 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5526 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5529 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5530 List.insert(List.end(), MT->getNumElementsFlattened(),
5531 MT->getElementType());
5534 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5535 if (RD->isStandardLayout())
5536 RD = RD->getStandardLayoutBaseWithFields();
5540 if (RD->
isUnion() || !RD->isAggregate()) {
5546 for (
const auto *FD : RD->
fields())
5547 if (!FD->isUnnamedBitField())
5548 FieldTypes.push_back(FD->
getType());
5550 std::reverse(FieldTypes.begin(), FieldTypes.end());
5551 llvm::append_range(WorkList, FieldTypes);
5555 if (!RD->isStandardLayout()) {
5557 for (
const auto &
Base : RD->bases())
5558 FieldTypes.push_back(
Base.getType());
5559 std::reverse(FieldTypes.begin(), FieldTypes.end());
5560 llvm::append_range(WorkList, FieldTypes);
5595 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5601 int ArraySize = VT->getNumElements();
5606 QualType ElTy = VT->getElementType();
5610 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5626 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5635 return llvm::equal(T1Types, T2Types,
5637 return SemaRef.IsLayoutCompatible(LHS, RHS);
5646 bool HadError =
false;
5648 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5656 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5657 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5658 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5659 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5661 if (NSpellingIdx != OSpellingIdx) {
5663 diag::err_hlsl_param_qualifier_mismatch)
5664 << NDAttr << NewParam;
5680 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5695 llvm_unreachable(
"HLSL doesn't support pointers.");
5698 llvm_unreachable(
"HLSL doesn't support complex types.");
5700 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5702 llvm_unreachable(
"Should have returned before this");
5712 llvm_unreachable(
"HLSL doesn't support complex types.");
5714 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5719 llvm_unreachable(
"HLSL doesn't support pointers.");
5721 llvm_unreachable(
"Should have returned before this");
5727 llvm_unreachable(
"HLSL doesn't support pointers.");
5730 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5734 llvm_unreachable(
"HLSL doesn't support complex types.");
5737 llvm_unreachable(
"Unhandled scalar cast");
5758 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5764 SrcTy = SrcMatTy->getElementType();
5769 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5770 if (DestTypes[I]->isUnionType())
5802 if (SrcTypes.size() < DestTypes.size())
5805 unsigned SrcSize = SrcTypes.size();
5806 unsigned DstSize = DestTypes.size();
5808 for (I = 0; I < DstSize && I < SrcSize; I++) {
5809 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5817 for (; I < SrcSize; I++) {
5818 if (SrcTypes[I]->isUnionType())
5861 tok::equal, ArgOpV, OpV);
5873 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5874 "We should not get here without a parameter modifier expression");
5875 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5882 << Arg << (IsInOut ? 1 : 0);
5886 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5893 << Arg << (IsInOut ? 1 : 0);
5901 Param->getBeginLoc(), IsInOut);
5909 "Pointer and reference types cannot be inout or out parameters");
5910 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5926 for (
const auto *FD : RD->
fields()) {
5930 assert(RD->getNumBases() <= 1 &&
5931 "HLSL doesn't support multiple inheritance");
5932 return RD->getNumBases()
5937 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5938 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5950 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5955 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5961 if (
Decl->getType().hasAddressSpace())
5964 if (
Decl->getType()->isDependentType())
5976 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5990 llvm::Triple::Vulkan;
5991 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5992 if (HasDeclaredAPushConstant)
5998 HasDeclaredAPushConstant =
true;
6025class StructBindingContext {
6028 HLSLResourceBindingAttr *RegBindingsAttrs[4];
6029 unsigned RegBindingOffset[4];
6032 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
6033 static_cast<unsigned>(RegisterType::UAV) == 1 &&
6034 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
6035 static_cast<unsigned>(RegisterType::Sampler) == 3,
6036 "unexpected register type values");
6039 HLSLVkBindingAttr *VkBindingAttr;
6040 unsigned VkBindingOffset;
6045 StructBindingContext(
VarDecl *VD) {
6046 for (
unsigned i = 0; i < 4; ++i) {
6047 RegBindingsAttrs[i] =
nullptr;
6048 RegBindingOffset[i] = 0;
6050 VkBindingAttr =
nullptr;
6051 VkBindingOffset = 0;
6057 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
6059 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
6062 RegBindingsAttrs[RegTypeIdx] = RBA;
6067 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
6068 VkBindingAttr = VBA;
6075 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
6076 unsigned Range,
bool HasCounter) {
6077 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
6079 if (VkBindingAttr) {
6080 unsigned Offset = VkBindingOffset;
6081 VkBindingOffset +=
Range;
6082 return HLSLVkBindingAttr::CreateImplicit(
6083 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
6084 VkBindingAttr->getRange());
6087 HLSLResourceBindingAttr *RBA =
6088 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6089 HLSLResourceBindingAttr *NewAttr =
nullptr;
6091 if (RBA && RBA->hasRegisterSlot()) {
6094 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6095 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6097 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6098 StringRef NewSlotNumberStr =
6100 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6101 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6102 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6106 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6107 NewAttr->setBinding(RegType, std::nullopt,
6108 RBA ? RBA->getSpaceNumber() : 0);
6112 NewAttr->setImplicitCounterBindingOrderID(
6121static void createGlobalResourceDeclForStruct(
6123 QualType ResTy, StructBindingContext &BindingCtx) {
6125 "expected resource type or array of resources");
6136 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6137 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6142 const HLSLAttributedResourceType *ResHandleTy =
6143 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6147 Attr *BindingAttr = BindingCtx.createBindingAttr(
6149 ResDecl->
addAttr(BindingAttr);
6150 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6159 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6166static void handleArrayOfStructWithResources(
6168 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6173static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6175 EmbeddedResourceNameBuilder &NameBuilder,
6176 StructBindingContext &BindingCtx) {
6179 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6186 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6200 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6203 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6205 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6207 "resource arrays should have been already handled");
6208 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6217handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6219 EmbeddedResourceNameBuilder &NameBuilder,
6220 StructBindingContext &BindingCtx) {
6228 if (!SubCAT && !ElementRD)
6231 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6234 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6237 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6250void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6251 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6252 StructBindingContext BindingCtx(VD);
6256 "Expected non-resource struct or array type");
6259 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6263 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6264 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6272 if (
SemaRef.RequireCompleteType(
6275 diag::err_typecheck_decl_incomplete_type)) {
6289 DefaultCBufferDecls.push_back(VD);
6294 collectResourceBindingsOnVarDecl(VD);
6296 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6308 processExplicitBindingsOnDecl(VD);
6346 handleGlobalStructOrArrayOfWithResources(VD);
6350 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6359 "expected resource record type");
6375 const char *CreateMethodName;
6377 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6378 :
"__createFromBinding";
6380 CreateMethodName = HasCounter
6381 ?
"__createFromImplicitBindingWithImplicitCounter"
6382 :
"__createFromImplicitBinding";
6387 if (!CreateMethod) {
6392 "create method lookup should always succeed for built-in resource "
6401 Args.push_back(RegSlot);
6409 Args.push_back(OrderId);
6415 Args.push_back(Space);
6419 Args.push_back(RangeSize);
6423 Args.push_back(Index);
6425 StringRef VarName = VD->
getName();
6433 Args.push_back(NameCast);
6441 Args.push_back(CounterId);
6464 SemaRef.CheckCompleteVariableDeclaration(VD);
6470 "expected array of resource records");
6491 lookupMethod(
SemaRef, ResourceDecl,
6492 HasCounter ?
"__createFromBindingWithImplicitCounter"
6493 :
"__createFromBinding",
6497 CreateMethod = lookupMethod(
6499 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6500 :
"__createFromImplicitBinding",
6543std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6544 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6545 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6546 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6547 if (!TrueInfo || !FalseInfo)
6548 return std::nullopt;
6549 if (*TrueInfo != *FalseInfo)
6550 return std::nullopt;
6554 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6563 if (
const auto *AttrResType =
6564 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6566 return Bindings.getDeclBindingInfo(VD, RC);
6573void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6574 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6577 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6582 if (*ExprBinding ==
nullptr)
6585 auto PrevBinding = Assigns.find(VD);
6586 if (PrevBinding == Assigns.end()) {
6588 Assigns.insert({VD, *ExprBinding});
6593 if (*ExprBinding != PrevBinding->second) {
6595 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6597 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6608 "expected LHS to be a resource record or array of resource records");
6609 if (Opc != BO_Assign)
6614 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6622 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6627 trackLocalResource(VD, RHSExpr);
6644void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6646 "expected global variable that contains HLSL resource");
6649 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6650 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6651 ? ResourceClass::CBuffer
6652 : ResourceClass::SRV);
6665 if (
const HLSLAttributedResourceType *AttrResType =
6666 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6667 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6672 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6673 collectResourceBindingsOnUserRecordDecl(VD, RT);
6679void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6682 bool HasBinding =
false;
6683 for (Attr *A : VD->
attrs()) {
6686 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6687 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6690 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6691 if (!RBA || !RBA->hasRegisterSlot())
6696 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6697 "never have an attribute created");
6699 if (RT == RegisterType::C) {
6700 if (Bindings.hasBindingInfoForDecl(VD))
6702 diag::warn_hlsl_user_defined_type_missing_member)
6703 <<
static_cast<int>(RT);
6711 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6716 diag::warn_hlsl_user_defined_type_missing_member)
6717 <<
static_cast<int>(RT);
6725class InitListTransformer {
6729 QualType *DstIt =
nullptr;
6730 Expr **ArgIt =
nullptr;
6736 bool castInitializer(Expr *E) {
6737 assert(DstIt &&
"This should always be something!");
6738 if (DstIt == DestTypes.end()) {
6740 ArgExprs.push_back(E);
6745 DstIt = DestTypes.begin();
6748 Ctx, *DstIt,
false);
6753 ArgExprs.push_back(
Init);
6758 bool buildInitializerListImpl(Expr *E) {
6760 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6761 for (
auto *SubInit :
Init->inits())
6762 if (!buildInitializerListImpl(SubInit))
6772 return castInitializer(E);
6786 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6791 for (uint64_t I = 0; I <
Size; ++I) {
6793 SizeTy, SourceLocation());
6799 if (!castInitializer(ElExpr.
get()))
6804 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6805 unsigned Rows = MTy->getNumRows();
6806 unsigned Cols = MTy->getNumColumns();
6807 QualType ElemTy = MTy->getElementType();
6809 for (
unsigned R = 0;
R < Rows; ++
R) {
6810 for (
unsigned C = 0;
C < Cols; ++
C) {
6823 if (!castInitializer(ElExpr.
get()))
6831 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6835 for (uint64_t I = 0; I <
Size; ++I) {
6837 SizeTy, SourceLocation());
6842 if (!buildInitializerListImpl(ElExpr.
get()))
6849 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6850 RecordDecls.push_back(RD);
6851 while (RecordDecls.back()->getNumBases()) {
6852 CXXRecordDecl *D = RecordDecls.back();
6854 "HLSL doesn't support multiple inheritance");
6855 RecordDecls.push_back(
6858 while (!RecordDecls.empty()) {
6859 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6860 for (
auto *FD : RD->
fields()) {
6861 if (FD->isUnnamedBitField())
6869 if (!buildInitializerListImpl(Res.
get()))
6877 Expr *generateInitListsImpl(QualType Ty) {
6879 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6884 llvm::SmallVector<Expr *>
Inits;
6889 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6890 ElTy = ATy->getElementType();
6891 Size = ATy->getNumElements();
6892 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6893 ElTy = CMTy->getElementType();
6894 Size = CMTy->getNumElementsFlattened();
6897 ElTy = VTy->getElementType();
6898 Size = VTy->getZExtSize();
6900 for (uint64_t I = 0; I <
Size; ++I)
6901 Inits.push_back(generateInitListsImpl(ElTy));
6904 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6905 RecordDecls.push_back(RD);
6906 while (RecordDecls.back()->getNumBases()) {
6907 CXXRecordDecl *D = RecordDecls.back();
6909 "HLSL doesn't support multiple inheritance");
6910 RecordDecls.push_back(
6913 while (!RecordDecls.empty()) {
6914 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6915 for (
auto *FD : RD->
fields())
6916 if (!FD->isUnnamedBitField())
6921 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6922 Inits.back()->getEndLoc(),
false);
6923 NewInit->setType(Ty);
6928 llvm::SmallVector<QualType, 16> DestTypes;
6929 llvm::SmallVector<Expr *, 16> ArgExprs;
6930 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6931 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6932 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6933 InitTy = Entity.
getType().getNonReferenceType();
6943 DstIt = DestTypes.begin();
6946 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6948 Expr *generateInitLists() {
6949 assert(!ArgExprs.empty() &&
6950 "Call buildInitializerList to generate argument expressions.");
6951 ArgIt = ArgExprs.begin();
6953 return generateInitListsImpl(InitTy);
6954 llvm::SmallVector<Expr *>
Inits;
6955 while (ArgIt != ArgExprs.end())
6956 Inits.push_back(generateInitListsImpl(InitTy));
6959 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6960 Inits.back()->getEndLoc(),
false);
6961 llvm::APInt ArySize(64,
Inits.size());
6963 ArraySizeModifier::Normal, 0));
6975 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6982 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6986 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
7006 if (
Init->getType()->isScalarType())
7009 InitListTransformer ILT(
SemaRef, Entity);
7011 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
7019 Init->setInit(I, E);
7021 if (!ILT.buildInitializerList(E))
7024 size_t ExpectedSize = ILT.DestTypes.size();
7025 size_t ActualSize = ILT.ArgExprs.size();
7026 if (ExpectedSize == 0 && ActualSize == 0)
7033 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7035 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7036 << (int)(ExpectedSize < ActualSize) << InitTy
7037 << ExpectedSize << ActualSize;
7047 assert(ExpectedSize > 0 &&
7048 "The expected size of an incomplete array type must be at least 1.");
7050 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
7058 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7059 if (ExpectedSize != ActualSize) {
7060 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
7061 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7062 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
7069 Init->resizeInits(Ctx, NewInit->getNumInits());
7070 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
7071 Init->updateInit(Ctx, I, NewInit->getInit(I));
7079 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7089 StringRef AccessorName = CompName->
getName();
7090 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7092 unsigned Rows = MT->getNumRows();
7093 unsigned Cols = MT->getNumColumns();
7094 bool IsZeroBasedAccessor =
false;
7095 unsigned ChunkLen = 0;
7096 if (AccessorName.size() < 2)
7098 "length 4 for zero based: \'_mRC\' or "
7099 "length 3 for one-based: \'_RC\' accessor",
7102 if (AccessorName[0] ==
'_') {
7103 if (AccessorName[1] ==
'm') {
7104 IsZeroBasedAccessor =
true;
7111 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7114 if (AccessorName.size() % ChunkLen != 0) {
7115 const llvm::StringRef
Expected = IsZeroBasedAccessor
7116 ?
"zero based: '_mRC' accessor"
7117 :
"one-based: '_RC' accessor";
7122 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7123 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7124 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7126 bool HasRepeated =
false;
7128 unsigned NumComponents = 0;
7129 const char *Begin = AccessorName.data();
7131 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7132 const char *Chunk = Begin + I;
7133 char RowChar = 0, ColChar = 0;
7134 if (IsZeroBasedAccessor) {
7136 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7137 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7139 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7146 if (Chunk[0] !=
'_')
7148 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7155 bool IsDigitsError =
false;
7157 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7161 IsDigitsError =
true;
7165 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7169 IsDigitsError =
true;
7174 unsigned Row = RowChar -
'0';
7175 unsigned Col = ColChar -
'0';
7177 bool HasIndexingError =
false;
7178 if (IsZeroBasedAccessor) {
7180 if (!isZeroBasedIndex(Row)) {
7181 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7183 HasIndexingError =
true;
7185 if (!isZeroBasedIndex(Col)) {
7186 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7188 HasIndexingError =
true;
7192 if (!isOneBasedIndex(Row)) {
7193 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7195 HasIndexingError =
true;
7197 if (!isOneBasedIndex(Col)) {
7198 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7200 HasIndexingError =
true;
7207 if (HasIndexingError)
7213 bool HasBoundsError =
false;
7215 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7217 HasBoundsError =
true;
7220 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7222 HasBoundsError =
true;
7227 unsigned FlatIndex = Row * Cols + Col;
7228 if (Seen[FlatIndex])
7230 Seen[FlatIndex] =
true;
7233 if (NumComponents == 0 || NumComponents > 4) {
7234 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7239 QualType ElemTy = MT->getElementType();
7240 if (NumComponents == 1)
7246 for (Sema::ExtVectorDeclsType::iterator
7250 if ((*I)->getUnderlyingType() == VT)
7261 trackLocalResource(VDecl,
Init);
7263 const HLSLVkConstantIdAttr *ConstIdAttr =
7264 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7271 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7281 int ConstantID = ConstIdAttr->getId();
7282 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7284 ConstIdAttr->getLocation());
7288 if (
C->getType()->getCanonicalTypeUnqualified() !=
7292 Context.getTrivialTypeSourceInfo(
7293 Init->getType(),
Init->getExprLoc()),
7312 if (!Params || Params->
size() != 1)
7325 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7326 if (TTP->hasDefaultArgument()) {
7327 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7330 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7331 if (NTTP->hasDefaultArgument()) {
7332 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7335 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7336 if (TTPD->hasDefaultArgument()) {
7337 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7344 return SemaRef.CheckTemplateIdType(
7346 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.
Defines AST-level helper utilities for matrix types.
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
const LangOptions & getLangOpts() 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)
ExprResult CreateOutArgExpr(Expr *Arg, QualType ArgTy, QualType ParamTy, InitializedEntity Entity, SourceLocation Loc, bool IsInOut)
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)
bool isMatrixRowMajor(const LangOptions &LangOpts, QualType T)
Returns true if matrices of T should be laid out in row-major order.
@ 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.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
unsigned getImplicitOrderID() const
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
bool hasImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const