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) {
920 Semantic && llvm::hlsl::getSemanticKind(Semantic->getSemanticName()) ==
921 SemanticKind::Position;
924 Diag(A->getLocation(), diag::err_hlsl_interpolation_position);
925 Diag(Semantic->getLocation(), diag::note_conflicting_attribute);
932 Diag(A->getLocation(), diag::err_hlsl_interpolation_type) <<
T;
958 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
959 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
962 if (Shader->getType() != Env) {
963 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
975 case llvm::Triple::UnknownEnvironment:
976 case llvm::Triple::Library:
978 case llvm::Triple::RootSignature:
979 llvm_unreachable(
"rootsig environment has no functions");
981 llvm_unreachable(
"Unhandled environment in triple");
987 HLSLAppliedSemanticAttr *Semantic,
992 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
993 assert(ShaderAttr &&
"Entry point has no shader attribute");
994 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
995 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
998 case SemanticKind::Position:
1002 return (ST == llvm::Triple::Vertex && !IsInput) ||
1003 (ST == llvm::Triple::Pixel && IsInput);
1004 case SemanticKind::VertexID:
1006 case SemanticKind::InstanceID:
1007 return ST == llvm::Triple::Vertex && IsInput;
1008 case SemanticKind::ShadingRate:
1013 return (ST == llvm::Triple::Pixel && IsInput) ||
1014 (ST == llvm::Triple::Vertex && !IsInput);
1020bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1023 SemanticInfo &ActiveSemantic,
1024 SemaHLSL::SemanticContext &SC) {
1025 if (ActiveSemantic.Semantic ==
nullptr) {
1026 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1027 if (ActiveSemantic.Semantic)
1028 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1031 if (!ActiveSemantic.Semantic) {
1037 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1038 ActiveSemantic.Semantic->getAttrName()->getName(),
1039 ActiveSemantic.Index.value_or(0));
1044 QualType
T = D == FD ? FD->getReturnType() : D->
getType();
1045 const ConstantArrayType *AT =
1048 Diag(A->getLoc(), diag::err_hlsl_semantic_zero_sized_array)
1049 << A->getAttrName();
1057 if (
const auto *MT = BaseTy->
getAs<ConstantMatrixType>())
1060 : MT->getNumColumns();
1062 checkSemanticAnnotation(FD, D, A, SC, ElementCount);
1065 unsigned Location = ActiveSemantic.Index.value_or(0);
1068 any(SC.CurrentIOType & IOType::In))) {
1069 bool HasVkLocation =
false;
1070 if (
auto *A = D->
getAttr<HLSLVkLocationAttr>()) {
1071 HasVkLocation =
true;
1072 Location = A->getLocation();
1075 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1076 Diag(D->
getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1079 SC.UsesExplicitVkLocations = HasVkLocation;
1082 ActiveSemantic.Index = Location + ElementCount;
1084 StringRef BaseName = ActiveSemantic.Semantic->getAttrName()->getName();
1085 std::string LowerName = BaseName.lower();
1086 for (
unsigned I = 0; I < ElementCount; ++I) {
1087 auto [It, Inserted] = SC.ActiveSemantics.try_emplace(
1088 (Twine(LowerName) + Twine(Location + I)).str(), D->
getLocation());
1091 << (BaseName + Twine(Location + I)).str();
1092 Diag(It->second, diag::note_previous_use);
1100bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1103 SemanticInfo &ActiveSemantic,
1104 SemaHLSL::SemanticContext &SC) {
1105 if (ActiveSemantic.Semantic ==
nullptr) {
1106 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1107 if (ActiveSemantic.Semantic)
1108 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1114 const RecordType *RT = dyn_cast<RecordType>(
T);
1116 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1119 const RecordDecl *RD = RT->getDecl();
1120 for (FieldDecl *Field : RD->
fields()) {
1121 SemanticInfo Info = ActiveSemantic;
1122 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1123 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1126 if (ActiveSemantic.Semantic)
1127 ActiveSemantic = Info;
1134 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1135 assert(ShaderAttr &&
"Entry point has no shader attribute");
1136 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1140 case llvm::Triple::Pixel:
1141 case llvm::Triple::Vertex:
1142 case llvm::Triple::Geometry:
1143 case llvm::Triple::Hull:
1144 case llvm::Triple::Domain:
1145 case llvm::Triple::RayGeneration:
1146 case llvm::Triple::Intersection:
1147 case llvm::Triple::AnyHit:
1148 case llvm::Triple::ClosestHit:
1149 case llvm::Triple::Miss:
1150 case llvm::Triple::Callable:
1151 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1152 diagnoseAttrStageMismatch(NT, ST,
1153 {llvm::Triple::Compute,
1154 llvm::Triple::Amplification,
1155 llvm::Triple::Mesh});
1158 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1159 diagnoseAttrStageMismatch(WS, ST,
1160 {llvm::Triple::Compute,
1161 llvm::Triple::Amplification,
1162 llvm::Triple::Mesh});
1167 case llvm::Triple::Compute:
1168 case llvm::Triple::Amplification:
1169 case llvm::Triple::Mesh:
1170 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1172 << llvm::Triple::getEnvironmentTypeName(ST);
1175 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1177 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1178 }
else if (Ver < VersionTuple(6, 6)) {
1179 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1182 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1185 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1186 << WS << WS->getSpelledArgsCount() <<
"6.8";
1191 case llvm::Triple::RootSignature:
1192 llvm_unreachable(
"rootsig environment has no function entry point");
1194 llvm_unreachable(
"Unhandled environment in triple");
1197 SemaHLSL::SemanticContext InputSC = {};
1198 InputSC.CurrentIOType = IOType::In;
1199 SemaHLSL::SemanticContext OutputSC = {};
1200 OutputSC.CurrentIOType = IOType::Out;
1203 SemanticInfo ActiveSemantic;
1204 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1205 if (ActiveSemantic.Semantic)
1206 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1210 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1211 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1215 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1216 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1217 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1220 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1221 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1226 SemanticInfo ActiveSemantic;
1227 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1228 if (ActiveSemantic.Semantic)
1229 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1231 if (ST == llvm::Triple::Vertex &&
1232 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1234 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1238void SemaHLSL::checkSemanticAnnotation(
1240 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC,
1241 unsigned ElementCount) {
1242 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1243 assert(ShaderAttr &&
"Entry point has no shader attribute");
1244 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1247 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1248 llvm::hlsl::SemanticInterpretation Interpretation =
1249 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1250 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid) {
1251 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1256 if (Kind == SemanticKind::ShadingRate) {
1258 if (TT.isDXIL() && TT.getOSVersion() < VersionTuple(6, 4)) {
1259 Diag(SemanticAttr->getLoc(),
1260 diag::err_hlsl_semantic_in_wrong_shader_model)
1261 << SemanticAttr->getAttrName() <<
"6.4";
1268 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary) {
1269 diagnoseSemanticType(Param, SemanticAttr, SemanticKind::Arbitrary);
1273 diagnoseSystemSemanticIndex(SemanticAttr, Kind, ElementCount);
1274 diagnoseSemanticType(Param, SemanticAttr, Kind);
1277void SemaHLSL::diagnoseSystemSemanticIndex(
const HLSLAppliedSemanticAttr *A,
1279 unsigned ElementCount) {
1280 assert(Kind != SemanticKind::Invalid && Kind != SemanticKind::Arbitrary &&
1281 "expected a recognized system semantic");
1282 assert(ElementCount > 0 &&
"a semantic covers at least one element");
1285 uint32_t FirstIndex = A->getSemanticIndex();
1287 constexpr uint32_t MaxSemanticIndex = std::numeric_limits<uint32_t>::max();
1288 if (LastIndex > MaxSemanticIndex) {
1289 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1290 << A->getAttrName() << LastIndex << MaxSemanticIndex;
1298 case SemanticKind::ClipDistance:
1299 case SemanticKind::CullDistance:
1301 case SemanticKind::Target: {
1302 constexpr unsigned MaxTargetIndex = 7;
1303 if (LastIndex > MaxTargetIndex)
1304 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1305 << A->getAttrName() << LastIndex << MaxTargetIndex;
1309 Diag(A->getLoc(), diag::err_hlsl_semantic_indexing_not_supported)
1310 << A->getAttrName();
1317 return VT->getElementType();
1320 return MT->getElementType();
1326 return VT->getNumElements();
1347void SemaHLSL::diagnoseSemanticType(
const Decl *D,
1348 const HLSLAppliedSemanticAttr *A,
1350 assert(Kind != SemanticKind::Invalid &&
"expected a valid semantic");
1354 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
1360 T =
T.getNonReferenceType();
1363 QualType DeclaredTy =
T;
1365 T = AT->getElementType();
1373 case SemanticKind::DispatchThreadID:
1374 case SemanticKind::GroupID:
1375 case SemanticKind::GroupThreadID:
1377 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1378 << A->getAttrName() << 1 << 3
1381 case SemanticKind::GroupIndex:
1383 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1384 << A->getAttrName() << 0 << 1 << 1
1387 case SemanticKind::VertexID:
1389 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1390 << A->getAttrName() << 0 << 1
1393 case SemanticKind::Position:
1394 case SemanticKind::Target:
1396 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1397 << A->getAttrName() << 1 << 4
1400 case SemanticKind::InstanceID:
1401 case SemanticKind::ShadingRate:
1408 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1409 << A->getAttrName() << 0 << 1
1411 (IsSPIRV ? 4 : 3) << DeclaredTy;
1424 Diag(A->getLoc(), diag::err_hlsl_semantic_64bit_type)
1425 << A->getAttrName() << DeclaredTy;
1428void SemaHLSL::diagnoseAttrStageMismatch(
1429 const Attr *A, llvm::Triple::EnvironmentType Stage,
1430 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1431 SmallVector<StringRef, 8> StageStrings;
1432 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1433 [](llvm::Triple::EnvironmentType ST) {
1435 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1437 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1438 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1439 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1442void SemaHLSL::diagnoseSemanticStageMismatch(
1443 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1446 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1447 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1448 return Info.Stage == Stage;
1451 StringRef CurrentIOTypeName =
"patch constants or primitives";
1452 if (
any(CurrentIOType & IOType::In))
1453 CurrentIOTypeName =
"inputs";
1454 else if (
any(CurrentIOType & IOType::Out))
1455 CurrentIOTypeName =
"outputs";
1458 if (It == Allowed.end()) {
1459 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1460 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1461 << CurrentIOTypeName;
1465 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1466 if (!(AllowedIOTypes & CurrentIOType)) {
1467 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1468 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1469 << CurrentIOTypeName;
1474template <CastKind Kind>
1477 Ty = VTy->getElementType();
1482template <CastKind Kind>
1494 if (LHSFloat && RHSFloat) {
1522 if (LHSSigned == RHSSigned) {
1523 if (IsCompAssign || IntOrder >= 0)
1531 if (IntOrder != (LHSSigned ? 1 : -1)) {
1532 if (IsCompAssign || RHSSigned)
1541 if (IsCompAssign || LHSSigned)
1568 return CK_FloatingCast;
1570 return CK_IntegralCast;
1572 return CK_IntegralToFloating;
1574 return CK_FloatingToIntegral;
1580 bool IsCompAssign) {
1587 if (!LVecTy && IsCompAssign) {
1589 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1591 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1593 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1598 unsigned EndSz = std::numeric_limits<unsigned>::max();
1601 LSz = EndSz = LVecTy->getNumElements();
1604 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1605 "one of the above should have had a value");
1609 if (IsCompAssign && LSz != EndSz) {
1611 diag::err_hlsl_vector_compound_assignment_truncation)
1612 << LHSType << RHSType;
1618 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1623 if (!IsCompAssign && !LVecTy)
1627 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1628 return Ctx.getCommonSugaredType(LHSType, RHSType);
1636 LElTy, RElTy, IsCompAssign);
1639 "HLSL Vectors can only contain integer or floating point types");
1641 LElTy, RElTy, IsCompAssign);
1646 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1647 "Called with non-logical operator");
1649 llvm::raw_svector_ostream OS(Buff);
1651 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1652 OS << NewFnName <<
"(";
1662std::pair<IdentifierInfo *, bool>
1665 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1672 return {DeclIdent,
Found};
1683 for (
auto &RootSigElement : RootElements)
1684 Elements.push_back(RootSigElement.getElement());
1688 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1690 SignatureDecl->setImplicit();
1696 if (RootSigOverrideIdent) {
1699 if (
SemaRef.LookupQualifiedName(R, DC))
1700 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1708struct PerVisibilityBindingChecker {
1711 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1715 llvm::dxbc::ShaderVisibility Vis;
1720 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1722 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1723 llvm::dxil::ResourceClass RC,
uint32_t Space,
1725 const hlsl::RootSignatureElement *Elem) {
1727 assert(BuilderIndex < Builders.size() &&
1728 "Not enough builders for visibility type");
1729 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1730 static_cast<const void *
>(Elem));
1732 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1733 "'All' visibility must come first");
1734 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1735 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1736 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1737 static_cast<const void *
>(Elem));
1739 ElemInfoMap.push_back({Elem,
Visibility,
false});
1742 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1743 auto It = llvm::lower_bound(
1745 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1746 assert(It->Elem == Elem &&
"Element not in map");
1750 bool checkOverlap() {
1751 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1752 return LHS.Elem < RHS.Elem;
1755 bool HadOverlap =
false;
1757 using llvm::hlsl::BindingInfoBuilder;
1758 auto ReportOverlap = [
this,
1759 &HadOverlap](
const BindingInfoBuilder &Builder,
1760 const llvm::hlsl::Binding &Reported) {
1764 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1765 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1766 const auto *PrevElem =
1767 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1769 ElemInfo &Info =
getInfo(Elem);
1774 Info.Diagnosed =
true;
1776 ElemInfo &PrevInfo =
getInfo(PrevElem);
1777 llvm::dxbc::ShaderVisibility CommonVis =
1778 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1781 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1782 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1783 << Reported.isUnbounded() << Reported.UpperBound
1788 this->S->
Diag(PrevElem->getLocation(),
1789 diag::note_hlsl_resource_range_here);
1792 for (BindingInfoBuilder &Builder : Builders)
1793 Builder.calculateBindingInfo(ReportOverlap);
1813 bool HadError =
false;
1814 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1815 uint32_t UpperBound) {
1817 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1818 << LowerBound << UpperBound;
1825 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1826 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1827 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1830 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1831 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1832 ReportError(Loc, 0, 0xfffffffe);
1835 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1836 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1837 ReportError(Loc, 0, 0xffffffef);
1840 const uint32_t Version =
1841 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1842 const uint32_t VersionEnum = Version - 1;
1843 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1845 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1852 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1853 if (
const auto *Descriptor =
1854 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1855 VerifyRegister(Loc, Descriptor->Reg.Number);
1856 VerifySpace(Loc, Descriptor->Space);
1858 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1860 ReportFlagError(Loc);
1861 }
else if (
const auto *Constants =
1862 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1863 VerifyRegister(Loc, Constants->Reg.Number);
1864 VerifySpace(Loc, Constants->Space);
1865 }
else if (
const auto *Sampler =
1866 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1867 VerifyRegister(Loc, Sampler->Reg.Number);
1868 VerifySpace(Loc, Sampler->Space);
1871 "By construction, parseFloatParam can't produce a NaN from a "
1872 "float_literal token");
1874 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1875 ReportError(Loc, 0, 16);
1876 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1877 ReportFloatError(Loc, -16.f, 15.99f);
1878 }
else if (
const auto *Clause =
1879 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1881 VerifyRegister(Loc, Clause->Reg.Number);
1882 VerifySpace(Loc, Clause->Space);
1884 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1888 ReportError(Loc, 1, 0xfffffffe);
1891 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1893 ReportFlagError(Loc);
1897 PerVisibilityBindingChecker BindingChecker(
this);
1898 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1903 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1904 if (
const auto *Descriptor =
1905 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1906 uint32_t LowerBound(Descriptor->Reg.Number);
1907 uint32_t UpperBound(LowerBound);
1909 BindingChecker.trackBinding(
1910 Descriptor->Visibility,
1911 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1912 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1913 }
else if (
const auto *Constants =
1914 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1915 uint32_t LowerBound(Constants->Reg.Number);
1916 uint32_t UpperBound(LowerBound);
1918 BindingChecker.trackBinding(
1919 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1920 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1921 }
else if (
const auto *Sampler =
1922 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1923 uint32_t LowerBound(Sampler->Reg.Number);
1924 uint32_t UpperBound(LowerBound);
1926 BindingChecker.trackBinding(
1927 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1928 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1929 }
else if (
const auto *Clause =
1930 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1933 UnboundClauses.emplace_back(Clause, &RootSigElem);
1934 }
else if (
const auto *Table =
1935 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1936 assert(UnboundClauses.size() == Table->NumClauses &&
1937 "Number of unbound elements must match the number of clauses");
1938 bool HasAnySampler =
false;
1939 bool HasAnyNonSampler =
false;
1940 uint64_t Offset = 0;
1941 bool IsPrevUnbound =
false;
1942 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1944 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1945 HasAnySampler =
true;
1947 HasAnyNonSampler =
true;
1949 if (HasAnySampler && HasAnyNonSampler)
1950 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1955 if (Clause->NumDescriptors == 0)
1959 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1961 Offset = Clause->Offset;
1963 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1964 Offset, Clause->NumDescriptors);
1966 if (IsPrevUnbound && IsAppending)
1967 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1968 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1969 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1972 Offset = RangeBound + 1;
1973 IsPrevUnbound = Clause->NumDescriptors ==
1974 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1977 uint32_t LowerBound(Clause->Reg.Number);
1978 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1979 LowerBound, Clause->NumDescriptors);
1981 BindingChecker.trackBinding(
1983 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1984 LowerBound, UpperBound, ClauseElem);
1986 UnboundClauses.clear();
1990 return BindingChecker.checkOverlap();
1995 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2000 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
2001 if (RS->getSignatureIdent() != Ident) {
2002 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
2006 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
2012 if (
auto *SignatureDecl =
2013 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
2020 llvm::VersionTuple SMVersion =
2025 uint32_t ZMax = 1024;
2026 uint32_t ThreadMax = 1024;
2027 if (IsDXIL && SMVersion.getMajor() <= 4) {
2030 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
2040 diag::err_hlsl_numthreads_argument_oor)
2049 diag::err_hlsl_numthreads_argument_oor)
2058 diag::err_hlsl_numthreads_argument_oor)
2063 if (
X * Y * Z > ThreadMax) {
2064 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
2081 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
2089 if (SpelledArgsCount > 1 &&
2093 uint32_t Preferred = 0;
2094 if (SpelledArgsCount > 2 &&
2098 if (SpelledArgsCount > 2) {
2101 diag::err_attribute_power_of_two_in_range)
2102 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
2107 if (Preferred < Min || Preferred >
Max) {
2109 diag::err_attribute_power_of_two_in_range)
2110 << AL <<
Min <<
Max << Preferred;
2113 }
else if (SpelledArgsCount > 1) {
2116 diag::err_attribute_power_of_two_in_range)
2117 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
2121 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
2124 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
2129 diag::err_attribute_power_of_two_in_range)
2130 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
2135 HLSLWaveSizeAttr *NewAttr =
2172 uint32_t Binding = 0;
2194 uint32_t IndexValue(0), ExplicitIndex(0);
2197 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2199 assert(IndexValue > 0 ? ExplicitIndex :
true);
2202 if (Kind == SemanticKind::Invalid) {
2203 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2209 case SemanticKind::RenderTargetArrayIndex:
2210 case SemanticKind::ViewPortArrayIndex:
2211 case SemanticKind::ClipDistance:
2212 case SemanticKind::CullDistance:
2213 case SemanticKind::OutputControlPointID:
2214 case SemanticKind::DomainLocation:
2215 case SemanticKind::PrimitiveID:
2216 case SemanticKind::GSInstanceID:
2217 case SemanticKind::SampleIndex:
2218 case SemanticKind::IsFrontFace:
2219 case SemanticKind::Coverage:
2220 case SemanticKind::InnerCoverage:
2221 case SemanticKind::Depth:
2222 case SemanticKind::DepthLessEqual:
2223 case SemanticKind::DepthGreaterEqual:
2224 case SemanticKind::StencilRef:
2225 case SemanticKind::TessFactor:
2226 case SemanticKind::InsideTessFactor:
2227 case SemanticKind::ViewID:
2228 case SemanticKind::Barycentrics:
2229 case SemanticKind::CullPrimitive:
2230 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2236 D->
addAttr(HLSLParsedSemanticAttr::Create(
2242 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2243 << AL <<
"shader constant in a constant buffer";
2247 uint32_t SubComponent;
2257 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2262 if (IsAggregateTy) {
2263 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2267 if ((Component * 32 + Size) > 128) {
2268 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2273 EltTy = VT->getElementType();
2275 if (Align > 32 && Component == 1) {
2278 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2292 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2295 llvm::Triple::EnvironmentType ShaderType;
2296 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2297 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2298 << AL << Str << ArgLoc;
2312 Expr *SampleCountExpr) {
2313 assert(AttrList.size() &&
"expected list of resource attributes");
2320 HLSLAttributedResourceType::Attributes ResAttrs;
2322 bool HasResourceClass =
false;
2323 bool HasResourceDimension =
false;
2324 for (
const Attr *A : AttrList) {
2329 case attr::HLSLResourceClass: {
2331 if (HasResourceClass) {
2333 ? diag::warn_duplicate_attribute_exact
2334 : diag::warn_duplicate_attribute)
2338 ResAttrs.ResourceClass = RC;
2339 HasResourceClass =
true;
2342 case attr::HLSLResourceDimension: {
2343 llvm::dxil::ResourceDimension RD =
2345 if (HasResourceDimension) {
2347 ? diag::warn_duplicate_attribute_exact
2348 : diag::warn_duplicate_attribute)
2352 ResAttrs.ResourceDimension = RD;
2353 HasResourceDimension =
true;
2356 case attr::HLSLIsROV:
2357 if (ResAttrs.IsROV) {
2361 ResAttrs.IsROV =
true;
2363 case attr::HLSLRawBuffer:
2364 if (ResAttrs.RawBuffer) {
2368 ResAttrs.RawBuffer =
true;
2370 case attr::HLSLIsArray:
2371 if (ResAttrs.IsArray) {
2375 ResAttrs.IsArray =
true;
2377 case attr::HLSLIsMultiSampled:
2378 if (ResAttrs.SampleCountExpr) {
2384 ResAttrs.SampleCountExpr =
2390 case attr::HLSLIsCounter:
2391 if (ResAttrs.IsCounter) {
2395 ResAttrs.IsCounter =
true;
2397 case attr::HLSLContainedType: {
2400 if (!ContainedTy.
isNull()) {
2402 ? diag::warn_duplicate_attribute_exact
2403 : diag::warn_duplicate_attribute)
2412 llvm_unreachable(
"unhandled resource attribute type");
2416 if (!HasResourceClass) {
2417 S.
Diag(AttrList.back()->getRange().getEnd(),
2418 diag::err_hlsl_missing_resource_class);
2423 Wrapped, ContainedTy, ResAttrs);
2425 if (LocInfo && ContainedTyInfo) {
2438 if (!
T->isHLSLResourceType()) {
2439 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2454 AttributeCommonInfo::AS_CXX11, 0, false ,
2459 case ParsedAttr::AT_HLSLResourceClass: {
2460 StringRef Identifier;
2462 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2467 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2468 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2469 <<
"ResourceClass" << Identifier;
2472 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2476 case ParsedAttr::AT_HLSLResourceDimension: {
2477 StringRef Identifier;
2479 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2483 llvm::dxil::ResourceDimension RD;
2484 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2486 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2487 <<
"ResourceDimension" << Identifier;
2490 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2494 case ParsedAttr::AT_HLSLIsROV:
2498 case ParsedAttr::AT_HLSLRawBuffer:
2502 case ParsedAttr::AT_HLSLIsCounter:
2506 case ParsedAttr::AT_HLSLIsArray:
2510 case ParsedAttr::AT_HLSLIsMultiSampled:
2514 case ParsedAttr::AT_HLSLContainedType: {
2516 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2522 assert(TSI &&
"no type source info for attribute argument");
2524 diag::err_incomplete_type))
2526 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2531 llvm_unreachable(
"unhandled HLSL attribute");
2534 HLSLResourcesTypeAttrs.emplace_back(A);
2540 if (!HLSLResourcesTypeAttrs.size())
2546 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2547 const HLSLAttributedResourceType *RT =
2554 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2556 HLSLResourcesTypeAttrs.clear();
2564 auto I = LocsForHLSLAttributedResources.find(RT);
2565 if (I != LocsForHLSLAttributedResources.end()) {
2566 LocInfo = I->second;
2567 LocsForHLSLAttributedResources.erase(I);
2576void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2577 const RecordType *RT) {
2585 "incomplete arrays inside user defined types are not supported");
2594 if (
const HLSLAttributedResourceType *AttrResType =
2595 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2600 Bindings.addDeclBindingInfo(VD, RC);
2601 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2607 collectResourceBindingsOnUserRecordDecl(VD, RT);
2619 bool SpecifiedSpace) {
2620 int RegTypeNum =
static_cast<int>(RegType);
2623 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2624 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2629 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2630 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2631 : ResourceClass::SRV;
2641 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2645 if (
const HLSLAttributedResourceType *AttrResType =
2646 HLSLAttributedResourceType::findHandleTypeOnResource(
2663 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2664 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2669 if (RegType == RegisterType::CBuffer)
2670 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2671 else if (RegType != RegisterType::C)
2672 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2676 if (RegType == RegisterType::C)
2677 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2679 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2689 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2697 bool RegisterTypesDetected[5] = {
false};
2698 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2701 if (HLSLResourceBindingAttr *
attr =
2702 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2705 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2706 int otherRegTypeNum =
static_cast<int>(otherRegType);
2708 diag::err_hlsl_duplicate_register_annotation)
2712 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2720 bool SpecifiedSpace) {
2725 "expecting VarDecl or HLSLBufferDecl");
2737 const uint64_t &Limit,
2740 uint64_t ArrayCount = 1) {
2745 if (StartSlot > Limit)
2749 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2752 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2753 Count = CAT->
getSize().getZExtValue();
2755 QualType ElemTy = AT->getElementType();
2757 ArrayCount * Count);
2761 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2764 if (ResTy->getAttrs().ResourceClass != ResClass)
2768 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2769 if (EndSlot > Limit)
2773 StartSlot = EndSlot + 1;
2778 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2781 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2784 ResClass, Ctx, ArrayCount))
2791 ResClass, Ctx, ArrayCount))
2805 const uint64_t Limit = UINT32_MAX;
2806 if (SlotNum > Limit)
2811 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2814 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2815 uint64_t BaseSlot = SlotNum;
2823 return (BaseSlot > Limit);
2830 return (SlotNum > Limit);
2833 llvm_unreachable(
"unexpected decl type");
2837 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2839 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2840 Ty = IAT->getElementType();
2842 diag::err_incomplete_type))
2846 StringRef Slot =
"";
2847 StringRef Space =
"";
2851 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2861 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2867 SpaceLoc = Loc->
getLoc();
2870 if (Str.starts_with(
"space")) {
2872 SpaceLoc = Loc->
getLoc();
2881 std::optional<unsigned> SlotNum;
2882 unsigned SpaceNum = 0;
2885 if (!Slot.empty()) {
2887 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2890 if (RegType == RegisterType::I) {
2891 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2894 const StringRef SlotNumStr = Slot.substr(1);
2899 if (SlotNumStr.getAsInteger(10, N)) {
2900 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2908 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2917 if (!Space.starts_with(
"space")) {
2918 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2921 StringRef SpaceNumStr = Space.substr(5);
2922 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2923 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2928 if (SlotNum.has_value())
2933 HLSLResourceBindingAttr *NewAttr =
2934 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2936 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2960 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
2962 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
2966 Cur = AT->getModifiedType();
2977 ? attr::HLSLRowMajor
2978 : attr::HLSLColumnMajor;
2982 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
2991 if (ExistingKind == AttrK) {
2992 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
2994 Diag(AL.
getLoc(), diag::note_previous_attribute);
2998 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
2999 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
3001 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
3006 if (AttrK == attr::HLSLRowMajor)
3007 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
3008 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
3019 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
3021 if (
T.isNull() ||
T->isDependentType())
3026 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3027 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
3035using llvm::dxil::BarrierMemoryTypeFlag;
3036using llvm::dxil::BarrierSemanticFlag;
3038template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
3039 return llvm::to_underlying(Flag);
3053 bool DiagnoseAvailability;
3080 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
3084 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
3085 unsigned CurrentShaderStageBit;
3090 bool ReportOnlyShaderStageIssues;
3093 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
3094 static_assert(
sizeof(
unsigned) >= 4);
3095 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
3096 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
3097 "ShaderType is too big for this bitmap");
3100 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
3101 CurrentShaderEnvironment = ShaderType;
3102 CurrentShaderStageBit = (1 << bitmapIndex);
3105 void SetUnknownShaderStageContext() {
3106 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
3107 CurrentShaderStageBit = (1 << 31);
3110 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
3111 return CurrentShaderEnvironment;
3114 bool InUnknownShaderStageContext()
const {
3115 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
3119 void AddToScannedFunctions(
const FunctionDecl *FD) {
3120 unsigned &ScannedStages = ScannedDecls[FD];
3121 ScannedStages |= CurrentShaderStageBit;
3124 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
3126 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
3127 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
3130 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
3131 return ScannerStages & CurrentShaderStageBit;
3134 static bool NeverBeenScanned(
unsigned ScannedStages) {
3135 return ScannedStages == 0;
3139 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3140 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3142 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3143 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3144 void DiagnoseBarrierCall(CallExpr *CE);
3145 uint64_t DiagnoseBarrierGroupMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3146 bool HasVisibleGroup,
bool IsAllMemory);
3147 uint64_t DiagnoseBarrierNodeMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3148 bool HasKnownStage,
bool IsAllMemory);
3149 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg, uint64_t SemanticFlags,
3150 bool HasVisibleGroup);
3151 void DiagnoseBarrierScope(Expr *SemanticArg, uint64_t MemoryFlags,
3152 uint64_t SemanticFlags);
3155 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3156 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3157 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3158 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3161 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3162 void RunOnFunction(
const FunctionDecl *FD);
3164 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3165 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3167 HandleFunctionOrMethodRef(FD, DRE);
3171 bool VisitMemberExpr(MemberExpr *ME)
override {
3172 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3174 HandleFunctionOrMethodRef(FD, ME);
3178 bool VisitCallExpr(CallExpr *CE)
override {
3179 DiagnoseBarrierCall(CE);
3184uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3185 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasVisibleGroup,
3188 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3189 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3194 diag::err_hlsl_barrier_flag_requires_group)
3199 return MemoryFlags & ~GroupSharedMemory;
3202uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3203 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasKnownStage,
3206 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3207 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3212 diag::err_hlsl_barrier_node_memory_requires_node);
3216 return MemoryFlags & ~NodeMemory;
3219void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3220 Expr *SemanticArg, uint64_t SemanticFlags,
bool HasVisibleGroup) {
3221 if (HasVisibleGroup ||
3222 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3226 diag::err_hlsl_barrier_flag_requires_group)
3227 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3233void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3234 uint64_t MemoryFlags,
3235 uint64_t SemanticFlags) {
3236 if (ReportOnlyShaderStageIssues)
3240 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3241 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3242 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3244 (MemoryFlags & DeviceScopeMemory) == 0)
3246 diag::err_hlsl_barrier_scope_requires_memory)
3248 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3252 diag::err_hlsl_barrier_scope_requires_memory)
3256void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3258 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3261 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3262 const bool HasKnownStage = !InUnknownShaderStageContext();
3263 const bool HasVisibleGroup =
3264 !HasKnownStage || Stage == llvm::Triple::Compute ||
3265 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3267 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3270 std::optional<llvm::APSInt>
Value =
3274 MemoryFlags =
Value->getZExtValue();
3275 const bool IsAllMemory =
3276 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3278 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3279 HasVisibleGroup, IsAllMemory);
3280 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3281 HasKnownStage, IsAllMemory);
3282 }
else if (!HasVisibleGroup) {
3284 diag::err_hlsl_barrier_resource_requires_group);
3289 std::optional<llvm::APSInt>
Value =
3295 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3298 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3301void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3304 "expected DeclRefExpr or MemberExpr");
3306 if (DiagnoseAvailability)
3307 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3308 CheckDeclAvailability(
3313 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3314 DeclsToScan.push_back(FDWithBody);
3317void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3322 llvm::Triple::EnvironmentType::Library;
3331 DeclContextsToScan.push_back(TU);
3333 while (!DeclContextsToScan.empty()) {
3334 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3335 for (
auto &D : DC->
decls()) {
3342 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3343 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3348 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3353 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3354 if (!IsLibraryShader && FD->
getName() == EntryName) {
3357 diag::err_hlsl_ambiguous_entry_point)
3359 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3365 SetShaderStageContext(ShaderAttr->getType());
3374 for (
const auto *Redecl : FD->
redecls()) {
3375 if (Redecl->isInExportDeclContext()) {
3382 SetUnknownShaderStageContext();
3389 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3396void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3397 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3398 DeclsToScan.push_back(FD);
3400 while (!DeclsToScan.empty()) {
3408 const unsigned ScannedStages = GetScannedStages(FD);
3409 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3412 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3414 AddToScannedFunctions(FD);
3419bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3420 const AvailabilityAttr *AA) {
3425 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3426 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3429 llvm::Triple::EnvironmentType AttrEnv =
3430 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3432 return CurrentEnv == AttrEnv;
3435const AvailabilityAttr *
3436DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3437 AvailabilityAttr
const *PartialMatch =
nullptr;
3441 for (
const auto *A : D->
attrs()) {
3442 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3443 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3444 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3445 StringRef TargetPlatform =
3449 if (AttrPlatform == TargetPlatform) {
3451 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3453 PartialMatch = Avail;
3457 return PartialMatch;
3462void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3463 const AvailabilityAttr *AA,
3482 if (ReportOnlyShaderStageIssues)
3488 if (InUnknownShaderStageContext())
3493 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3494 VersionTuple Introduced = AA->getIntroduced();
3503 llvm::StringRef PlatformName(
3506 llvm::StringRef CurrentEnvStr =
3507 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3509 llvm::StringRef AttrEnvStr =
3510 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3511 bool UseEnvironment = !AttrEnvStr.empty();
3513 if (EnvironmentMatches) {
3514 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3515 <<
Range << D << PlatformName << Introduced.getAsString()
3516 << UseEnvironment << CurrentEnvStr;
3518 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3522 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3523 << D << PlatformName << Introduced.getAsString()
3525 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3532 if (!DefaultCBufferDecls.empty()) {
3535 DefaultCBufferDecls);
3538 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3542 for (
const Decl *VD : DefaultCBufferDecls) {
3543 const HLSLResourceBindingAttr *RBA =
3544 VD->
getAttr<HLSLResourceBindingAttr>();
3545 if (RBA && RBA->hasRegisterSlot() &&
3546 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3553 SemaRef.Consumer.HandleTopLevelDecl(DG);
3555 diagnoseAvailabilityViolations(TU);
3564 "expected member expr to have resource record type or array of them");
3570 const Expr *NonConstIndexExpr =
nullptr;
3573 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3574 if (!NonConstIndexExpr)
3582 diag::err_hlsl_resource_member_array_access_not_constant);
3586 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3587 const Expr *IdxExpr = ASE->getIdx();
3589 NonConstIndexExpr = IdxExpr;
3591 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3592 E = SubME->getBase();
3593 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3594 E = ICE->getSubExpr();
3596 llvm_unreachable(
"unexpected expr type in resource member access");
3605 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3608 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3611 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3615 [[maybe_unused]]
bool LookupSucceeded =
3616 SemaRef.LookupQualifiedName(ConvR, RD);
3617 assert(LookupSucceeded);
3626std::optional<ExprResult>
3629 const HLSLAttributedResourceType *ResTy =
3630 HLSLAttributedResourceType::findHandleTypeOnResource(
3631 BaseType.getTypePtr());
3633 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3634 return std::nullopt;
3636 QualType TemplateType = ResTy->getContainedType();
3640 assert(NamedConversionDecl &&
3641 "Could not find conversion function for ConstantBuffer.");
3642 auto *ConversionDecl =
3645 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3655 const bool DiagnoseAvailability =
3657 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3658 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3659 .RunOnTranslationUnit(TU);
3666 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3669 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3694 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3707 if (!BaseType->isFloat32Type())
3708 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3709 << ArgOrdinal << 5 << 0
3719 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3720 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3721 << ArgOrdinal << 5 << 0
3730 if (!BaseType->isDoubleType()) {
3733 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3734 << ArgOrdinal << PassedType;
3741 unsigned ArgIndex) {
3742 auto *Arg = TheCall->
getArg(ArgIndex);
3744 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3747 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3761 << (ArgIndex + 1) << LValueTy;
3771 if (VecTy->getElementType()->isDoubleType())
3772 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3773 << ArgOrdinal << 1 << 0 << 1
3783 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3784 << ArgOrdinal << 5 << 1
3793 if (VecTy->getElementType()->isUnsignedIntegerType())
3796 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3797 << ArgOrdinal << 4 << 3 << 0
3806 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3807 << ArgOrdinal << 5 << 3
3813 unsigned ArgOrdinal,
unsigned Width) {
3816 ArgTy = VTy->getElementType();
3818 uint64_t ElementBitCount =
3820 if (ElementBitCount != Width) {
3822 diag::err_integer_incorrect_bit_count)
3823 << Width << ElementBitCount;
3834 else if (
auto *MatTyA =
3837 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3843 unsigned ArgIndex) {
3852 diag::err_typecheck_expect_scalar_or_vector)
3853 << ArgType << Scalar;
3860 QualType Scalar,
unsigned ArgIndex) {
3871 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3884 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3885 << ArgType << Scalar;
3890 unsigned ArgIndex) {
3895 if (!(ArgType->isScalarType() ||
3896 (VTy && VTy->getElementType()->isScalarType()))) {
3898 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3906 unsigned ArgIndex) {
3909 if (ArgType->isDependentType())
3913 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3914 ElementType = VectorTy->getElementType();
3916 ElementType = MatrixTy->getElementType();
3918 if (ElementType->isBooleanType())
3921 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3923 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3928 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3936 unsigned ArgIndex) {
3938 assert(ArgIndex < TheCall->getNumArgs());
3946 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3971 diag::err_typecheck_call_different_arg_types)
3990 Arg1ScalarTy = VTy->getElementType();
3994 Arg2ScalarTy = VTy->getElementType();
3997 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3998 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4008 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
4010 diag::err_typecheck_vector_lengths_not_equal)
4016 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
4018 diag::err_typecheck_vector_lengths_not_equal)
4038 Arg1ScalarTy = MTy->getElementType();
4042 Arg2ScalarTy = MTy->getElementType();
4045 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4046 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4051 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
4053 for (
Expr *Arg : {Arg1, Arg2}) {
4056 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
4058 diag::err_typecheck_vector_lengths_not_equal)
4060 << Arg->getSourceRange();
4076 unsigned ArgIndex) {
4081 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
4084 unsigned int ActualDim = 1;
4086 ActualDim = VTy->getNumElements();
4087 IndexTy = VTy->getElementType();
4091 diag::err_typecheck_expect_int)
4097 const HLSLAttributedResourceType *ResTy =
4099 assert(ResTy &&
"Resource argument must be a resource");
4100 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
4102 unsigned int ExpectedDim = 1;
4103 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
4105 (ResAttrs.IsArray ? 1 : 0);
4107 if (ActualDim != ExpectedDim) {
4109 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
4120 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
4124 const HLSLAttributedResourceType *ResTy =
4128 diag::err_typecheck_expect_hlsl_resource)
4132 if (Check && Check(ResTy)) {
4134 diag::err_invalid_hlsl_resource_type)
4144 "expected resource handle type");
4145 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4146 auto MainAttrs = MainResType->getAttrs();
4147 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4148 MainAttrs.IsCounter =
true;
4150 MainResType->getContainedType(),
4161 return "SampleBias";
4163 return "SampleGrad";
4165 return "SampleLevel";
4169 return "SampleCmpLevelZero";
4171 llvm_unreachable(
"Invalid SampleKind");
4181 if (!MD || !MD->getDeclName().isIdentifier())
4188 return MD->getName();
4196 StringRef DefaultName) {
4201 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4228 if (SMVersion >= VersionTuple(6, 7))
4231 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4233 << ContainedType << SMVersion.getAsString();
4238 bool IncludeArraySlice =
true) {
4241 [](
const HLSLAttributedResourceType *ResType) {
4242 return ResType->getAttrs().ResourceDimension ==
4243 llvm::dxil::ResourceDimension::Unknown;
4249 [](
const HLSLAttributedResourceType *ResType) {
4250 return ResType->getAttrs().ResourceClass !=
4251 llvm::hlsl::ResourceClass::Sampler;
4259 unsigned ExpectedDim =
4261 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4290 unsigned NextIdx = 3;
4302 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4306 std::optional<llvm::APSInt> ComponentOpt =
4309 int64_t ComponentVal = ComponentOpt->getSExtValue();
4310 if (ComponentVal != 0) {
4313 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4314 "The component is not in the expected range.");
4316 diag::err_hlsl_gathercmp_invalid_component)
4326 const HLSLAttributedResourceType *ResourceTy =
4329 unsigned ExpectedDim =
4332 &S, TheCall->
getArg(NextIdx),
4338 assert(ResourceTy->hasContainedType() &&
4339 "Expecting a contained type for resource with a dimension "
4341 QualType ReturnType = ResourceTy->getContainedType();
4344 IsCmp ?
"GatherCmp" :
"Gather"))
4349 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4355 ReturnType = VecTy->getElementType();
4368 [](
const HLSLAttributedResourceType *ResType) {
4369 return ResType->getAttrs().ResourceDimension ==
4370 llvm::dxil::ResourceDimension::Unknown;
4380 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4387 unsigned ResourceDim =
4389 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4405 TheCall->
setType(ResourceTy->getContainedType());
4415 [](
const HLSLAttributedResourceType *ResType) {
4416 return !ResType->isMultiSampled();
4425 unsigned ResourceDim =
4427 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4445 TheCall->
setType(ResourceTy->getContainedType());
4450 unsigned MinArgs, MaxArgs;
4478 const HLSLAttributedResourceType *ResourceTy =
4480 unsigned ExpectedDim =
4483 unsigned NextIdx = 3;
4508 &S, TheCall->
getArg(NextIdx),
4521 assert(ResourceTy->hasContainedType() &&
4522 "Expecting a contained type for resource with a dimension "
4524 QualType ReturnType = ResourceTy->getContainedType();
4535 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4552 unsigned MinArgs,
unsigned MaxArgs,
4554 bool ReportsOriginalValue) {
4555 if (MinArgs == MaxArgs) {
4558 }
else if (TheCall->
getNumArgs() < MinArgs) {
4559 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4569 const bool DestIsOK =
4575 diag::err_builtin_invalid_arg_type)
4589 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4605 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4611 const unsigned NumArgs = TheCall->
getNumArgs();
4612 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4623 switch (BuiltinID) {
4624 case Builtin::BI__builtin_hlsl_barrier: {
4625 if (
SemaRef.checkArgCount(TheCall, 2))
4628 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4629 llvm::Triple::dxil) {
4637 std::optional<llvm::APSInt> MemoryFlags =
4641 diag::err_constant_integer_arg_type)
4645 if ((MemoryFlags->getZExtValue() &
4646 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4648 diag::err_hlsl_invalid_barrier_memory_flags);
4652 const HLSLAttributedResourceType *ResTy =
4653 HLSLAttributedResourceType::findHandleTypeOnResource(
4657 diag::err_typecheck_expect_hlsl_resource)
4661 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4663 diag::err_invalid_hlsl_resource_type)
4670 std::optional<llvm::APSInt> SemanticFlags =
4672 if (!SemanticFlags) {
4674 diag::err_constant_integer_arg_type)
4678 if ((SemanticFlags->getZExtValue() &
4679 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4681 diag::err_hlsl_invalid_barrier_semantic_flags);
4688 case Builtin::BI__builtin_hlsl_adduint64: {
4689 if (
SemaRef.checkArgCount(TheCall, 2))
4703 if (NumElementsArg != 2 && NumElementsArg != 4) {
4705 << 1 << 64 << NumElementsArg * 32;
4719 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4720 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4727 QualType ContainedTy = ResourceTy->getContainedType();
4728 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4731 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4736 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4737 if (
SemaRef.checkArgCount(TheCall, 3) ||
4744 "expected pointer type for second argument");
4751 diag::err_invalid_use_of_array_type);
4755 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4758 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4763 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4764 if (
SemaRef.checkArgCount(TheCall, 2) ||
4766 SemaRef.getASTContext().IntTy))
4773 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4774 if (
SemaRef.checkArgCount(TheCall, 3) ||
4777 SemaRef.getASTContext().UnsignedIntTy) ||
4779 SemaRef.getASTContext().UnsignedIntTy) ||
4785 QualType ReturnType = ResourceTy->getContainedType();
4790 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4791 if (
SemaRef.checkArgCount(TheCall, 4) ||
4794 SemaRef.getASTContext().UnsignedIntTy) ||
4796 SemaRef.getASTContext().UnsignedIntTy) ||
4802 "expected pointer type for second argument");
4809 diag::err_invalid_use_of_array_type);
4815 case Builtin::BI__builtin_hlsl_resource_load_level:
4817 case Builtin::BI__builtin_hlsl_resource_load_ms:
4819 case Builtin::BI__builtin_hlsl_resource_sample:
4821 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4823 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4825 case Builtin::BI__builtin_hlsl_resource_sample_level:
4827 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4829 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4831 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4832 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4834 case Builtin::BI__builtin_hlsl_resource_gather:
4836 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4838 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4839 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4845 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4846 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4852 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4853 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4859 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4860 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4866 TheCall->
setType(CounterHandleTy);
4869 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4870 if (
SemaRef.checkArgCount(TheCall, 2) ||
4873 SemaRef.getASTContext().UnsignedIntTy))
4881 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4882 if (
SemaRef.checkArgCount(TheCall, 1) ||
4890 TheCall->
setType(CounterHandleTy);
4893 case Builtin::BI__builtin_hlsl_and:
4894 case Builtin::BI__builtin_hlsl_or: {
4895 if (
SemaRef.checkArgCount(TheCall, 2))
4909 case Builtin::BI__builtin_hlsl_all:
4910 case Builtin::BI__builtin_hlsl_any: {
4911 if (
SemaRef.checkArgCount(TheCall, 1))
4917 case Builtin::BI__builtin_hlsl_asdouble: {
4918 if (
SemaRef.checkArgCount(TheCall, 2))
4922 SemaRef.Context.UnsignedIntTy,
4927 SemaRef.Context.UnsignedIntTy,
4936 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4937 if (
SemaRef.BuiltinElementwiseTernaryMath(
4943 case Builtin::BI__builtin_hlsl_dot: {
4945 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4951 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4952 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4953 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
4963 EltTy = VecTy->getElementType();
4964 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
4977 case Builtin::BI__builtin_hlsl_select: {
4978 if (
SemaRef.checkArgCount(TheCall, 3))
4987 if (VTy && VTy->getElementType()->isBooleanType() &&
4991 if (MTy && MTy->getElementType()->isBooleanType() &&
4996 case Builtin::BI__builtin_hlsl_elementwise_saturate:
4997 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
4998 if (
SemaRef.checkArgCount(TheCall, 1))
5004 diag::err_builtin_invalid_arg_type)
5007 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5011 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
5012 case Builtin::BI__builtin_hlsl_elementwise_frac:
5013 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
5014 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
5015 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
5016 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
5017 if (
SemaRef.checkArgCount(TheCall, 1))
5022 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5026 case Builtin::BI__builtin_hlsl_elementwise_isfinite:
5027 case Builtin::BI__builtin_hlsl_elementwise_isinf:
5028 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
5029 if (
SemaRef.checkArgCount(TheCall, 1))
5034 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5039 case Builtin::BI__builtin_hlsl_mad: {
5040 if (
SemaRef.BuiltinElementwiseTernaryMath(
5046 case Builtin::BI__builtin_hlsl_mul: {
5047 if (
SemaRef.checkArgCount(TheCall, 2))
5057 return VTy->getElementType();
5059 return MTy->getElementType();
5063 QualType EltTy0 = getElemType(Ty0);
5072 if (IsVec0 && IsMat1) {
5075 }
else if (IsMat0 && IsVec1) {
5079 assert(IsMat0 && IsMat1);
5089 case Builtin::BI__builtin_elementwise_fma: {
5090 if (
SemaRef.checkArgCount(TheCall, 3) ||
5105 case Builtin::BI__builtin_hlsl_transpose: {
5106 if (
SemaRef.checkArgCount(TheCall, 1))
5115 << 1 << 3 << 0 << 0 << ArgTy;
5120 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
5124 case Builtin::BI__builtin_hlsl_elementwise_sign: {
5125 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5133 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5134 if (
SemaRef.checkArgCount(TheCall, 1))
5148 unsigned NumElts = VecTy->getNumElements();
5158 case Builtin::BI__builtin_hlsl_wave_active_max:
5159 case Builtin::BI__builtin_hlsl_wave_active_min:
5160 case Builtin::BI__builtin_hlsl_wave_active_sum:
5161 case Builtin::BI__builtin_hlsl_wave_active_product: {
5162 if (
SemaRef.checkArgCount(TheCall, 1))
5175 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5176 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5177 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5178 if (
SemaRef.checkArgCount(TheCall, 1))
5193 (VTy && VTy->getElementType()->isIntegerType()))) {
5195 diag::err_builtin_invalid_arg_type)
5196 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5204 case Builtin::BI__builtin_hlsl_interlocked_add:
5205 case Builtin::BI__builtin_hlsl_interlocked_and:
5206 case Builtin::BI__builtin_hlsl_interlocked_max:
5207 case Builtin::BI__builtin_hlsl_interlocked_min:
5208 case Builtin::BI__builtin_hlsl_interlocked_or:
5209 case Builtin::BI__builtin_hlsl_interlocked_xor:
5215 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5221 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5227 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5233 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5239 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5247 case Builtin::BI__builtin_elementwise_bitreverse: {
5255 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
5256 if (
SemaRef.checkArgCount(TheCall, 1))
5261 if (!(
ArgType->isScalarType())) {
5263 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5268 if (!(
ArgType->isBooleanType())) {
5270 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5277 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5278 if (
SemaRef.checkArgCount(TheCall, 2))
5286 diag::err_typecheck_convert_incompatible)
5287 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5300 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5301 if (
SemaRef.checkArgCount(TheCall, 1))
5310 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5311 if (
SemaRef.checkArgCount(TheCall, 0))
5315 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5316 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5317 if (
SemaRef.checkArgCount(TheCall, 1))
5330 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5331 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5332 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5333 if (
SemaRef.checkArgCount(TheCall, 1))
5345 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5346 if (
SemaRef.checkArgCount(TheCall, 3))
5352 SemaRef.Context.UnsignedIntTy, 1) ||
5354 SemaRef.Context.UnsignedIntTy, 2))
5362 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5363 if (
SemaRef.checkArgCount(TheCall, 1))
5370 case Builtin::BI__builtin_elementwise_acos:
5371 case Builtin::BI__builtin_elementwise_asin:
5372 case Builtin::BI__builtin_elementwise_atan:
5373 case Builtin::BI__builtin_elementwise_atan2:
5374 case Builtin::BI__builtin_elementwise_ceil:
5375 case Builtin::BI__builtin_elementwise_cos:
5376 case Builtin::BI__builtin_elementwise_cosh:
5377 case Builtin::BI__builtin_elementwise_exp:
5378 case Builtin::BI__builtin_elementwise_exp2:
5379 case Builtin::BI__builtin_elementwise_exp10:
5380 case Builtin::BI__builtin_elementwise_floor:
5381 case Builtin::BI__builtin_elementwise_fmod:
5382 case Builtin::BI__builtin_elementwise_log:
5383 case Builtin::BI__builtin_elementwise_log2:
5384 case Builtin::BI__builtin_elementwise_log10:
5385 case Builtin::BI__builtin_elementwise_pow:
5386 case Builtin::BI__builtin_elementwise_roundeven:
5387 case Builtin::BI__builtin_elementwise_sin:
5388 case Builtin::BI__builtin_elementwise_sinh:
5389 case Builtin::BI__builtin_elementwise_sqrt:
5390 case Builtin::BI__builtin_elementwise_tan:
5391 case Builtin::BI__builtin_elementwise_tanh:
5392 case Builtin::BI__builtin_elementwise_trunc: {
5398 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5399 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5400 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5401 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5402 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5407 std::optional<llvm::APSInt> Offset =
5409 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5411 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5417 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5418 if (
SemaRef.checkArgCount(TheCall, 1))
5429 ArgTy = VTy->getElementType();
5432 diag::err_builtin_invalid_arg_type)
5441 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5442 if (
SemaRef.checkArgCount(TheCall, 1))
5457 WorkList.push_back(BaseTy);
5458 while (!WorkList.empty()) {
5460 T =
T.getCanonicalType().getUnqualifiedType();
5461 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5469 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5470 llvm::append_range(List, ElementFields);
5475 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5476 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5479 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5480 List.insert(List.end(), MT->getNumElementsFlattened(),
5481 MT->getElementType());
5484 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5485 if (RD->isStandardLayout())
5486 RD = RD->getStandardLayoutBaseWithFields();
5490 if (RD->
isUnion() || !RD->isAggregate()) {
5496 for (
const auto *FD : RD->
fields())
5497 if (!FD->isUnnamedBitField())
5498 FieldTypes.push_back(FD->
getType());
5500 std::reverse(FieldTypes.begin(), FieldTypes.end());
5501 llvm::append_range(WorkList, FieldTypes);
5505 if (!RD->isStandardLayout()) {
5507 for (
const auto &
Base : RD->bases())
5508 FieldTypes.push_back(
Base.getType());
5509 std::reverse(FieldTypes.begin(), FieldTypes.end());
5510 llvm::append_range(WorkList, FieldTypes);
5545 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5551 int ArraySize = VT->getNumElements();
5556 QualType ElTy = VT->getElementType();
5560 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5576 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5585 return llvm::equal(T1Types, T2Types,
5587 return SemaRef.IsLayoutCompatible(LHS, RHS);
5596 bool HadError =
false;
5598 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5606 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5607 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5608 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5609 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5611 if (NSpellingIdx != OSpellingIdx) {
5613 diag::err_hlsl_param_qualifier_mismatch)
5614 << NDAttr << NewParam;
5630 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5645 llvm_unreachable(
"HLSL doesn't support pointers.");
5648 llvm_unreachable(
"HLSL doesn't support complex types.");
5650 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5652 llvm_unreachable(
"Should have returned before this");
5662 llvm_unreachable(
"HLSL doesn't support complex types.");
5664 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5669 llvm_unreachable(
"HLSL doesn't support pointers.");
5671 llvm_unreachable(
"Should have returned before this");
5677 llvm_unreachable(
"HLSL doesn't support pointers.");
5680 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5684 llvm_unreachable(
"HLSL doesn't support complex types.");
5687 llvm_unreachable(
"Unhandled scalar cast");
5708 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5714 SrcTy = SrcMatTy->getElementType();
5719 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5720 if (DestTypes[I]->isUnionType())
5752 if (SrcTypes.size() < DestTypes.size())
5755 unsigned SrcSize = SrcTypes.size();
5756 unsigned DstSize = DestTypes.size();
5758 for (I = 0; I < DstSize && I < SrcSize; I++) {
5759 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5767 for (; I < SrcSize; I++) {
5768 if (SrcTypes[I]->isUnionType())
5811 tok::equal, ArgOpV, OpV);
5823 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5824 "We should not get here without a parameter modifier expression");
5825 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5832 << Arg << (IsInOut ? 1 : 0);
5836 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5843 << Arg << (IsInOut ? 1 : 0);
5851 Param->getBeginLoc(), IsInOut);
5859 "Pointer and reference types cannot be inout or out parameters");
5860 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5876 for (
const auto *FD : RD->
fields()) {
5880 assert(RD->getNumBases() <= 1 &&
5881 "HLSL doesn't support multiple inheritance");
5882 return RD->getNumBases()
5887 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5888 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5900 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5905 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5911 if (
Decl->getType().hasAddressSpace())
5914 if (
Decl->getType()->isDependentType())
5926 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5940 llvm::Triple::Vulkan;
5941 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5942 if (HasDeclaredAPushConstant)
5948 HasDeclaredAPushConstant =
true;
5975class StructBindingContext {
5978 HLSLResourceBindingAttr *RegBindingsAttrs[4];
5979 unsigned RegBindingOffset[4];
5982 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
5983 static_cast<unsigned>(RegisterType::UAV) == 1 &&
5984 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
5985 static_cast<unsigned>(RegisterType::Sampler) == 3,
5986 "unexpected register type values");
5989 HLSLVkBindingAttr *VkBindingAttr;
5990 unsigned VkBindingOffset;
5995 StructBindingContext(
VarDecl *VD) {
5996 for (
unsigned i = 0; i < 4; ++i) {
5997 RegBindingsAttrs[i] =
nullptr;
5998 RegBindingOffset[i] = 0;
6000 VkBindingAttr =
nullptr;
6001 VkBindingOffset = 0;
6007 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
6009 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
6012 RegBindingsAttrs[RegTypeIdx] = RBA;
6017 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
6018 VkBindingAttr = VBA;
6025 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
6026 unsigned Range,
bool HasCounter) {
6027 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
6029 if (VkBindingAttr) {
6030 unsigned Offset = VkBindingOffset;
6031 VkBindingOffset +=
Range;
6032 return HLSLVkBindingAttr::CreateImplicit(
6033 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
6034 VkBindingAttr->getRange());
6037 HLSLResourceBindingAttr *RBA =
6038 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6039 HLSLResourceBindingAttr *NewAttr =
nullptr;
6041 if (RBA && RBA->hasRegisterSlot()) {
6044 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6045 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6047 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6048 StringRef NewSlotNumberStr =
6050 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6051 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6052 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6056 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6057 NewAttr->setBinding(RegType, std::nullopt,
6058 RBA ? RBA->getSpaceNumber() : 0);
6062 NewAttr->setImplicitCounterBindingOrderID(
6071static void createGlobalResourceDeclForStruct(
6073 QualType ResTy, StructBindingContext &BindingCtx) {
6075 "expected resource type or array of resources");
6086 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6087 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6092 const HLSLAttributedResourceType *ResHandleTy =
6093 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6097 Attr *BindingAttr = BindingCtx.createBindingAttr(
6099 ResDecl->
addAttr(BindingAttr);
6100 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6109 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6116static void handleArrayOfStructWithResources(
6118 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6123static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6125 EmbeddedResourceNameBuilder &NameBuilder,
6126 StructBindingContext &BindingCtx) {
6129 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6136 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6150 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6153 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6155 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6157 "resource arrays should have been already handled");
6158 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6167handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6169 EmbeddedResourceNameBuilder &NameBuilder,
6170 StructBindingContext &BindingCtx) {
6178 if (!SubCAT && !ElementRD)
6181 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6184 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6187 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6200void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6201 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6202 StructBindingContext BindingCtx(VD);
6206 "Expected non-resource struct or array type");
6209 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6213 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6214 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6222 if (
SemaRef.RequireCompleteType(
6225 diag::err_typecheck_decl_incomplete_type)) {
6239 DefaultCBufferDecls.push_back(VD);
6244 collectResourceBindingsOnVarDecl(VD);
6246 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6258 processExplicitBindingsOnDecl(VD);
6296 handleGlobalStructOrArrayOfWithResources(VD);
6300 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6309 "expected resource record type");
6325 const char *CreateMethodName;
6327 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6328 :
"__createFromBinding";
6330 CreateMethodName = HasCounter
6331 ?
"__createFromImplicitBindingWithImplicitCounter"
6332 :
"__createFromImplicitBinding";
6337 if (!CreateMethod) {
6342 "create method lookup should always succeed for built-in resource "
6351 Args.push_back(RegSlot);
6359 Args.push_back(OrderId);
6365 Args.push_back(Space);
6369 Args.push_back(RangeSize);
6373 Args.push_back(Index);
6375 StringRef VarName = VD->
getName();
6383 Args.push_back(NameCast);
6391 Args.push_back(CounterId);
6414 SemaRef.CheckCompleteVariableDeclaration(VD);
6420 "expected array of resource records");
6441 lookupMethod(
SemaRef, ResourceDecl,
6442 HasCounter ?
"__createFromBindingWithImplicitCounter"
6443 :
"__createFromBinding",
6447 CreateMethod = lookupMethod(
6449 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6450 :
"__createFromImplicitBinding",
6493std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6494 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6495 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6496 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6497 if (!TrueInfo || !FalseInfo)
6498 return std::nullopt;
6499 if (*TrueInfo != *FalseInfo)
6500 return std::nullopt;
6504 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6513 if (
const auto *AttrResType =
6514 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6516 return Bindings.getDeclBindingInfo(VD, RC);
6523void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6524 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6527 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6532 if (*ExprBinding ==
nullptr)
6535 auto PrevBinding = Assigns.find(VD);
6536 if (PrevBinding == Assigns.end()) {
6538 Assigns.insert({VD, *ExprBinding});
6543 if (*ExprBinding != PrevBinding->second) {
6545 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6547 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6558 "expected LHS to be a resource record or array of resource records");
6559 if (Opc != BO_Assign)
6564 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6572 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6577 trackLocalResource(VD, RHSExpr);
6594void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6596 "expected global variable that contains HLSL resource");
6599 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6600 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6601 ? ResourceClass::CBuffer
6602 : ResourceClass::SRV);
6615 if (
const HLSLAttributedResourceType *AttrResType =
6616 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6617 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6622 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6623 collectResourceBindingsOnUserRecordDecl(VD, RT);
6629void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6632 bool HasBinding =
false;
6633 for (Attr *A : VD->
attrs()) {
6636 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6637 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6640 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6641 if (!RBA || !RBA->hasRegisterSlot())
6646 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6647 "never have an attribute created");
6649 if (RT == RegisterType::C) {
6650 if (Bindings.hasBindingInfoForDecl(VD))
6652 diag::warn_hlsl_user_defined_type_missing_member)
6653 <<
static_cast<int>(RT);
6661 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6666 diag::warn_hlsl_user_defined_type_missing_member)
6667 <<
static_cast<int>(RT);
6675class InitListTransformer {
6679 QualType *DstIt =
nullptr;
6680 Expr **ArgIt =
nullptr;
6686 bool castInitializer(Expr *E) {
6687 assert(DstIt &&
"This should always be something!");
6688 if (DstIt == DestTypes.end()) {
6690 ArgExprs.push_back(E);
6695 DstIt = DestTypes.begin();
6698 Ctx, *DstIt,
false);
6703 ArgExprs.push_back(
Init);
6708 bool buildInitializerListImpl(Expr *E) {
6710 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6711 for (
auto *SubInit :
Init->inits())
6712 if (!buildInitializerListImpl(SubInit))
6722 return castInitializer(E);
6736 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6741 for (uint64_t I = 0; I <
Size; ++I) {
6743 SizeTy, SourceLocation());
6749 if (!castInitializer(ElExpr.
get()))
6754 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6755 unsigned Rows = MTy->getNumRows();
6756 unsigned Cols = MTy->getNumColumns();
6757 QualType ElemTy = MTy->getElementType();
6759 for (
unsigned R = 0;
R < Rows; ++
R) {
6760 for (
unsigned C = 0;
C < Cols; ++
C) {
6773 if (!castInitializer(ElExpr.
get()))
6781 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6785 for (uint64_t I = 0; I <
Size; ++I) {
6787 SizeTy, SourceLocation());
6792 if (!buildInitializerListImpl(ElExpr.
get()))
6799 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6800 RecordDecls.push_back(RD);
6801 while (RecordDecls.back()->getNumBases()) {
6802 CXXRecordDecl *D = RecordDecls.back();
6804 "HLSL doesn't support multiple inheritance");
6805 RecordDecls.push_back(
6808 while (!RecordDecls.empty()) {
6809 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6810 for (
auto *FD : RD->
fields()) {
6811 if (FD->isUnnamedBitField())
6819 if (!buildInitializerListImpl(Res.
get()))
6827 Expr *generateInitListsImpl(QualType Ty) {
6829 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6834 llvm::SmallVector<Expr *>
Inits;
6839 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6840 ElTy = ATy->getElementType();
6841 Size = ATy->getNumElements();
6842 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6843 ElTy = CMTy->getElementType();
6844 Size = CMTy->getNumElementsFlattened();
6847 ElTy = VTy->getElementType();
6848 Size = VTy->getZExtSize();
6850 for (uint64_t I = 0; I <
Size; ++I)
6851 Inits.push_back(generateInitListsImpl(ElTy));
6854 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6855 RecordDecls.push_back(RD);
6856 while (RecordDecls.back()->getNumBases()) {
6857 CXXRecordDecl *D = RecordDecls.back();
6859 "HLSL doesn't support multiple inheritance");
6860 RecordDecls.push_back(
6863 while (!RecordDecls.empty()) {
6864 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6865 for (
auto *FD : RD->
fields())
6866 if (!FD->isUnnamedBitField())
6871 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6872 Inits.back()->getEndLoc(),
false);
6873 NewInit->setType(Ty);
6878 llvm::SmallVector<QualType, 16> DestTypes;
6879 llvm::SmallVector<Expr *, 16> ArgExprs;
6880 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6881 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6882 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6883 InitTy = Entity.
getType().getNonReferenceType();
6893 DstIt = DestTypes.begin();
6896 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6898 Expr *generateInitLists() {
6899 assert(!ArgExprs.empty() &&
6900 "Call buildInitializerList to generate argument expressions.");
6901 ArgIt = ArgExprs.begin();
6903 return generateInitListsImpl(InitTy);
6904 llvm::SmallVector<Expr *>
Inits;
6905 while (ArgIt != ArgExprs.end())
6906 Inits.push_back(generateInitListsImpl(InitTy));
6909 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6910 Inits.back()->getEndLoc(),
false);
6911 llvm::APInt ArySize(64,
Inits.size());
6913 ArraySizeModifier::Normal, 0));
6925 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6932 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6936 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6956 if (
Init->getType()->isScalarType())
6959 InitListTransformer ILT(
SemaRef, Entity);
6961 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
6969 Init->setInit(I, E);
6971 if (!ILT.buildInitializerList(E))
6974 size_t ExpectedSize = ILT.DestTypes.size();
6975 size_t ActualSize = ILT.ArgExprs.size();
6976 if (ExpectedSize == 0 && ActualSize == 0)
6983 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
6985 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
6986 << (int)(ExpectedSize < ActualSize) << InitTy
6987 << ExpectedSize << ActualSize;
6997 assert(ExpectedSize > 0 &&
6998 "The expected size of an incomplete array type must be at least 1.");
7000 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
7008 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7009 if (ExpectedSize != ActualSize) {
7010 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
7011 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7012 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
7019 Init->resizeInits(Ctx, NewInit->getNumInits());
7020 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
7021 Init->updateInit(Ctx, I, NewInit->getInit(I));
7029 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7039 StringRef AccessorName = CompName->
getName();
7040 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7042 unsigned Rows = MT->getNumRows();
7043 unsigned Cols = MT->getNumColumns();
7044 bool IsZeroBasedAccessor =
false;
7045 unsigned ChunkLen = 0;
7046 if (AccessorName.size() < 2)
7048 "length 4 for zero based: \'_mRC\' or "
7049 "length 3 for one-based: \'_RC\' accessor",
7052 if (AccessorName[0] ==
'_') {
7053 if (AccessorName[1] ==
'm') {
7054 IsZeroBasedAccessor =
true;
7061 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7064 if (AccessorName.size() % ChunkLen != 0) {
7065 const llvm::StringRef
Expected = IsZeroBasedAccessor
7066 ?
"zero based: '_mRC' accessor"
7067 :
"one-based: '_RC' accessor";
7072 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7073 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7074 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7076 bool HasRepeated =
false;
7078 unsigned NumComponents = 0;
7079 const char *Begin = AccessorName.data();
7081 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7082 const char *Chunk = Begin + I;
7083 char RowChar = 0, ColChar = 0;
7084 if (IsZeroBasedAccessor) {
7086 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7087 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7089 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7096 if (Chunk[0] !=
'_')
7098 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7105 bool IsDigitsError =
false;
7107 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7111 IsDigitsError =
true;
7115 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7119 IsDigitsError =
true;
7124 unsigned Row = RowChar -
'0';
7125 unsigned Col = ColChar -
'0';
7127 bool HasIndexingError =
false;
7128 if (IsZeroBasedAccessor) {
7130 if (!isZeroBasedIndex(Row)) {
7131 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7133 HasIndexingError =
true;
7135 if (!isZeroBasedIndex(Col)) {
7136 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7138 HasIndexingError =
true;
7142 if (!isOneBasedIndex(Row)) {
7143 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7145 HasIndexingError =
true;
7147 if (!isOneBasedIndex(Col)) {
7148 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7150 HasIndexingError =
true;
7157 if (HasIndexingError)
7163 bool HasBoundsError =
false;
7165 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7167 HasBoundsError =
true;
7170 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7172 HasBoundsError =
true;
7177 unsigned FlatIndex = Row * Cols + Col;
7178 if (Seen[FlatIndex])
7180 Seen[FlatIndex] =
true;
7183 if (NumComponents == 0 || NumComponents > 4) {
7184 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7189 QualType ElemTy = MT->getElementType();
7190 if (NumComponents == 1)
7196 for (Sema::ExtVectorDeclsType::iterator
7200 if ((*I)->getUnderlyingType() == VT)
7211 trackLocalResource(VDecl,
Init);
7213 const HLSLVkConstantIdAttr *ConstIdAttr =
7214 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7221 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7231 int ConstantID = ConstIdAttr->getId();
7232 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7234 ConstIdAttr->getLocation());
7238 if (
C->getType()->getCanonicalTypeUnqualified() !=
7242 Context.getTrivialTypeSourceInfo(
7243 Init->getType(),
Init->getExprLoc()),
7262 if (!Params || Params->
size() != 1)
7275 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7276 if (TTP->hasDefaultArgument()) {
7277 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7280 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7281 if (NTTP->hasDefaultArgument()) {
7282 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7285 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7286 if (TTPD->hasDefaultArgument()) {
7287 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7294 return SemaRef.CheckTemplateIdType(
7296 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.
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