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 return ST == llvm::Triple::Pixel && IsInput;
1024bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1027 SemanticInfo &ActiveSemantic,
1028 SemaHLSL::SemanticContext &SC) {
1029 if (ActiveSemantic.Semantic ==
nullptr) {
1030 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1031 if (ActiveSemantic.Semantic)
1032 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1035 if (!ActiveSemantic.Semantic) {
1041 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1042 ActiveSemantic.Semantic->getAttrName()->getName(),
1043 ActiveSemantic.Index.value_or(0));
1048 QualType
T = D == FD ? FD->getReturnType() : D->
getType();
1049 const ConstantArrayType *AT =
1052 Diag(A->getLoc(), diag::err_hlsl_semantic_zero_sized_array)
1053 << A->getAttrName();
1061 if (
const auto *MT = BaseTy->
getAs<ConstantMatrixType>())
1064 : MT->getNumColumns();
1066 checkSemanticAnnotation(FD, D, A, SC, ElementCount);
1069 unsigned Location = ActiveSemantic.Index.value_or(0);
1072 any(SC.CurrentIOType & IOType::In))) {
1073 bool HasVkLocation =
false;
1074 if (
auto *A = D->
getAttr<HLSLVkLocationAttr>()) {
1075 HasVkLocation =
true;
1076 Location = A->getLocation();
1079 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1080 Diag(D->
getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1083 SC.UsesExplicitVkLocations = HasVkLocation;
1086 ActiveSemantic.Index = Location + ElementCount;
1088 StringRef BaseName = ActiveSemantic.Semantic->getAttrName()->getName();
1089 std::string LowerName = BaseName.lower();
1090 for (
unsigned I = 0; I < ElementCount; ++I) {
1091 auto [It, Inserted] = SC.ActiveSemantics.try_emplace(
1092 (Twine(LowerName) + Twine(Location + I)).str(), D->
getLocation());
1095 << (BaseName + Twine(Location + I)).str();
1096 Diag(It->second, diag::note_previous_use);
1104bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1107 SemanticInfo &ActiveSemantic,
1108 SemaHLSL::SemanticContext &SC) {
1109 if (ActiveSemantic.Semantic ==
nullptr) {
1110 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1111 if (ActiveSemantic.Semantic)
1112 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1118 const RecordType *RT = dyn_cast<RecordType>(
T);
1120 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1123 const RecordDecl *RD = RT->getDecl();
1124 for (FieldDecl *Field : RD->
fields()) {
1125 SemanticInfo Info = ActiveSemantic;
1126 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1127 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1130 if (ActiveSemantic.Semantic)
1131 ActiveSemantic = Info;
1138 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1139 assert(ShaderAttr &&
"Entry point has no shader attribute");
1140 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1144 case llvm::Triple::Pixel:
1145 case llvm::Triple::Vertex:
1146 case llvm::Triple::Geometry:
1147 case llvm::Triple::Hull:
1148 case llvm::Triple::Domain:
1149 case llvm::Triple::RayGeneration:
1150 case llvm::Triple::Intersection:
1151 case llvm::Triple::AnyHit:
1152 case llvm::Triple::ClosestHit:
1153 case llvm::Triple::Miss:
1154 case llvm::Triple::Callable:
1155 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1156 diagnoseAttrStageMismatch(NT, ST,
1157 {llvm::Triple::Compute,
1158 llvm::Triple::Amplification,
1159 llvm::Triple::Mesh});
1162 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1163 diagnoseAttrStageMismatch(WS, ST,
1164 {llvm::Triple::Compute,
1165 llvm::Triple::Amplification,
1166 llvm::Triple::Mesh});
1171 case llvm::Triple::Compute:
1172 case llvm::Triple::Amplification:
1173 case llvm::Triple::Mesh:
1174 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1176 << llvm::Triple::getEnvironmentTypeName(ST);
1179 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1181 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1182 }
else if (Ver < VersionTuple(6, 6)) {
1183 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1186 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1189 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1190 << WS << WS->getSpelledArgsCount() <<
"6.8";
1195 case llvm::Triple::RootSignature:
1196 llvm_unreachable(
"rootsig environment has no function entry point");
1198 llvm_unreachable(
"Unhandled environment in triple");
1201 SemaHLSL::SemanticContext InputSC = {};
1202 InputSC.CurrentIOType = IOType::In;
1203 SemaHLSL::SemanticContext OutputSC = {};
1204 OutputSC.CurrentIOType = IOType::Out;
1207 SemanticInfo ActiveSemantic;
1208 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1209 if (ActiveSemantic.Semantic)
1210 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1214 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1215 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1219 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1220 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1221 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1224 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1225 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1230 SemanticInfo ActiveSemantic;
1231 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1232 if (ActiveSemantic.Semantic)
1233 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1235 if (ST == llvm::Triple::Vertex &&
1236 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1238 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1242void SemaHLSL::checkSemanticAnnotation(
1244 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC,
1245 unsigned ElementCount) {
1246 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1247 assert(ShaderAttr &&
"Entry point has no shader attribute");
1248 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1251 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1252 llvm::hlsl::SemanticInterpretation Interpretation =
1253 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1254 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid) {
1255 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1261 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary) {
1262 diagnoseSemanticType(Param, SemanticAttr, SemanticKind::Arbitrary);
1266 diagnoseSystemSemanticIndex(SemanticAttr, Kind, ElementCount);
1267 diagnoseSemanticType(Param, SemanticAttr, Kind);
1268 diagnoseSemanticShaderModel(SemanticAttr, Kind);
1271void SemaHLSL::diagnoseSemanticShaderModel(
const HLSLAppliedSemanticAttr *A,
1274 if (!Triple.isDXIL())
1278 case SemanticKind::Barycentrics:
1279 if (Triple.getOSVersion() < VersionTuple(6, 1))
1280 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1281 << A->getAttrName() <<
"6.1";
1283 case SemanticKind::ShadingRate:
1284 if (Triple.getOSVersion() < VersionTuple(6, 4))
1285 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1286 << A->getAttrName() <<
"6.4";
1293void SemaHLSL::diagnoseSystemSemanticIndex(
const HLSLAppliedSemanticAttr *A,
1295 unsigned ElementCount) {
1296 assert(Kind != SemanticKind::Invalid && Kind != SemanticKind::Arbitrary &&
1297 "expected a recognized system semantic");
1298 assert(ElementCount > 0 &&
"a semantic covers at least one element");
1301 uint32_t FirstIndex = A->getSemanticIndex();
1303 constexpr uint32_t MaxSemanticIndex = std::numeric_limits<uint32_t>::max();
1304 if (LastIndex > MaxSemanticIndex) {
1305 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1306 << A->getAttrName() << LastIndex << MaxSemanticIndex;
1314 case SemanticKind::ClipDistance:
1315 case SemanticKind::CullDistance:
1317 case SemanticKind::Target: {
1318 constexpr unsigned MaxTargetIndex = 7;
1319 if (LastIndex > MaxTargetIndex)
1320 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1321 << A->getAttrName() << LastIndex << MaxTargetIndex;
1325 Diag(A->getLoc(), diag::err_hlsl_semantic_indexing_not_supported)
1326 << A->getAttrName();
1333 return VT->getElementType();
1336 return MT->getElementType();
1342 return VT->getNumElements();
1363void SemaHLSL::diagnoseSemanticType(
const Decl *D,
1364 const HLSLAppliedSemanticAttr *A,
1366 assert(Kind != SemanticKind::Invalid &&
"expected a valid semantic");
1370 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
1376 T =
T.getNonReferenceType();
1379 QualType DeclaredTy =
T;
1381 T = AT->getElementType();
1389 case SemanticKind::Barycentrics:
1391 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1392 << A->getAttrName() << 2 << 3
1395 case SemanticKind::DispatchThreadID:
1396 case SemanticKind::GroupID:
1397 case SemanticKind::GroupThreadID:
1399 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1400 << A->getAttrName() << 1 << 3
1403 case SemanticKind::GroupIndex:
1405 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1406 << A->getAttrName() << 0 << 1 << 1
1409 case SemanticKind::VertexID:
1411 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1412 << A->getAttrName() << 0 << 1
1415 case SemanticKind::Position:
1416 case SemanticKind::Target:
1418 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1419 << A->getAttrName() << 1 << 4
1422 case SemanticKind::InstanceID:
1423 case SemanticKind::ShadingRate:
1430 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1431 << A->getAttrName() << 0 << 1
1433 (IsSPIRV ? 4 : 3) << DeclaredTy;
1446 Diag(A->getLoc(), diag::err_hlsl_semantic_64bit_type)
1447 << A->getAttrName() << DeclaredTy;
1450void SemaHLSL::diagnoseAttrStageMismatch(
1451 const Attr *A, llvm::Triple::EnvironmentType Stage,
1452 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1453 SmallVector<StringRef, 8> StageStrings;
1454 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1455 [](llvm::Triple::EnvironmentType ST) {
1457 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1459 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1460 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1461 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1464void SemaHLSL::diagnoseSemanticStageMismatch(
1465 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1468 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1469 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1470 return Info.Stage == Stage;
1473 StringRef CurrentIOTypeName =
"patch constants or primitives";
1474 if (
any(CurrentIOType & IOType::In))
1475 CurrentIOTypeName =
"inputs";
1476 else if (
any(CurrentIOType & IOType::Out))
1477 CurrentIOTypeName =
"outputs";
1480 if (It == Allowed.end()) {
1481 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1482 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1483 << CurrentIOTypeName;
1487 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1488 if (!(AllowedIOTypes & CurrentIOType)) {
1489 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1490 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1491 << CurrentIOTypeName;
1496template <CastKind Kind>
1499 Ty = VTy->getElementType();
1504template <CastKind Kind>
1516 if (LHSFloat && RHSFloat) {
1544 if (LHSSigned == RHSSigned) {
1545 if (IsCompAssign || IntOrder >= 0)
1553 if (IntOrder != (LHSSigned ? 1 : -1)) {
1554 if (IsCompAssign || RHSSigned)
1563 if (IsCompAssign || LHSSigned)
1590 return CK_FloatingCast;
1592 return CK_IntegralCast;
1594 return CK_IntegralToFloating;
1596 return CK_FloatingToIntegral;
1602 bool IsCompAssign) {
1609 if (!LVecTy && IsCompAssign) {
1611 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1613 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1615 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1620 unsigned EndSz = std::numeric_limits<unsigned>::max();
1623 LSz = EndSz = LVecTy->getNumElements();
1626 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1627 "one of the above should have had a value");
1631 if (IsCompAssign && LSz != EndSz) {
1633 diag::err_hlsl_vector_compound_assignment_truncation)
1634 << LHSType << RHSType;
1640 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1645 if (!IsCompAssign && !LVecTy)
1649 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1650 return Ctx.getCommonSugaredType(LHSType, RHSType);
1658 LElTy, RElTy, IsCompAssign);
1661 "HLSL Vectors can only contain integer or floating point types");
1663 LElTy, RElTy, IsCompAssign);
1668 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1669 "Called with non-logical operator");
1671 llvm::raw_svector_ostream OS(Buff);
1673 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1674 OS << NewFnName <<
"(";
1684std::pair<IdentifierInfo *, bool>
1687 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1694 return {DeclIdent,
Found};
1705 for (
auto &RootSigElement : RootElements)
1706 Elements.push_back(RootSigElement.getElement());
1710 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1712 SignatureDecl->setImplicit();
1718 if (RootSigOverrideIdent) {
1721 if (
SemaRef.LookupQualifiedName(R, DC))
1722 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1730struct PerVisibilityBindingChecker {
1733 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1737 llvm::dxbc::ShaderVisibility Vis;
1742 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1744 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1745 llvm::dxil::ResourceClass RC,
uint32_t Space,
1747 const hlsl::RootSignatureElement *Elem) {
1749 assert(BuilderIndex < Builders.size() &&
1750 "Not enough builders for visibility type");
1751 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1752 static_cast<const void *
>(Elem));
1754 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1755 "'All' visibility must come first");
1756 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1757 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1758 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1759 static_cast<const void *
>(Elem));
1761 ElemInfoMap.push_back({Elem,
Visibility,
false});
1764 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1765 auto It = llvm::lower_bound(
1767 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1768 assert(It->Elem == Elem &&
"Element not in map");
1772 bool checkOverlap() {
1773 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1774 return LHS.Elem < RHS.Elem;
1777 bool HadOverlap =
false;
1779 using llvm::hlsl::BindingInfoBuilder;
1780 auto ReportOverlap = [
this,
1781 &HadOverlap](
const BindingInfoBuilder &Builder,
1782 const llvm::hlsl::Binding &Reported) {
1786 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1787 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1788 const auto *PrevElem =
1789 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1791 ElemInfo &Info =
getInfo(Elem);
1796 Info.Diagnosed =
true;
1798 ElemInfo &PrevInfo =
getInfo(PrevElem);
1799 llvm::dxbc::ShaderVisibility CommonVis =
1800 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1803 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1804 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1805 << Reported.isUnbounded() << Reported.UpperBound
1810 this->S->
Diag(PrevElem->getLocation(),
1811 diag::note_hlsl_resource_range_here);
1814 for (BindingInfoBuilder &Builder : Builders)
1815 Builder.calculateBindingInfo(ReportOverlap);
1835 bool HadError =
false;
1836 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1837 uint32_t UpperBound) {
1839 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1840 << LowerBound << UpperBound;
1847 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1848 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1849 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1852 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1853 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1854 ReportError(Loc, 0, 0xfffffffe);
1857 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1858 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1859 ReportError(Loc, 0, 0xffffffef);
1862 const uint32_t Version =
1863 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1864 const uint32_t VersionEnum = Version - 1;
1865 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1867 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1874 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1875 if (
const auto *Descriptor =
1876 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1877 VerifyRegister(Loc, Descriptor->Reg.Number);
1878 VerifySpace(Loc, Descriptor->Space);
1880 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1882 ReportFlagError(Loc);
1883 }
else if (
const auto *Constants =
1884 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1885 VerifyRegister(Loc, Constants->Reg.Number);
1886 VerifySpace(Loc, Constants->Space);
1887 }
else if (
const auto *Sampler =
1888 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1889 VerifyRegister(Loc, Sampler->Reg.Number);
1890 VerifySpace(Loc, Sampler->Space);
1893 "By construction, parseFloatParam can't produce a NaN from a "
1894 "float_literal token");
1896 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1897 ReportError(Loc, 0, 16);
1898 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1899 ReportFloatError(Loc, -16.f, 15.99f);
1900 }
else if (
const auto *Clause =
1901 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1903 VerifyRegister(Loc, Clause->Reg.Number);
1904 VerifySpace(Loc, Clause->Space);
1906 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1910 ReportError(Loc, 1, 0xfffffffe);
1913 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1915 ReportFlagError(Loc);
1919 PerVisibilityBindingChecker BindingChecker(
this);
1920 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1925 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1926 if (
const auto *Descriptor =
1927 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1928 uint32_t LowerBound(Descriptor->Reg.Number);
1929 uint32_t UpperBound(LowerBound);
1931 BindingChecker.trackBinding(
1932 Descriptor->Visibility,
1933 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1934 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1935 }
else if (
const auto *Constants =
1936 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1937 uint32_t LowerBound(Constants->Reg.Number);
1938 uint32_t UpperBound(LowerBound);
1940 BindingChecker.trackBinding(
1941 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1942 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1943 }
else if (
const auto *Sampler =
1944 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1945 uint32_t LowerBound(Sampler->Reg.Number);
1946 uint32_t UpperBound(LowerBound);
1948 BindingChecker.trackBinding(
1949 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1950 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1951 }
else if (
const auto *Clause =
1952 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1955 UnboundClauses.emplace_back(Clause, &RootSigElem);
1956 }
else if (
const auto *Table =
1957 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1958 assert(UnboundClauses.size() == Table->NumClauses &&
1959 "Number of unbound elements must match the number of clauses");
1960 bool HasAnySampler =
false;
1961 bool HasAnyNonSampler =
false;
1962 uint64_t Offset = 0;
1963 bool IsPrevUnbound =
false;
1964 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1966 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1967 HasAnySampler =
true;
1969 HasAnyNonSampler =
true;
1971 if (HasAnySampler && HasAnyNonSampler)
1972 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1977 if (Clause->NumDescriptors == 0)
1981 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1983 Offset = Clause->Offset;
1985 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1986 Offset, Clause->NumDescriptors);
1988 if (IsPrevUnbound && IsAppending)
1989 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1990 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1991 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1994 Offset = RangeBound + 1;
1995 IsPrevUnbound = Clause->NumDescriptors ==
1996 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1999 uint32_t LowerBound(Clause->Reg.Number);
2000 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
2001 LowerBound, Clause->NumDescriptors);
2003 BindingChecker.trackBinding(
2005 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
2006 LowerBound, UpperBound, ClauseElem);
2008 UnboundClauses.clear();
2012 return BindingChecker.checkOverlap();
2017 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2022 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
2023 if (RS->getSignatureIdent() != Ident) {
2024 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
2028 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
2034 if (
auto *SignatureDecl =
2035 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
2042 llvm::VersionTuple SMVersion =
2047 uint32_t ZMax = 1024;
2048 uint32_t ThreadMax = 1024;
2049 if (IsDXIL && SMVersion.getMajor() <= 4) {
2052 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
2062 diag::err_hlsl_numthreads_argument_oor)
2071 diag::err_hlsl_numthreads_argument_oor)
2080 diag::err_hlsl_numthreads_argument_oor)
2085 if (
X * Y * Z > ThreadMax) {
2086 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
2103 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
2111 if (SpelledArgsCount > 1 &&
2115 uint32_t Preferred = 0;
2116 if (SpelledArgsCount > 2 &&
2120 if (SpelledArgsCount > 2) {
2123 diag::err_attribute_power_of_two_in_range)
2124 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
2129 if (Preferred < Min || Preferred >
Max) {
2131 diag::err_attribute_power_of_two_in_range)
2132 << AL <<
Min <<
Max << Preferred;
2135 }
else if (SpelledArgsCount > 1) {
2138 diag::err_attribute_power_of_two_in_range)
2139 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
2143 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
2146 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
2151 diag::err_attribute_power_of_two_in_range)
2152 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
2157 HLSLWaveSizeAttr *NewAttr =
2194 uint32_t Binding = 0;
2216 uint32_t IndexValue(0), ExplicitIndex(0);
2219 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2221 assert(IndexValue > 0 ? ExplicitIndex :
true);
2224 if (Kind == SemanticKind::Invalid) {
2225 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2231 case SemanticKind::RenderTargetArrayIndex:
2232 case SemanticKind::ViewPortArrayIndex:
2233 case SemanticKind::ClipDistance:
2234 case SemanticKind::CullDistance:
2235 case SemanticKind::OutputControlPointID:
2236 case SemanticKind::DomainLocation:
2237 case SemanticKind::PrimitiveID:
2238 case SemanticKind::GSInstanceID:
2239 case SemanticKind::SampleIndex:
2240 case SemanticKind::IsFrontFace:
2241 case SemanticKind::Coverage:
2242 case SemanticKind::InnerCoverage:
2243 case SemanticKind::Depth:
2244 case SemanticKind::DepthLessEqual:
2245 case SemanticKind::DepthGreaterEqual:
2246 case SemanticKind::StencilRef:
2247 case SemanticKind::TessFactor:
2248 case SemanticKind::InsideTessFactor:
2249 case SemanticKind::ViewID:
2250 case SemanticKind::CullPrimitive:
2251 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2257 D->
addAttr(HLSLParsedSemanticAttr::Create(
2263 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2264 << AL <<
"shader constant in a constant buffer";
2268 uint32_t SubComponent;
2278 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2283 if (IsAggregateTy) {
2284 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2288 if ((Component * 32 + Size) > 128) {
2289 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2294 EltTy = VT->getElementType();
2296 if (Align > 32 && Component == 1) {
2299 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2313 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2316 llvm::Triple::EnvironmentType ShaderType;
2317 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2318 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2319 << AL << Str << ArgLoc;
2333 Expr *SampleCountExpr) {
2334 assert(AttrList.size() &&
"expected list of resource attributes");
2341 HLSLAttributedResourceType::Attributes ResAttrs;
2343 bool HasResourceClass =
false;
2344 bool HasResourceDimension =
false;
2345 for (
const Attr *A : AttrList) {
2350 case attr::HLSLResourceClass: {
2352 if (HasResourceClass) {
2354 ? diag::warn_duplicate_attribute_exact
2355 : diag::warn_duplicate_attribute)
2359 ResAttrs.ResourceClass = RC;
2360 HasResourceClass =
true;
2363 case attr::HLSLResourceDimension: {
2364 llvm::dxil::ResourceDimension RD =
2366 if (HasResourceDimension) {
2368 ? diag::warn_duplicate_attribute_exact
2369 : diag::warn_duplicate_attribute)
2373 ResAttrs.ResourceDimension = RD;
2374 HasResourceDimension =
true;
2377 case attr::HLSLIsROV:
2378 if (ResAttrs.IsROV) {
2382 ResAttrs.IsROV =
true;
2384 case attr::HLSLRawBuffer:
2385 if (ResAttrs.RawBuffer) {
2389 ResAttrs.RawBuffer =
true;
2391 case attr::HLSLIsArray:
2392 if (ResAttrs.IsArray) {
2396 ResAttrs.IsArray =
true;
2398 case attr::HLSLIsMultiSampled:
2399 if (ResAttrs.SampleCountExpr) {
2405 ResAttrs.SampleCountExpr =
2411 case attr::HLSLIsCounter:
2412 if (ResAttrs.IsCounter) {
2416 ResAttrs.IsCounter =
true;
2418 case attr::HLSLContainedType: {
2421 if (!ContainedTy.
isNull()) {
2423 ? diag::warn_duplicate_attribute_exact
2424 : diag::warn_duplicate_attribute)
2433 llvm_unreachable(
"unhandled resource attribute type");
2437 if (!HasResourceClass) {
2438 S.
Diag(AttrList.back()->getRange().getEnd(),
2439 diag::err_hlsl_missing_resource_class);
2444 Wrapped, ContainedTy, ResAttrs);
2446 if (LocInfo && ContainedTyInfo) {
2459 if (!
T->isHLSLResourceType()) {
2460 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2475 AttributeCommonInfo::AS_CXX11, 0, false ,
2480 case ParsedAttr::AT_HLSLResourceClass: {
2481 StringRef Identifier;
2483 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2488 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2489 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2490 <<
"ResourceClass" << Identifier;
2493 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2497 case ParsedAttr::AT_HLSLResourceDimension: {
2498 StringRef Identifier;
2500 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2504 llvm::dxil::ResourceDimension RD;
2505 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2507 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2508 <<
"ResourceDimension" << Identifier;
2511 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2515 case ParsedAttr::AT_HLSLIsROV:
2519 case ParsedAttr::AT_HLSLRawBuffer:
2523 case ParsedAttr::AT_HLSLIsCounter:
2527 case ParsedAttr::AT_HLSLIsArray:
2531 case ParsedAttr::AT_HLSLIsMultiSampled:
2535 case ParsedAttr::AT_HLSLContainedType: {
2537 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2543 assert(TSI &&
"no type source info for attribute argument");
2545 diag::err_incomplete_type))
2547 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2552 llvm_unreachable(
"unhandled HLSL attribute");
2555 HLSLResourcesTypeAttrs.emplace_back(A);
2561 if (!HLSLResourcesTypeAttrs.size())
2567 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2568 const HLSLAttributedResourceType *RT =
2575 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2577 HLSLResourcesTypeAttrs.clear();
2585 auto I = LocsForHLSLAttributedResources.find(RT);
2586 if (I != LocsForHLSLAttributedResources.end()) {
2587 LocInfo = I->second;
2588 LocsForHLSLAttributedResources.erase(I);
2597void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2598 const RecordType *RT) {
2606 "incomplete arrays inside user defined types are not supported");
2615 if (
const HLSLAttributedResourceType *AttrResType =
2616 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2621 Bindings.addDeclBindingInfo(VD, RC);
2622 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2628 collectResourceBindingsOnUserRecordDecl(VD, RT);
2640 bool SpecifiedSpace) {
2641 int RegTypeNum =
static_cast<int>(RegType);
2644 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2645 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2650 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2651 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2652 : ResourceClass::SRV;
2662 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2666 if (
const HLSLAttributedResourceType *AttrResType =
2667 HLSLAttributedResourceType::findHandleTypeOnResource(
2684 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2685 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2690 if (RegType == RegisterType::CBuffer)
2691 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2692 else if (RegType != RegisterType::C)
2693 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2697 if (RegType == RegisterType::C)
2698 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2700 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2710 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2718 bool RegisterTypesDetected[5] = {
false};
2719 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2722 if (HLSLResourceBindingAttr *
attr =
2723 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2726 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2727 int otherRegTypeNum =
static_cast<int>(otherRegType);
2729 diag::err_hlsl_duplicate_register_annotation)
2733 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2741 bool SpecifiedSpace) {
2746 "expecting VarDecl or HLSLBufferDecl");
2758 const uint64_t &Limit,
2761 uint64_t ArrayCount = 1) {
2766 if (StartSlot > Limit)
2770 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2773 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2774 Count = CAT->
getSize().getZExtValue();
2776 QualType ElemTy = AT->getElementType();
2778 ArrayCount * Count);
2782 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2785 if (ResTy->getAttrs().ResourceClass != ResClass)
2789 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2790 if (EndSlot > Limit)
2794 StartSlot = EndSlot + 1;
2799 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2802 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2805 ResClass, Ctx, ArrayCount))
2812 ResClass, Ctx, ArrayCount))
2826 const uint64_t Limit = UINT32_MAX;
2827 if (SlotNum > Limit)
2832 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2835 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2836 uint64_t BaseSlot = SlotNum;
2844 return (BaseSlot > Limit);
2851 return (SlotNum > Limit);
2854 llvm_unreachable(
"unexpected decl type");
2858 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2860 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2861 Ty = IAT->getElementType();
2863 diag::err_incomplete_type))
2867 StringRef Slot =
"";
2868 StringRef Space =
"";
2872 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2882 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2888 SpaceLoc = Loc->
getLoc();
2891 if (Str.starts_with(
"space")) {
2893 SpaceLoc = Loc->
getLoc();
2902 std::optional<unsigned> SlotNum;
2903 unsigned SpaceNum = 0;
2906 if (!Slot.empty()) {
2908 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2911 if (RegType == RegisterType::I) {
2912 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2915 const StringRef SlotNumStr = Slot.substr(1);
2920 if (SlotNumStr.getAsInteger(10, N)) {
2921 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2929 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2938 if (!Space.starts_with(
"space")) {
2939 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2942 StringRef SpaceNumStr = Space.substr(5);
2943 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2944 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2949 if (SlotNum.has_value())
2954 HLSLResourceBindingAttr *NewAttr =
2955 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2957 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2981 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2983 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2987 Cur = AT->getModifiedType();
2998 ? attr::HLSLRowMajor
2999 : attr::HLSLColumnMajor;
3003 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
3012 if (ExistingKind == AttrK) {
3013 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
3015 Diag(AL.
getLoc(), diag::note_previous_attribute);
3019 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3020 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
3022 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
3027 if (AttrK == attr::HLSLRowMajor)
3028 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
3029 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
3040 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
3042 if (
T.isNull() ||
T->isDependentType())
3047 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3048 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
3056using llvm::dxil::BarrierMemoryTypeFlag;
3057using llvm::dxil::BarrierSemanticFlag;
3059template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
3060 return llvm::to_underlying(Flag);
3074 bool DiagnoseAvailability;
3101 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
3105 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
3106 unsigned CurrentShaderStageBit;
3111 bool ReportOnlyShaderStageIssues;
3114 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
3115 static_assert(
sizeof(
unsigned) >= 4);
3116 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
3117 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
3118 "ShaderType is too big for this bitmap");
3121 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
3122 CurrentShaderEnvironment = ShaderType;
3123 CurrentShaderStageBit = (1 << bitmapIndex);
3126 void SetUnknownShaderStageContext() {
3127 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
3128 CurrentShaderStageBit = (1 << 31);
3131 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
3132 return CurrentShaderEnvironment;
3135 bool InUnknownShaderStageContext()
const {
3136 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
3140 void AddToScannedFunctions(
const FunctionDecl *FD) {
3141 unsigned &ScannedStages = ScannedDecls[FD];
3142 ScannedStages |= CurrentShaderStageBit;
3145 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
3147 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
3148 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
3151 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
3152 return ScannerStages & CurrentShaderStageBit;
3155 static bool NeverBeenScanned(
unsigned ScannedStages) {
3156 return ScannedStages == 0;
3160 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3161 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3163 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3164 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3165 void DiagnoseBarrierCall(CallExpr *CE);
3166 uint64_t DiagnoseBarrierGroupMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3167 bool HasVisibleGroup,
bool IsAllMemory);
3168 uint64_t DiagnoseBarrierNodeMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3169 bool HasKnownStage,
bool IsAllMemory);
3170 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg, uint64_t SemanticFlags,
3171 bool HasVisibleGroup);
3172 void DiagnoseBarrierScope(Expr *SemanticArg, uint64_t MemoryFlags,
3173 uint64_t SemanticFlags);
3176 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3177 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3178 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3179 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3182 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3183 void RunOnFunction(
const FunctionDecl *FD);
3185 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3186 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3188 HandleFunctionOrMethodRef(FD, DRE);
3192 bool VisitMemberExpr(MemberExpr *ME)
override {
3193 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3195 HandleFunctionOrMethodRef(FD, ME);
3199 bool VisitCallExpr(CallExpr *CE)
override {
3200 DiagnoseBarrierCall(CE);
3205uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3206 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasVisibleGroup,
3209 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3210 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3215 diag::err_hlsl_barrier_flag_requires_group)
3220 return MemoryFlags & ~GroupSharedMemory;
3223uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3224 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasKnownStage,
3227 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3228 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3233 diag::err_hlsl_barrier_node_memory_requires_node);
3237 return MemoryFlags & ~NodeMemory;
3240void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3241 Expr *SemanticArg, uint64_t SemanticFlags,
bool HasVisibleGroup) {
3242 if (HasVisibleGroup ||
3243 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3247 diag::err_hlsl_barrier_flag_requires_group)
3248 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3254void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3255 uint64_t MemoryFlags,
3256 uint64_t SemanticFlags) {
3257 if (ReportOnlyShaderStageIssues)
3261 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3262 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3263 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3265 (MemoryFlags & DeviceScopeMemory) == 0)
3267 diag::err_hlsl_barrier_scope_requires_memory)
3269 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3273 diag::err_hlsl_barrier_scope_requires_memory)
3277void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3279 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3282 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3283 const bool HasKnownStage = !InUnknownShaderStageContext();
3284 const bool HasVisibleGroup =
3285 !HasKnownStage || Stage == llvm::Triple::Compute ||
3286 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3288 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3291 std::optional<llvm::APSInt>
Value =
3295 MemoryFlags =
Value->getZExtValue();
3296 const bool IsAllMemory =
3297 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3299 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3300 HasVisibleGroup, IsAllMemory);
3301 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3302 HasKnownStage, IsAllMemory);
3303 }
else if (!HasVisibleGroup) {
3305 diag::err_hlsl_barrier_resource_requires_group);
3310 std::optional<llvm::APSInt>
Value =
3316 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3319 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3322void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3325 "expected DeclRefExpr or MemberExpr");
3327 if (DiagnoseAvailability)
3328 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3329 CheckDeclAvailability(
3334 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3335 DeclsToScan.push_back(FDWithBody);
3338void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3343 llvm::Triple::EnvironmentType::Library;
3352 DeclContextsToScan.push_back(TU);
3354 while (!DeclContextsToScan.empty()) {
3355 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3356 for (
auto &D : DC->
decls()) {
3363 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3364 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3369 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3374 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3375 if (!IsLibraryShader && FD->
getName() == EntryName) {
3378 diag::err_hlsl_ambiguous_entry_point)
3380 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3386 SetShaderStageContext(ShaderAttr->getType());
3395 for (
const auto *Redecl : FD->
redecls()) {
3396 if (Redecl->isInExportDeclContext()) {
3403 SetUnknownShaderStageContext();
3410 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3417void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3418 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3419 DeclsToScan.push_back(FD);
3421 while (!DeclsToScan.empty()) {
3429 const unsigned ScannedStages = GetScannedStages(FD);
3430 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3433 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3435 AddToScannedFunctions(FD);
3440bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3441 const AvailabilityAttr *AA) {
3446 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3447 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3450 llvm::Triple::EnvironmentType AttrEnv =
3451 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3453 return CurrentEnv == AttrEnv;
3456const AvailabilityAttr *
3457DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3458 AvailabilityAttr
const *PartialMatch =
nullptr;
3462 for (
const auto *A : D->
attrs()) {
3463 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3464 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3465 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3466 StringRef TargetPlatform =
3470 if (AttrPlatform == TargetPlatform) {
3472 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3474 PartialMatch = Avail;
3478 return PartialMatch;
3483void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3484 const AvailabilityAttr *AA,
3503 if (ReportOnlyShaderStageIssues)
3509 if (InUnknownShaderStageContext())
3514 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3515 VersionTuple Introduced = AA->getIntroduced();
3524 llvm::StringRef PlatformName(
3527 llvm::StringRef CurrentEnvStr =
3528 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3530 llvm::StringRef AttrEnvStr =
3531 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3532 bool UseEnvironment = !AttrEnvStr.empty();
3534 if (EnvironmentMatches) {
3535 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3536 <<
Range << D << PlatformName << Introduced.getAsString()
3537 << UseEnvironment << CurrentEnvStr;
3539 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3543 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3544 << D << PlatformName << Introduced.getAsString()
3546 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3553 if (!DefaultCBufferDecls.empty()) {
3556 DefaultCBufferDecls);
3559 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3563 for (
const Decl *VD : DefaultCBufferDecls) {
3564 const HLSLResourceBindingAttr *RBA =
3565 VD->
getAttr<HLSLResourceBindingAttr>();
3566 if (RBA && RBA->hasRegisterSlot() &&
3567 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3574 SemaRef.Consumer.HandleTopLevelDecl(DG);
3576 diagnoseAvailabilityViolations(TU);
3585 "expected member expr to have resource record type or array of them");
3591 const Expr *NonConstIndexExpr =
nullptr;
3594 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3595 if (!NonConstIndexExpr)
3603 diag::err_hlsl_resource_member_array_access_not_constant);
3607 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3608 const Expr *IdxExpr = ASE->getIdx();
3610 NonConstIndexExpr = IdxExpr;
3612 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3613 E = SubME->getBase();
3614 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3615 E = ICE->getSubExpr();
3617 llvm_unreachable(
"unexpected expr type in resource member access");
3626 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3629 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3632 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3636 [[maybe_unused]]
bool LookupSucceeded =
3637 SemaRef.LookupQualifiedName(ConvR, RD);
3638 assert(LookupSucceeded);
3647std::optional<ExprResult>
3650 const HLSLAttributedResourceType *ResTy =
3651 HLSLAttributedResourceType::findHandleTypeOnResource(
3652 BaseType.getTypePtr());
3654 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3655 return std::nullopt;
3657 QualType TemplateType = ResTy->getContainedType();
3661 assert(NamedConversionDecl &&
3662 "Could not find conversion function for ConstantBuffer.");
3663 auto *ConversionDecl =
3666 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3676 const bool DiagnoseAvailability =
3678 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3679 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3680 .RunOnTranslationUnit(TU);
3687 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3690 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3715 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3728 if (!BaseType->isFloat32Type())
3729 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3730 << ArgOrdinal << 5 << 0
3740 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3741 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3742 << ArgOrdinal << 5 << 0
3751 if (!BaseType->isDoubleType()) {
3754 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3755 << ArgOrdinal << PassedType;
3762 unsigned ArgIndex) {
3763 auto *Arg = TheCall->
getArg(ArgIndex);
3765 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3768 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3782 << (ArgIndex + 1) << LValueTy;
3792 if (VecTy->getElementType()->isDoubleType())
3793 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3794 << ArgOrdinal << 1 << 0 << 1
3804 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3805 << ArgOrdinal << 5 << 1
3814 if (VecTy->getElementType()->isUnsignedIntegerType())
3817 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3818 << ArgOrdinal << 4 << 3 << 0
3827 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3828 << ArgOrdinal << 5 << 3
3834 unsigned ArgOrdinal,
unsigned Width) {
3837 ArgTy = VTy->getElementType();
3839 uint64_t ElementBitCount =
3841 if (ElementBitCount != Width) {
3843 diag::err_integer_incorrect_bit_count)
3844 << Width << ElementBitCount;
3855 else if (
auto *MatTyA =
3858 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3864 unsigned ArgIndex) {
3873 diag::err_typecheck_expect_scalar_or_vector)
3874 << ArgType << Scalar;
3881 QualType Scalar,
unsigned ArgIndex) {
3892 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3905 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3906 << ArgType << Scalar;
3911 unsigned ArgIndex) {
3916 if (!(ArgType->isScalarType() ||
3917 (VTy && VTy->getElementType()->isScalarType()))) {
3919 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3927 unsigned ArgIndex) {
3930 if (ArgType->isDependentType())
3934 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3935 ElementType = VectorTy->getElementType();
3937 ElementType = MatrixTy->getElementType();
3939 if (ElementType->isBooleanType())
3942 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3944 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3949 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3957 unsigned ArgIndex) {
3959 assert(ArgIndex < TheCall->getNumArgs());
3967 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3992 diag::err_typecheck_call_different_arg_types)
4011 Arg1ScalarTy = VTy->getElementType();
4015 Arg2ScalarTy = VTy->getElementType();
4018 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4019 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4029 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
4031 diag::err_typecheck_vector_lengths_not_equal)
4037 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
4039 diag::err_typecheck_vector_lengths_not_equal)
4059 Arg1ScalarTy = MTy->getElementType();
4063 Arg2ScalarTy = MTy->getElementType();
4066 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4067 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4072 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
4074 for (
Expr *Arg : {Arg1, Arg2}) {
4077 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
4079 diag::err_typecheck_vector_lengths_not_equal)
4081 << Arg->getSourceRange();
4097 unsigned ArgIndex) {
4102 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
4105 unsigned int ActualDim = 1;
4107 ActualDim = VTy->getNumElements();
4108 IndexTy = VTy->getElementType();
4112 diag::err_typecheck_expect_int)
4118 const HLSLAttributedResourceType *ResTy =
4120 assert(ResTy &&
"Resource argument must be a resource");
4121 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
4123 unsigned int ExpectedDim = 1;
4124 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
4126 (ResAttrs.IsArray ? 1 : 0);
4128 if (ActualDim != ExpectedDim) {
4130 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
4141 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
4145 const HLSLAttributedResourceType *ResTy =
4149 diag::err_typecheck_expect_hlsl_resource)
4153 if (Check && Check(ResTy)) {
4155 diag::err_invalid_hlsl_resource_type)
4165 "expected resource handle type");
4166 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4167 auto MainAttrs = MainResType->getAttrs();
4168 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4169 MainAttrs.IsCounter =
true;
4171 MainResType->getContainedType(),
4182 return "SampleBias";
4184 return "SampleGrad";
4186 return "SampleLevel";
4190 return "SampleCmpLevelZero";
4192 llvm_unreachable(
"Invalid SampleKind");
4202 if (!MD || !MD->getDeclName().isIdentifier())
4209 return MD->getName();
4217 StringRef DefaultName) {
4222 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4249 if (SMVersion >= VersionTuple(6, 7))
4252 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4254 << ContainedType << SMVersion.getAsString();
4259 bool IncludeArraySlice =
true) {
4262 [](
const HLSLAttributedResourceType *ResType) {
4263 return ResType->getAttrs().ResourceDimension ==
4264 llvm::dxil::ResourceDimension::Unknown;
4270 [](
const HLSLAttributedResourceType *ResType) {
4271 return ResType->getAttrs().ResourceClass !=
4272 llvm::hlsl::ResourceClass::Sampler;
4280 unsigned ExpectedDim =
4282 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4311 unsigned NextIdx = 3;
4323 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4327 std::optional<llvm::APSInt> ComponentOpt =
4330 int64_t ComponentVal = ComponentOpt->getSExtValue();
4331 if (ComponentVal != 0) {
4334 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4335 "The component is not in the expected range.");
4337 diag::err_hlsl_gathercmp_invalid_component)
4347 const HLSLAttributedResourceType *ResourceTy =
4350 unsigned ExpectedDim =
4353 &S, TheCall->
getArg(NextIdx),
4359 assert(ResourceTy->hasContainedType() &&
4360 "Expecting a contained type for resource with a dimension "
4362 QualType ReturnType = ResourceTy->getContainedType();
4365 IsCmp ?
"GatherCmp" :
"Gather"))
4370 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4376 ReturnType = VecTy->getElementType();
4389 [](
const HLSLAttributedResourceType *ResType) {
4390 return ResType->getAttrs().ResourceDimension ==
4391 llvm::dxil::ResourceDimension::Unknown;
4401 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4408 unsigned ResourceDim =
4410 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4426 TheCall->
setType(ResourceTy->getContainedType());
4436 [](
const HLSLAttributedResourceType *ResType) {
4437 return !ResType->isMultiSampled();
4446 unsigned ResourceDim =
4448 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4466 TheCall->
setType(ResourceTy->getContainedType());
4471 unsigned MinArgs, MaxArgs;
4499 const HLSLAttributedResourceType *ResourceTy =
4501 unsigned ExpectedDim =
4504 unsigned NextIdx = 3;
4529 &S, TheCall->
getArg(NextIdx),
4542 assert(ResourceTy->hasContainedType() &&
4543 "Expecting a contained type for resource with a dimension "
4545 QualType ReturnType = ResourceTy->getContainedType();
4556 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4573 unsigned MinArgs,
unsigned MaxArgs,
4575 bool ReportsOriginalValue) {
4576 if (MinArgs == MaxArgs) {
4579 }
else if (TheCall->
getNumArgs() < MinArgs) {
4580 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4590 const bool DestIsOK =
4596 diag::err_builtin_invalid_arg_type)
4610 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4626 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4632 const unsigned NumArgs = TheCall->
getNumArgs();
4633 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4644 switch (BuiltinID) {
4645 case Builtin::BI__builtin_hlsl_barrier: {
4646 if (
SemaRef.checkArgCount(TheCall, 2))
4649 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4650 llvm::Triple::dxil) {
4658 std::optional<llvm::APSInt> MemoryFlags =
4662 diag::err_constant_integer_arg_type)
4666 if ((MemoryFlags->getZExtValue() &
4667 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4669 diag::err_hlsl_invalid_barrier_memory_flags);
4673 const HLSLAttributedResourceType *ResTy =
4674 HLSLAttributedResourceType::findHandleTypeOnResource(
4678 diag::err_typecheck_expect_hlsl_resource)
4682 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4684 diag::err_invalid_hlsl_resource_type)
4691 std::optional<llvm::APSInt> SemanticFlags =
4693 if (!SemanticFlags) {
4695 diag::err_constant_integer_arg_type)
4699 if ((SemanticFlags->getZExtValue() &
4700 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4702 diag::err_hlsl_invalid_barrier_semantic_flags);
4709 case Builtin::BI__builtin_hlsl_adduint64: {
4710 if (
SemaRef.checkArgCount(TheCall, 2))
4724 if (NumElementsArg != 2 && NumElementsArg != 4) {
4726 << 1 << 64 << NumElementsArg * 32;
4740 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4741 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4748 QualType ContainedTy = ResourceTy->getContainedType();
4749 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4752 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4757 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4758 if (
SemaRef.checkArgCount(TheCall, 3) ||
4765 "expected pointer type for second argument");
4772 diag::err_invalid_use_of_array_type);
4776 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4779 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4784 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4785 if (
SemaRef.checkArgCount(TheCall, 2) ||
4787 SemaRef.getASTContext().IntTy))
4794 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4795 if (
SemaRef.checkArgCount(TheCall, 3) ||
4798 SemaRef.getASTContext().UnsignedIntTy) ||
4800 SemaRef.getASTContext().UnsignedIntTy) ||
4806 QualType ReturnType = ResourceTy->getContainedType();
4811 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4812 if (
SemaRef.checkArgCount(TheCall, 4) ||
4815 SemaRef.getASTContext().UnsignedIntTy) ||
4817 SemaRef.getASTContext().UnsignedIntTy) ||
4823 "expected pointer type for second argument");
4830 diag::err_invalid_use_of_array_type);
4836 case Builtin::BI__builtin_hlsl_resource_load_level:
4838 case Builtin::BI__builtin_hlsl_resource_load_ms:
4840 case Builtin::BI__builtin_hlsl_resource_sample:
4842 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4844 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4846 case Builtin::BI__builtin_hlsl_resource_sample_level:
4848 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4850 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4852 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4853 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4855 case Builtin::BI__builtin_hlsl_resource_gather:
4857 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4859 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4860 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4866 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4867 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4873 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4874 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4880 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4881 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4887 TheCall->
setType(CounterHandleTy);
4890 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4891 if (
SemaRef.checkArgCount(TheCall, 2) ||
4894 SemaRef.getASTContext().UnsignedIntTy))
4902 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4903 if (
SemaRef.checkArgCount(TheCall, 1) ||
4911 TheCall->
setType(CounterHandleTy);
4914 case Builtin::BI__builtin_hlsl_and:
4915 case Builtin::BI__builtin_hlsl_or: {
4916 if (
SemaRef.checkArgCount(TheCall, 2))
4930 case Builtin::BI__builtin_hlsl_all:
4931 case Builtin::BI__builtin_hlsl_any: {
4932 if (
SemaRef.checkArgCount(TheCall, 1))
4938 case Builtin::BI__builtin_hlsl_asdouble: {
4939 if (
SemaRef.checkArgCount(TheCall, 2))
4943 SemaRef.Context.UnsignedIntTy,
4948 SemaRef.Context.UnsignedIntTy,
4957 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4958 if (
SemaRef.BuiltinElementwiseTernaryMath(
4964 case Builtin::BI__builtin_hlsl_dot: {
4966 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4972 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4973 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4974 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4984 EltTy = VecTy->getElementType();
4985 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4998 case Builtin::BI__builtin_hlsl_select: {
4999 if (
SemaRef.checkArgCount(TheCall, 3))
5008 if (VTy && VTy->getElementType()->isBooleanType() &&
5012 if (MTy && MTy->getElementType()->isBooleanType() &&
5017 case Builtin::BI__builtin_hlsl_elementwise_saturate:
5018 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
5019 if (
SemaRef.checkArgCount(TheCall, 1))
5025 diag::err_builtin_invalid_arg_type)
5028 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5032 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
5033 case Builtin::BI__builtin_hlsl_elementwise_frac:
5034 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
5035 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
5036 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
5037 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
5038 if (
SemaRef.checkArgCount(TheCall, 1))
5043 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5047 case Builtin::BI__builtin_hlsl_elementwise_isfinite:
5048 case Builtin::BI__builtin_hlsl_elementwise_isinf:
5049 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
5050 if (
SemaRef.checkArgCount(TheCall, 1))
5055 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5060 case Builtin::BI__builtin_hlsl_mad: {
5061 if (
SemaRef.BuiltinElementwiseTernaryMath(
5067 case Builtin::BI__builtin_hlsl_mul: {
5068 if (
SemaRef.checkArgCount(TheCall, 2))
5078 return VTy->getElementType();
5080 return MTy->getElementType();
5084 QualType EltTy0 = getElemType(Ty0);
5093 if (IsVec0 && IsMat1) {
5096 }
else if (IsMat0 && IsVec1) {
5100 assert(IsMat0 && IsMat1);
5110 case Builtin::BI__builtin_elementwise_fma: {
5111 if (
SemaRef.checkArgCount(TheCall, 3) ||
5126 case Builtin::BI__builtin_hlsl_transpose: {
5127 if (
SemaRef.checkArgCount(TheCall, 1))
5136 << 1 << 3 << 0 << 0 << ArgTy;
5141 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
5145 case Builtin::BI__builtin_hlsl_elementwise_sign: {
5146 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5154 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5155 if (
SemaRef.checkArgCount(TheCall, 1))
5169 unsigned NumElts = VecTy->getNumElements();
5179 case Builtin::BI__builtin_hlsl_wave_active_max:
5180 case Builtin::BI__builtin_hlsl_wave_active_min:
5181 case Builtin::BI__builtin_hlsl_wave_active_sum:
5182 case Builtin::BI__builtin_hlsl_wave_active_product: {
5183 if (
SemaRef.checkArgCount(TheCall, 1))
5196 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5197 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5198 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5199 if (
SemaRef.checkArgCount(TheCall, 1))
5214 (VTy && VTy->getElementType()->isIntegerType()))) {
5216 diag::err_builtin_invalid_arg_type)
5217 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5225 case Builtin::BI__builtin_hlsl_interlocked_add:
5226 case Builtin::BI__builtin_hlsl_interlocked_and:
5227 case Builtin::BI__builtin_hlsl_interlocked_max:
5228 case Builtin::BI__builtin_hlsl_interlocked_min:
5229 case Builtin::BI__builtin_hlsl_interlocked_or:
5230 case Builtin::BI__builtin_hlsl_interlocked_xor:
5236 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5242 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5248 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5254 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5260 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5268 case Builtin::BI__builtin_elementwise_bitreverse: {
5276 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
5277 if (
SemaRef.checkArgCount(TheCall, 1))
5282 if (!(
ArgType->isScalarType())) {
5284 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5289 if (!(
ArgType->isBooleanType())) {
5291 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5298 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5299 if (
SemaRef.checkArgCount(TheCall, 2))
5307 diag::err_typecheck_convert_incompatible)
5308 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5321 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5322 if (
SemaRef.checkArgCount(TheCall, 1))
5331 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5332 if (
SemaRef.checkArgCount(TheCall, 0))
5336 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5337 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5338 if (
SemaRef.checkArgCount(TheCall, 1))
5351 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5352 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5353 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5354 if (
SemaRef.checkArgCount(TheCall, 1))
5366 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5367 if (
SemaRef.checkArgCount(TheCall, 3))
5373 SemaRef.Context.UnsignedIntTy, 1) ||
5375 SemaRef.Context.UnsignedIntTy, 2))
5383 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5384 if (
SemaRef.checkArgCount(TheCall, 1))
5391 case Builtin::BI__builtin_elementwise_acos:
5392 case Builtin::BI__builtin_elementwise_asin:
5393 case Builtin::BI__builtin_elementwise_atan:
5394 case Builtin::BI__builtin_elementwise_atan2:
5395 case Builtin::BI__builtin_elementwise_ceil:
5396 case Builtin::BI__builtin_elementwise_cos:
5397 case Builtin::BI__builtin_elementwise_cosh:
5398 case Builtin::BI__builtin_elementwise_exp:
5399 case Builtin::BI__builtin_elementwise_exp2:
5400 case Builtin::BI__builtin_elementwise_exp10:
5401 case Builtin::BI__builtin_elementwise_floor:
5402 case Builtin::BI__builtin_elementwise_fmod:
5403 case Builtin::BI__builtin_elementwise_log:
5404 case Builtin::BI__builtin_elementwise_log2:
5405 case Builtin::BI__builtin_elementwise_log10:
5406 case Builtin::BI__builtin_elementwise_pow:
5407 case Builtin::BI__builtin_elementwise_roundeven:
5408 case Builtin::BI__builtin_elementwise_sin:
5409 case Builtin::BI__builtin_elementwise_sinh:
5410 case Builtin::BI__builtin_elementwise_sqrt:
5411 case Builtin::BI__builtin_elementwise_tan:
5412 case Builtin::BI__builtin_elementwise_tanh:
5413 case Builtin::BI__builtin_elementwise_trunc: {
5419 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5420 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5421 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5422 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5423 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5428 std::optional<llvm::APSInt> Offset =
5430 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5432 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5438 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5439 if (
SemaRef.checkArgCount(TheCall, 1))
5450 ArgTy = VTy->getElementType();
5453 diag::err_builtin_invalid_arg_type)
5462 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5463 if (
SemaRef.checkArgCount(TheCall, 1))
5478 WorkList.push_back(BaseTy);
5479 while (!WorkList.empty()) {
5481 T =
T.getCanonicalType().getUnqualifiedType();
5482 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5490 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5491 llvm::append_range(List, ElementFields);
5496 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5497 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5500 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5501 List.insert(List.end(), MT->getNumElementsFlattened(),
5502 MT->getElementType());
5505 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5506 if (RD->isStandardLayout())
5507 RD = RD->getStandardLayoutBaseWithFields();
5511 if (RD->
isUnion() || !RD->isAggregate()) {
5517 for (
const auto *FD : RD->
fields())
5518 if (!FD->isUnnamedBitField())
5519 FieldTypes.push_back(FD->
getType());
5521 std::reverse(FieldTypes.begin(), FieldTypes.end());
5522 llvm::append_range(WorkList, FieldTypes);
5526 if (!RD->isStandardLayout()) {
5528 for (
const auto &
Base : RD->bases())
5529 FieldTypes.push_back(
Base.getType());
5530 std::reverse(FieldTypes.begin(), FieldTypes.end());
5531 llvm::append_range(WorkList, FieldTypes);
5566 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5572 int ArraySize = VT->getNumElements();
5577 QualType ElTy = VT->getElementType();
5581 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5597 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5606 return llvm::equal(T1Types, T2Types,
5608 return SemaRef.IsLayoutCompatible(LHS, RHS);
5617 bool HadError =
false;
5619 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5627 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5628 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5629 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5630 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5632 if (NSpellingIdx != OSpellingIdx) {
5634 diag::err_hlsl_param_qualifier_mismatch)
5635 << NDAttr << NewParam;
5651 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5666 llvm_unreachable(
"HLSL doesn't support pointers.");
5669 llvm_unreachable(
"HLSL doesn't support complex types.");
5671 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5673 llvm_unreachable(
"Should have returned before this");
5683 llvm_unreachable(
"HLSL doesn't support complex types.");
5685 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5690 llvm_unreachable(
"HLSL doesn't support pointers.");
5692 llvm_unreachable(
"Should have returned before this");
5698 llvm_unreachable(
"HLSL doesn't support pointers.");
5701 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5705 llvm_unreachable(
"HLSL doesn't support complex types.");
5708 llvm_unreachable(
"Unhandled scalar cast");
5729 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5735 SrcTy = SrcMatTy->getElementType();
5740 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5741 if (DestTypes[I]->isUnionType())
5773 if (SrcTypes.size() < DestTypes.size())
5776 unsigned SrcSize = SrcTypes.size();
5777 unsigned DstSize = DestTypes.size();
5779 for (I = 0; I < DstSize && I < SrcSize; I++) {
5780 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5788 for (; I < SrcSize; I++) {
5789 if (SrcTypes[I]->isUnionType())
5832 tok::equal, ArgOpV, OpV);
5844 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5845 "We should not get here without a parameter modifier expression");
5846 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5853 << Arg << (IsInOut ? 1 : 0);
5857 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5864 << Arg << (IsInOut ? 1 : 0);
5872 Param->getBeginLoc(), IsInOut);
5880 "Pointer and reference types cannot be inout or out parameters");
5881 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5897 for (
const auto *FD : RD->
fields()) {
5901 assert(RD->getNumBases() <= 1 &&
5902 "HLSL doesn't support multiple inheritance");
5903 return RD->getNumBases()
5908 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5909 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5921 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5926 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5932 if (
Decl->getType().hasAddressSpace())
5935 if (
Decl->getType()->isDependentType())
5947 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5961 llvm::Triple::Vulkan;
5962 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5963 if (HasDeclaredAPushConstant)
5969 HasDeclaredAPushConstant =
true;
5996class StructBindingContext {
5999 HLSLResourceBindingAttr *RegBindingsAttrs[4];
6000 unsigned RegBindingOffset[4];
6003 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
6004 static_cast<unsigned>(RegisterType::UAV) == 1 &&
6005 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
6006 static_cast<unsigned>(RegisterType::Sampler) == 3,
6007 "unexpected register type values");
6010 HLSLVkBindingAttr *VkBindingAttr;
6011 unsigned VkBindingOffset;
6016 StructBindingContext(
VarDecl *VD) {
6017 for (
unsigned i = 0; i < 4; ++i) {
6018 RegBindingsAttrs[i] =
nullptr;
6019 RegBindingOffset[i] = 0;
6021 VkBindingAttr =
nullptr;
6022 VkBindingOffset = 0;
6028 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
6030 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
6033 RegBindingsAttrs[RegTypeIdx] = RBA;
6038 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
6039 VkBindingAttr = VBA;
6046 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
6047 unsigned Range,
bool HasCounter) {
6048 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
6050 if (VkBindingAttr) {
6051 unsigned Offset = VkBindingOffset;
6052 VkBindingOffset +=
Range;
6053 return HLSLVkBindingAttr::CreateImplicit(
6054 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
6055 VkBindingAttr->getRange());
6058 HLSLResourceBindingAttr *RBA =
6059 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6060 HLSLResourceBindingAttr *NewAttr =
nullptr;
6062 if (RBA && RBA->hasRegisterSlot()) {
6065 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6066 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6068 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6069 StringRef NewSlotNumberStr =
6071 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6072 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6073 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6077 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6078 NewAttr->setBinding(RegType, std::nullopt,
6079 RBA ? RBA->getSpaceNumber() : 0);
6083 NewAttr->setImplicitCounterBindingOrderID(
6092static void createGlobalResourceDeclForStruct(
6094 QualType ResTy, StructBindingContext &BindingCtx) {
6096 "expected resource type or array of resources");
6107 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6108 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6113 const HLSLAttributedResourceType *ResHandleTy =
6114 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6118 Attr *BindingAttr = BindingCtx.createBindingAttr(
6120 ResDecl->
addAttr(BindingAttr);
6121 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6130 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6137static void handleArrayOfStructWithResources(
6139 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6144static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6146 EmbeddedResourceNameBuilder &NameBuilder,
6147 StructBindingContext &BindingCtx) {
6150 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6157 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6171 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6174 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6176 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6178 "resource arrays should have been already handled");
6179 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6188handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6190 EmbeddedResourceNameBuilder &NameBuilder,
6191 StructBindingContext &BindingCtx) {
6199 if (!SubCAT && !ElementRD)
6202 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6205 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6208 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6221void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6222 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6223 StructBindingContext BindingCtx(VD);
6227 "Expected non-resource struct or array type");
6230 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6234 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6235 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6243 if (
SemaRef.RequireCompleteType(
6246 diag::err_typecheck_decl_incomplete_type)) {
6260 DefaultCBufferDecls.push_back(VD);
6265 collectResourceBindingsOnVarDecl(VD);
6267 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6279 processExplicitBindingsOnDecl(VD);
6317 handleGlobalStructOrArrayOfWithResources(VD);
6321 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6330 "expected resource record type");
6346 const char *CreateMethodName;
6348 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6349 :
"__createFromBinding";
6351 CreateMethodName = HasCounter
6352 ?
"__createFromImplicitBindingWithImplicitCounter"
6353 :
"__createFromImplicitBinding";
6358 if (!CreateMethod) {
6363 "create method lookup should always succeed for built-in resource "
6372 Args.push_back(RegSlot);
6380 Args.push_back(OrderId);
6386 Args.push_back(Space);
6390 Args.push_back(RangeSize);
6394 Args.push_back(Index);
6396 StringRef VarName = VD->
getName();
6404 Args.push_back(NameCast);
6412 Args.push_back(CounterId);
6435 SemaRef.CheckCompleteVariableDeclaration(VD);
6441 "expected array of resource records");
6462 lookupMethod(
SemaRef, ResourceDecl,
6463 HasCounter ?
"__createFromBindingWithImplicitCounter"
6464 :
"__createFromBinding",
6468 CreateMethod = lookupMethod(
6470 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6471 :
"__createFromImplicitBinding",
6514std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6515 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6516 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6517 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6518 if (!TrueInfo || !FalseInfo)
6519 return std::nullopt;
6520 if (*TrueInfo != *FalseInfo)
6521 return std::nullopt;
6525 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6534 if (
const auto *AttrResType =
6535 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6537 return Bindings.getDeclBindingInfo(VD, RC);
6544void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6545 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6548 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6553 if (*ExprBinding ==
nullptr)
6556 auto PrevBinding = Assigns.find(VD);
6557 if (PrevBinding == Assigns.end()) {
6559 Assigns.insert({VD, *ExprBinding});
6564 if (*ExprBinding != PrevBinding->second) {
6566 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6568 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6579 "expected LHS to be a resource record or array of resource records");
6580 if (Opc != BO_Assign)
6585 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6593 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6598 trackLocalResource(VD, RHSExpr);
6615void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6617 "expected global variable that contains HLSL resource");
6620 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6621 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6622 ? ResourceClass::CBuffer
6623 : ResourceClass::SRV);
6636 if (
const HLSLAttributedResourceType *AttrResType =
6637 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6638 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6643 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6644 collectResourceBindingsOnUserRecordDecl(VD, RT);
6650void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6653 bool HasBinding =
false;
6654 for (Attr *A : VD->
attrs()) {
6657 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6658 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6661 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6662 if (!RBA || !RBA->hasRegisterSlot())
6667 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6668 "never have an attribute created");
6670 if (RT == RegisterType::C) {
6671 if (Bindings.hasBindingInfoForDecl(VD))
6673 diag::warn_hlsl_user_defined_type_missing_member)
6674 <<
static_cast<int>(RT);
6682 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6687 diag::warn_hlsl_user_defined_type_missing_member)
6688 <<
static_cast<int>(RT);
6696class InitListTransformer {
6700 QualType *DstIt =
nullptr;
6701 Expr **ArgIt =
nullptr;
6707 bool castInitializer(Expr *E) {
6708 assert(DstIt &&
"This should always be something!");
6709 if (DstIt == DestTypes.end()) {
6711 ArgExprs.push_back(E);
6716 DstIt = DestTypes.begin();
6719 Ctx, *DstIt,
false);
6724 ArgExprs.push_back(
Init);
6729 bool buildInitializerListImpl(Expr *E) {
6731 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6732 for (
auto *SubInit :
Init->inits())
6733 if (!buildInitializerListImpl(SubInit))
6743 return castInitializer(E);
6757 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6762 for (uint64_t I = 0; I <
Size; ++I) {
6764 SizeTy, SourceLocation());
6770 if (!castInitializer(ElExpr.
get()))
6775 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6776 unsigned Rows = MTy->getNumRows();
6777 unsigned Cols = MTy->getNumColumns();
6778 QualType ElemTy = MTy->getElementType();
6780 for (
unsigned R = 0;
R < Rows; ++
R) {
6781 for (
unsigned C = 0;
C < Cols; ++
C) {
6794 if (!castInitializer(ElExpr.
get()))
6802 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6806 for (uint64_t I = 0; I <
Size; ++I) {
6808 SizeTy, SourceLocation());
6813 if (!buildInitializerListImpl(ElExpr.
get()))
6820 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6821 RecordDecls.push_back(RD);
6822 while (RecordDecls.back()->getNumBases()) {
6823 CXXRecordDecl *D = RecordDecls.back();
6825 "HLSL doesn't support multiple inheritance");
6826 RecordDecls.push_back(
6829 while (!RecordDecls.empty()) {
6830 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6831 for (
auto *FD : RD->
fields()) {
6832 if (FD->isUnnamedBitField())
6840 if (!buildInitializerListImpl(Res.
get()))
6848 Expr *generateInitListsImpl(QualType Ty) {
6850 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6855 llvm::SmallVector<Expr *>
Inits;
6860 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6861 ElTy = ATy->getElementType();
6862 Size = ATy->getNumElements();
6863 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6864 ElTy = CMTy->getElementType();
6865 Size = CMTy->getNumElementsFlattened();
6868 ElTy = VTy->getElementType();
6869 Size = VTy->getZExtSize();
6871 for (uint64_t I = 0; I <
Size; ++I)
6872 Inits.push_back(generateInitListsImpl(ElTy));
6875 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6876 RecordDecls.push_back(RD);
6877 while (RecordDecls.back()->getNumBases()) {
6878 CXXRecordDecl *D = RecordDecls.back();
6880 "HLSL doesn't support multiple inheritance");
6881 RecordDecls.push_back(
6884 while (!RecordDecls.empty()) {
6885 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6886 for (
auto *FD : RD->
fields())
6887 if (!FD->isUnnamedBitField())
6892 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6893 Inits.back()->getEndLoc(),
false);
6894 NewInit->setType(Ty);
6899 llvm::SmallVector<QualType, 16> DestTypes;
6900 llvm::SmallVector<Expr *, 16> ArgExprs;
6901 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6902 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6903 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6904 InitTy = Entity.
getType().getNonReferenceType();
6914 DstIt = DestTypes.begin();
6917 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6919 Expr *generateInitLists() {
6920 assert(!ArgExprs.empty() &&
6921 "Call buildInitializerList to generate argument expressions.");
6922 ArgIt = ArgExprs.begin();
6924 return generateInitListsImpl(InitTy);
6925 llvm::SmallVector<Expr *>
Inits;
6926 while (ArgIt != ArgExprs.end())
6927 Inits.push_back(generateInitListsImpl(InitTy));
6930 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6931 Inits.back()->getEndLoc(),
false);
6932 llvm::APInt ArySize(64,
Inits.size());
6934 ArraySizeModifier::Normal, 0));
6946 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6953 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6957 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6977 if (
Init->getType()->isScalarType())
6980 InitListTransformer ILT(
SemaRef, Entity);
6982 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6990 Init->setInit(I, E);
6992 if (!ILT.buildInitializerList(E))
6995 size_t ExpectedSize = ILT.DestTypes.size();
6996 size_t ActualSize = ILT.ArgExprs.size();
6997 if (ExpectedSize == 0 && ActualSize == 0)
7004 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7006 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7007 << (int)(ExpectedSize < ActualSize) << InitTy
7008 << ExpectedSize << ActualSize;
7018 assert(ExpectedSize > 0 &&
7019 "The expected size of an incomplete array type must be at least 1.");
7021 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
7029 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7030 if (ExpectedSize != ActualSize) {
7031 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
7032 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7033 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
7040 Init->resizeInits(Ctx, NewInit->getNumInits());
7041 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
7042 Init->updateInit(Ctx, I, NewInit->getInit(I));
7050 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7060 StringRef AccessorName = CompName->
getName();
7061 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7063 unsigned Rows = MT->getNumRows();
7064 unsigned Cols = MT->getNumColumns();
7065 bool IsZeroBasedAccessor =
false;
7066 unsigned ChunkLen = 0;
7067 if (AccessorName.size() < 2)
7069 "length 4 for zero based: \'_mRC\' or "
7070 "length 3 for one-based: \'_RC\' accessor",
7073 if (AccessorName[0] ==
'_') {
7074 if (AccessorName[1] ==
'm') {
7075 IsZeroBasedAccessor =
true;
7082 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7085 if (AccessorName.size() % ChunkLen != 0) {
7086 const llvm::StringRef
Expected = IsZeroBasedAccessor
7087 ?
"zero based: '_mRC' accessor"
7088 :
"one-based: '_RC' accessor";
7093 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7094 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7095 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7097 bool HasRepeated =
false;
7099 unsigned NumComponents = 0;
7100 const char *Begin = AccessorName.data();
7102 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7103 const char *Chunk = Begin + I;
7104 char RowChar = 0, ColChar = 0;
7105 if (IsZeroBasedAccessor) {
7107 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7108 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7110 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7117 if (Chunk[0] !=
'_')
7119 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7126 bool IsDigitsError =
false;
7128 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7132 IsDigitsError =
true;
7136 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7140 IsDigitsError =
true;
7145 unsigned Row = RowChar -
'0';
7146 unsigned Col = ColChar -
'0';
7148 bool HasIndexingError =
false;
7149 if (IsZeroBasedAccessor) {
7151 if (!isZeroBasedIndex(Row)) {
7152 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7154 HasIndexingError =
true;
7156 if (!isZeroBasedIndex(Col)) {
7157 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7159 HasIndexingError =
true;
7163 if (!isOneBasedIndex(Row)) {
7164 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7166 HasIndexingError =
true;
7168 if (!isOneBasedIndex(Col)) {
7169 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7171 HasIndexingError =
true;
7178 if (HasIndexingError)
7184 bool HasBoundsError =
false;
7186 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7188 HasBoundsError =
true;
7191 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7193 HasBoundsError =
true;
7198 unsigned FlatIndex = Row * Cols + Col;
7199 if (Seen[FlatIndex])
7201 Seen[FlatIndex] =
true;
7204 if (NumComponents == 0 || NumComponents > 4) {
7205 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7210 QualType ElemTy = MT->getElementType();
7211 if (NumComponents == 1)
7217 for (Sema::ExtVectorDeclsType::iterator
7221 if ((*I)->getUnderlyingType() == VT)
7232 trackLocalResource(VDecl,
Init);
7234 const HLSLVkConstantIdAttr *ConstIdAttr =
7235 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7242 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7252 int ConstantID = ConstIdAttr->getId();
7253 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7255 ConstIdAttr->getLocation());
7259 if (
C->getType()->getCanonicalTypeUnqualified() !=
7263 Context.getTrivialTypeSourceInfo(
7264 Init->getType(),
Init->getExprLoc()),
7283 if (!Params || Params->
size() != 1)
7296 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7297 if (TTP->hasDefaultArgument()) {
7298 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7301 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7302 if (NTTP->hasDefaultArgument()) {
7303 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7306 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7307 if (TTPD->hasDefaultArgument()) {
7308 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7315 return SemaRef.CheckTemplateIdType(
7317 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