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_wave_multi_prefix_bit_and:
5381 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_or:
5382 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_xor:
5383 case Builtin::BI__builtin_hlsl_wave_multi_prefix_product:
5384 case Builtin::BI__builtin_hlsl_wave_multi_prefix_sum: {
5385 if (
SemaRef.checkArgCount(TheCall, 2))
5395 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_product ||
5396 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_sum;
5401 diag::err_builtin_invalid_arg_type)
5402 << 1 << (ValueTy->
isMatrixType() ? 3 : 5) << 1 << IsArithmetic
5410 if (!
getASTContext().hasSameUnqualifiedType(MaskTy, UInt4Ty)) {
5412 diag::err_typecheck_convert_incompatible)
5413 << MaskTy << UInt4Ty << 1 << 0 << 0;
5420 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5421 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5422 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5423 if (
SemaRef.checkArgCount(TheCall, 1))
5435 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5436 if (
SemaRef.checkArgCount(TheCall, 3))
5442 SemaRef.Context.UnsignedIntTy, 1) ||
5444 SemaRef.Context.UnsignedIntTy, 2))
5452 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5453 if (
SemaRef.checkArgCount(TheCall, 1))
5460 case Builtin::BI__builtin_elementwise_acos:
5461 case Builtin::BI__builtin_elementwise_asin:
5462 case Builtin::BI__builtin_elementwise_atan:
5463 case Builtin::BI__builtin_elementwise_atan2:
5464 case Builtin::BI__builtin_elementwise_ceil:
5465 case Builtin::BI__builtin_elementwise_cos:
5466 case Builtin::BI__builtin_elementwise_cosh:
5467 case Builtin::BI__builtin_elementwise_exp:
5468 case Builtin::BI__builtin_elementwise_exp2:
5469 case Builtin::BI__builtin_elementwise_exp10:
5470 case Builtin::BI__builtin_elementwise_floor:
5471 case Builtin::BI__builtin_elementwise_fmod:
5472 case Builtin::BI__builtin_elementwise_log:
5473 case Builtin::BI__builtin_elementwise_log2:
5474 case Builtin::BI__builtin_elementwise_log10:
5475 case Builtin::BI__builtin_elementwise_pow:
5476 case Builtin::BI__builtin_elementwise_roundeven:
5477 case Builtin::BI__builtin_elementwise_sin:
5478 case Builtin::BI__builtin_elementwise_sinh:
5479 case Builtin::BI__builtin_elementwise_sqrt:
5480 case Builtin::BI__builtin_elementwise_tan:
5481 case Builtin::BI__builtin_elementwise_tanh:
5482 case Builtin::BI__builtin_elementwise_trunc: {
5488 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5489 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5490 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5491 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5492 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5497 std::optional<llvm::APSInt> Offset =
5499 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5501 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5507 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5508 if (
SemaRef.checkArgCount(TheCall, 1))
5519 ArgTy = VTy->getElementType();
5522 diag::err_builtin_invalid_arg_type)
5531 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5532 if (
SemaRef.checkArgCount(TheCall, 1))
5547 WorkList.push_back(BaseTy);
5548 while (!WorkList.empty()) {
5550 T =
T.getCanonicalType().getUnqualifiedType();
5551 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5559 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5560 llvm::append_range(List, ElementFields);
5565 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5566 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5569 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5570 List.insert(List.end(), MT->getNumElementsFlattened(),
5571 MT->getElementType());
5574 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5575 if (RD->isStandardLayout())
5576 RD = RD->getStandardLayoutBaseWithFields();
5580 if (RD->
isUnion() || !RD->isAggregate()) {
5586 for (
const auto *FD : RD->
fields())
5587 if (!FD->isUnnamedBitField())
5588 FieldTypes.push_back(FD->
getType());
5590 std::reverse(FieldTypes.begin(), FieldTypes.end());
5591 llvm::append_range(WorkList, FieldTypes);
5595 if (!RD->isStandardLayout()) {
5597 for (
const auto &
Base : RD->bases())
5598 FieldTypes.push_back(
Base.getType());
5599 std::reverse(FieldTypes.begin(), FieldTypes.end());
5600 llvm::append_range(WorkList, FieldTypes);
5635 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5641 int ArraySize = VT->getNumElements();
5646 QualType ElTy = VT->getElementType();
5650 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5666 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5675 return llvm::equal(T1Types, T2Types,
5677 return SemaRef.IsLayoutCompatible(LHS, RHS);
5686 bool HadError =
false;
5688 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5696 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5697 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5698 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5699 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5701 if (NSpellingIdx != OSpellingIdx) {
5703 diag::err_hlsl_param_qualifier_mismatch)
5704 << NDAttr << NewParam;
5720 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5735 llvm_unreachable(
"HLSL doesn't support pointers.");
5738 llvm_unreachable(
"HLSL doesn't support complex types.");
5740 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5742 llvm_unreachable(
"Should have returned before this");
5752 llvm_unreachable(
"HLSL doesn't support complex types.");
5754 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5759 llvm_unreachable(
"HLSL doesn't support pointers.");
5761 llvm_unreachable(
"Should have returned before this");
5767 llvm_unreachable(
"HLSL doesn't support pointers.");
5770 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5774 llvm_unreachable(
"HLSL doesn't support complex types.");
5777 llvm_unreachable(
"Unhandled scalar cast");
5798 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5804 SrcTy = SrcMatTy->getElementType();
5809 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5810 if (DestTypes[I]->isUnionType())
5842 if (SrcTypes.size() < DestTypes.size())
5845 unsigned SrcSize = SrcTypes.size();
5846 unsigned DstSize = DestTypes.size();
5848 for (I = 0; I < DstSize && I < SrcSize; I++) {
5849 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5857 for (; I < SrcSize; I++) {
5858 if (SrcTypes[I]->isUnionType())
5901 tok::equal, ArgOpV, OpV);
5913 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5914 "We should not get here without a parameter modifier expression");
5915 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5922 << Arg << (IsInOut ? 1 : 0);
5926 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5933 << Arg << (IsInOut ? 1 : 0);
5941 Param->getBeginLoc(), IsInOut);
5949 "Pointer and reference types cannot be inout or out parameters");
5950 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5966 for (
const auto *FD : RD->
fields()) {
5970 assert(RD->getNumBases() <= 1 &&
5971 "HLSL doesn't support multiple inheritance");
5972 return RD->getNumBases()
5977 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5978 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5990 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5995 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
6001 if (
Decl->getType().hasAddressSpace())
6004 if (
Decl->getType()->isDependentType())
6016 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
6030 llvm::Triple::Vulkan;
6031 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
6032 if (HasDeclaredAPushConstant)
6038 HasDeclaredAPushConstant =
true;
6065class StructBindingContext {
6068 HLSLResourceBindingAttr *RegBindingsAttrs[4];
6069 unsigned RegBindingOffset[4];
6072 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
6073 static_cast<unsigned>(RegisterType::UAV) == 1 &&
6074 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
6075 static_cast<unsigned>(RegisterType::Sampler) == 3,
6076 "unexpected register type values");
6079 HLSLVkBindingAttr *VkBindingAttr;
6080 unsigned VkBindingOffset;
6085 StructBindingContext(
VarDecl *VD) {
6086 for (
unsigned i = 0; i < 4; ++i) {
6087 RegBindingsAttrs[i] =
nullptr;
6088 RegBindingOffset[i] = 0;
6090 VkBindingAttr =
nullptr;
6091 VkBindingOffset = 0;
6097 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
6099 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
6102 RegBindingsAttrs[RegTypeIdx] = RBA;
6107 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
6108 VkBindingAttr = VBA;
6115 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
6116 unsigned Range,
bool HasCounter) {
6117 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
6119 if (VkBindingAttr) {
6120 unsigned Offset = VkBindingOffset;
6121 VkBindingOffset +=
Range;
6122 return HLSLVkBindingAttr::CreateImplicit(
6123 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
6124 VkBindingAttr->getRange());
6127 HLSLResourceBindingAttr *RBA =
6128 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6129 HLSLResourceBindingAttr *NewAttr =
nullptr;
6131 if (RBA && RBA->hasRegisterSlot()) {
6134 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6135 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6137 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6138 StringRef NewSlotNumberStr =
6140 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6141 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6142 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6146 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6147 NewAttr->setBinding(RegType, std::nullopt,
6148 RBA ? RBA->getSpaceNumber() : 0);
6152 NewAttr->setImplicitCounterBindingOrderID(
6161static void createGlobalResourceDeclForStruct(
6163 QualType ResTy, StructBindingContext &BindingCtx) {
6165 "expected resource type or array of resources");
6176 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6177 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6182 const HLSLAttributedResourceType *ResHandleTy =
6183 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6187 Attr *BindingAttr = BindingCtx.createBindingAttr(
6189 ResDecl->
addAttr(BindingAttr);
6190 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6199 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6206static void handleArrayOfStructWithResources(
6208 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6213static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6215 EmbeddedResourceNameBuilder &NameBuilder,
6216 StructBindingContext &BindingCtx) {
6219 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6226 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6240 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6243 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6245 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6247 "resource arrays should have been already handled");
6248 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6257handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6259 EmbeddedResourceNameBuilder &NameBuilder,
6260 StructBindingContext &BindingCtx) {
6268 if (!SubCAT && !ElementRD)
6271 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6274 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6277 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6290void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6291 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6292 StructBindingContext BindingCtx(VD);
6296 "Expected non-resource struct or array type");
6299 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6303 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6304 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6312 if (
SemaRef.RequireCompleteType(
6315 diag::err_typecheck_decl_incomplete_type)) {
6329 DefaultCBufferDecls.push_back(VD);
6334 collectResourceBindingsOnVarDecl(VD);
6336 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6348 processExplicitBindingsOnDecl(VD);
6386 handleGlobalStructOrArrayOfWithResources(VD);
6390 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6399 "expected resource record type");
6415 const char *CreateMethodName;
6417 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6418 :
"__createFromBinding";
6420 CreateMethodName = HasCounter
6421 ?
"__createFromImplicitBindingWithImplicitCounter"
6422 :
"__createFromImplicitBinding";
6427 if (!CreateMethod) {
6432 "create method lookup should always succeed for built-in resource "
6441 Args.push_back(RegSlot);
6449 Args.push_back(OrderId);
6455 Args.push_back(Space);
6459 Args.push_back(RangeSize);
6463 Args.push_back(Index);
6465 StringRef VarName = VD->
getName();
6473 Args.push_back(NameCast);
6481 Args.push_back(CounterId);
6504 SemaRef.CheckCompleteVariableDeclaration(VD);
6510 "expected array of resource records");
6531 lookupMethod(
SemaRef, ResourceDecl,
6532 HasCounter ?
"__createFromBindingWithImplicitCounter"
6533 :
"__createFromBinding",
6537 CreateMethod = lookupMethod(
6539 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6540 :
"__createFromImplicitBinding",
6583std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6584 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6585 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6586 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6587 if (!TrueInfo || !FalseInfo)
6588 return std::nullopt;
6589 if (*TrueInfo != *FalseInfo)
6590 return std::nullopt;
6594 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6603 if (
const auto *AttrResType =
6604 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6606 return Bindings.getDeclBindingInfo(VD, RC);
6613void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6614 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6617 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6622 if (*ExprBinding ==
nullptr)
6625 auto PrevBinding = Assigns.find(VD);
6626 if (PrevBinding == Assigns.end()) {
6628 Assigns.insert({VD, *ExprBinding});
6633 if (*ExprBinding != PrevBinding->second) {
6635 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6637 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6648 "expected LHS to be a resource record or array of resource records");
6649 if (Opc != BO_Assign)
6654 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6662 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6667 trackLocalResource(VD, RHSExpr);
6684void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6686 "expected global variable that contains HLSL resource");
6689 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6690 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6691 ? ResourceClass::CBuffer
6692 : ResourceClass::SRV);
6705 if (
const HLSLAttributedResourceType *AttrResType =
6706 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6707 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6712 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6713 collectResourceBindingsOnUserRecordDecl(VD, RT);
6719void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6722 bool HasBinding =
false;
6723 for (Attr *A : VD->
attrs()) {
6726 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6727 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6730 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6731 if (!RBA || !RBA->hasRegisterSlot())
6736 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6737 "never have an attribute created");
6739 if (RT == RegisterType::C) {
6740 if (Bindings.hasBindingInfoForDecl(VD))
6742 diag::warn_hlsl_user_defined_type_missing_member)
6743 <<
static_cast<int>(RT);
6751 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6756 diag::warn_hlsl_user_defined_type_missing_member)
6757 <<
static_cast<int>(RT);
6765class InitListTransformer {
6769 QualType *DstIt =
nullptr;
6770 Expr **ArgIt =
nullptr;
6776 bool castInitializer(Expr *E) {
6777 assert(DstIt &&
"This should always be something!");
6778 if (DstIt == DestTypes.end()) {
6780 ArgExprs.push_back(E);
6785 DstIt = DestTypes.begin();
6788 Ctx, *DstIt,
false);
6793 ArgExprs.push_back(
Init);
6798 bool buildInitializerListImpl(Expr *E) {
6800 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6801 for (
auto *SubInit :
Init->inits())
6802 if (!buildInitializerListImpl(SubInit))
6812 return castInitializer(E);
6826 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6831 for (uint64_t I = 0; I <
Size; ++I) {
6833 SizeTy, SourceLocation());
6839 if (!castInitializer(ElExpr.
get()))
6844 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6845 unsigned Rows = MTy->getNumRows();
6846 unsigned Cols = MTy->getNumColumns();
6847 QualType ElemTy = MTy->getElementType();
6849 for (
unsigned R = 0;
R < Rows; ++
R) {
6850 for (
unsigned C = 0;
C < Cols; ++
C) {
6863 if (!castInitializer(ElExpr.
get()))
6871 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6875 for (uint64_t I = 0; I <
Size; ++I) {
6877 SizeTy, SourceLocation());
6882 if (!buildInitializerListImpl(ElExpr.
get()))
6889 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6890 RecordDecls.push_back(RD);
6891 while (RecordDecls.back()->getNumBases()) {
6892 CXXRecordDecl *D = RecordDecls.back();
6894 "HLSL doesn't support multiple inheritance");
6895 RecordDecls.push_back(
6898 while (!RecordDecls.empty()) {
6899 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6900 for (
auto *FD : RD->
fields()) {
6901 if (FD->isUnnamedBitField())
6909 if (!buildInitializerListImpl(Res.
get()))
6917 Expr *generateInitListsImpl(QualType Ty) {
6919 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6924 llvm::SmallVector<Expr *>
Inits;
6929 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6930 ElTy = ATy->getElementType();
6931 Size = ATy->getNumElements();
6932 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6933 ElTy = CMTy->getElementType();
6934 Size = CMTy->getNumElementsFlattened();
6937 ElTy = VTy->getElementType();
6938 Size = VTy->getZExtSize();
6940 for (uint64_t I = 0; I <
Size; ++I)
6941 Inits.push_back(generateInitListsImpl(ElTy));
6944 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6945 RecordDecls.push_back(RD);
6946 while (RecordDecls.back()->getNumBases()) {
6947 CXXRecordDecl *D = RecordDecls.back();
6949 "HLSL doesn't support multiple inheritance");
6950 RecordDecls.push_back(
6953 while (!RecordDecls.empty()) {
6954 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6955 for (
auto *FD : RD->
fields())
6956 if (!FD->isUnnamedBitField())
6961 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6962 Inits.back()->getEndLoc(),
false);
6963 NewInit->setType(Ty);
6968 llvm::SmallVector<QualType, 16> DestTypes;
6969 llvm::SmallVector<Expr *, 16> ArgExprs;
6970 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6971 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6972 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6973 InitTy = Entity.
getType().getNonReferenceType();
6983 DstIt = DestTypes.begin();
6986 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6988 Expr *generateInitLists() {
6989 assert(!ArgExprs.empty() &&
6990 "Call buildInitializerList to generate argument expressions.");
6991 ArgIt = ArgExprs.begin();
6993 return generateInitListsImpl(InitTy);
6994 llvm::SmallVector<Expr *>
Inits;
6995 while (ArgIt != ArgExprs.end())
6996 Inits.push_back(generateInitListsImpl(InitTy));
6999 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
7000 Inits.back()->getEndLoc(),
false);
7001 llvm::APInt ArySize(64,
Inits.size());
7003 ArraySizeModifier::Normal, 0));
7015 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
7022 if (
const auto *RT = Ty->
getAs<RecordType>()) {
7026 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
7046 if (
Init->getType()->isScalarType())
7049 InitListTransformer ILT(
SemaRef, Entity);
7051 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
7059 Init->setInit(I, E);
7061 if (!ILT.buildInitializerList(E))
7064 size_t ExpectedSize = ILT.DestTypes.size();
7065 size_t ActualSize = ILT.ArgExprs.size();
7066 if (ExpectedSize == 0 && ActualSize == 0)
7073 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7075 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7076 << (int)(ExpectedSize < ActualSize) << InitTy
7077 << ExpectedSize << ActualSize;
7087 assert(ExpectedSize > 0 &&
7088 "The expected size of an incomplete array type must be at least 1.");
7090 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
7098 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7099 if (ExpectedSize != ActualSize) {
7100 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
7101 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7102 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
7109 Init->resizeInits(Ctx, NewInit->getNumInits());
7110 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
7111 Init->updateInit(Ctx, I, NewInit->getInit(I));
7119 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7129 StringRef AccessorName = CompName->
getName();
7130 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7132 unsigned Rows = MT->getNumRows();
7133 unsigned Cols = MT->getNumColumns();
7134 bool IsZeroBasedAccessor =
false;
7135 unsigned ChunkLen = 0;
7136 if (AccessorName.size() < 2)
7138 "length 4 for zero based: \'_mRC\' or "
7139 "length 3 for one-based: \'_RC\' accessor",
7142 if (AccessorName[0] ==
'_') {
7143 if (AccessorName[1] ==
'm') {
7144 IsZeroBasedAccessor =
true;
7151 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7154 if (AccessorName.size() % ChunkLen != 0) {
7155 const llvm::StringRef
Expected = IsZeroBasedAccessor
7156 ?
"zero based: '_mRC' accessor"
7157 :
"one-based: '_RC' accessor";
7162 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7163 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7164 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7166 bool HasRepeated =
false;
7168 unsigned NumComponents = 0;
7169 const char *Begin = AccessorName.data();
7171 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7172 const char *Chunk = Begin + I;
7173 char RowChar = 0, ColChar = 0;
7174 if (IsZeroBasedAccessor) {
7176 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7177 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7179 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7186 if (Chunk[0] !=
'_')
7188 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7195 bool IsDigitsError =
false;
7197 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7201 IsDigitsError =
true;
7205 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7209 IsDigitsError =
true;
7214 unsigned Row = RowChar -
'0';
7215 unsigned Col = ColChar -
'0';
7217 bool HasIndexingError =
false;
7218 if (IsZeroBasedAccessor) {
7220 if (!isZeroBasedIndex(Row)) {
7221 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7223 HasIndexingError =
true;
7225 if (!isZeroBasedIndex(Col)) {
7226 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7228 HasIndexingError =
true;
7232 if (!isOneBasedIndex(Row)) {
7233 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7235 HasIndexingError =
true;
7237 if (!isOneBasedIndex(Col)) {
7238 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7240 HasIndexingError =
true;
7247 if (HasIndexingError)
7253 bool HasBoundsError =
false;
7255 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7257 HasBoundsError =
true;
7260 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7262 HasBoundsError =
true;
7267 unsigned FlatIndex = Row * Cols + Col;
7268 if (Seen[FlatIndex])
7270 Seen[FlatIndex] =
true;
7273 if (NumComponents == 0 || NumComponents > 4) {
7274 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7279 QualType ElemTy = MT->getElementType();
7280 if (NumComponents == 1)
7286 for (Sema::ExtVectorDeclsType::iterator
7290 if ((*I)->getUnderlyingType() == VT)
7301 trackLocalResource(VDecl,
Init);
7303 const HLSLVkConstantIdAttr *ConstIdAttr =
7304 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7311 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7321 int ConstantID = ConstIdAttr->getId();
7322 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7324 ConstIdAttr->getLocation());
7328 if (
C->getType()->getCanonicalTypeUnqualified() !=
7332 Context.getTrivialTypeSourceInfo(
7333 Init->getType(),
Init->getExprLoc()),
7352 if (!Params || Params->
size() != 1)
7365 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7366 if (TTP->hasDefaultArgument()) {
7367 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7370 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7371 if (NTTP->hasDefaultArgument()) {
7372 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7375 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7376 if (TTPD->hasDefaultArgument()) {
7377 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7384 return SemaRef.CheckTemplateIdType(
7386 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