15#include "clang/AST/Attrs.inc"
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"
65 case ResourceClass::SRV:
66 return RegisterType::SRV;
67 case ResourceClass::UAV:
68 return RegisterType::UAV;
69 case ResourceClass::CBuffer:
70 return RegisterType::CBuffer;
71 case ResourceClass::Sampler:
72 return RegisterType::Sampler;
74 llvm_unreachable(
"unexpected ResourceClass value");
84 assert(RT !=
nullptr);
88 *RT = RegisterType::SRV;
92 *RT = RegisterType::UAV;
96 *RT = RegisterType::CBuffer;
100 *RT = RegisterType::Sampler;
104 *RT = RegisterType::C;
108 *RT = RegisterType::I;
117 case RegisterType::SRV:
118 return ResourceClass::SRV;
119 case RegisterType::UAV:
120 return ResourceClass::UAV;
121 case RegisterType::CBuffer:
122 return ResourceClass::CBuffer;
123 case RegisterType::Sampler:
124 return ResourceClass::Sampler;
125 case RegisterType::C:
126 case RegisterType::I:
130 llvm_unreachable(
"unexpected RegisterType value");
134 const auto *BT = dyn_cast<BuiltinType>(
Type);
138 return Builtin::BI__builtin_get_spirv_spec_constant_int;
141 switch (BT->getKind()) {
142 case BuiltinType::Bool:
143 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
144 case BuiltinType::Short:
145 return Builtin::BI__builtin_get_spirv_spec_constant_short;
146 case BuiltinType::Int:
147 return Builtin::BI__builtin_get_spirv_spec_constant_int;
148 case BuiltinType::LongLong:
149 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
150 case BuiltinType::UShort:
151 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
152 case BuiltinType::UInt:
153 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
154 case BuiltinType::ULongLong:
155 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
156 case BuiltinType::Half:
157 return Builtin::BI__builtin_get_spirv_spec_constant_half;
158 case BuiltinType::Float:
159 return Builtin::BI__builtin_get_spirv_spec_constant_float;
160 case BuiltinType::Double:
161 return Builtin::BI__builtin_get_spirv_spec_constant_double;
168 ResourceClass ResClass) {
170 "DeclBindingInfo already added");
176 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
177 return &BindingsList.emplace_back(VD, ResClass);
181 ResourceClass ResClass) {
182 auto Entry = DeclToBindingListIndex.find(VD);
183 if (Entry != DeclToBindingListIndex.end()) {
184 for (
unsigned Index = Entry->getSecond();
185 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
187 if (BindingsList[Index].ResClass == ResClass)
188 return &BindingsList[Index];
195 return DeclToBindingListIndex.contains(VD);
207 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
210 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
211 : llvm::hlsl::ResourceClass::SRV;
223 if (
T->isArrayType() ||
T->isStructureType())
230 assert(Context.getTypeSize(
T) <= 64 &&
231 "Scalar bit widths larger than 64 not supported");
234 return Context.getTypeSize(
T) / 8;
241 constexpr unsigned CBufferAlign = 16;
242 if (
const auto *RD =
T->getAsRecordDecl()) {
244 for (
const FieldDecl *Field : RD->fields()) {
251 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
252 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
253 FieldAlign = CBufferAlign;
256 Size = llvm::alignTo(Size, FieldAlign);
263 unsigned ElementCount = AT->getSize().getZExtValue();
264 if (ElementCount == 0)
267 unsigned ElementSize =
269 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
270 return AlignedElementSize * (ElementCount - 1) + ElementSize;
274 unsigned ElementCount = VT->getNumElements();
275 unsigned ElementSize =
277 return ElementSize * ElementCount;
280 return Context.getTypeSize(
T) / 8;
291 bool HasPackOffset =
false;
292 bool HasNonPackOffset =
false;
294 VarDecl *Var = dyn_cast<VarDecl>(Field);
297 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
298 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
299 HasPackOffset =
true;
301 HasNonPackOffset =
true;
308 if (HasNonPackOffset)
315 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
316 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
317 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
318 return LHS.second->getOffsetInBytes() <
319 RHS.second->getOffsetInBytes();
321 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
322 VarDecl *Var = PackOffsetVec[i].first;
323 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
325 unsigned Begin =
Attr->getOffsetInBytes();
326 unsigned End = Begin + Size;
327 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
328 if (End > NextBegin) {
329 VarDecl *NextVar = PackOffsetVec[i + 1].first;
341 CAT = dyn_cast<ConstantArrayType>(
343 return CAT !=
nullptr;
351static const HLSLAttributedResourceType *
354 "expected array of resource records");
356 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
358 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
370 return RD->isEmpty();
399 Base.getType()->castAsCXXRecordDecl()))
410 assert(RD ==
nullptr &&
411 "there should be at most 1 record by a given name in a scope");
428 Name.append(NameBaseII->
getName());
435 size_t NameLength = Name.size();
444 Name.append(llvm::Twine(suffix).str());
445 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
452 Name.truncate(NameLength);
493 "struct is already HLSL buffer compatible");
507 LS->
addAttr(PackedAttr::CreateImplicit(AST));
511 if (
unsigned NumBases = StructDecl->
getNumBases()) {
512 assert(NumBases == 1 &&
"HLSL supports only one base type");
562 LS->
addAttr(PackedAttr::CreateImplicit(AST));
567 VarDecl *VD = dyn_cast<VarDecl>(D);
587 uint32_t ImplicitBindingOrderID) {
589 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
590 Attr->setBinding(RT, std::nullopt, 0);
591 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
598 BufDecl->setRBraceLoc(RBrace);
610 uint32_t OrderID = getNextImplicitBindingOrderID();
615 BufDecl->isCBuffer() ? RegisterType::CBuffer
625 int X,
int Y,
int Z) {
626 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
627 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
628 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
629 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
639 int Min,
int Max,
int Preferred,
640 int SpelledArgsCount) {
641 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
642 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
643 WS->getPreferred() != Preferred ||
644 WS->getSpelledArgsCount() != SpelledArgsCount) {
645 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
646 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
652 Result->setSpelledArgsCount(SpelledArgsCount);
656HLSLVkConstantIdAttr *
662 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
670 Diag(VD->getLocation(), diag::err_specialization_const);
674 if (!VD->getType().isConstQualified()) {
675 Diag(VD->getLocation(), diag::err_specialization_const);
679 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
680 if (CI->getId() != Id) {
681 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
682 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
687 HLSLVkConstantIdAttr *
Result =
694 llvm::Triple::EnvironmentType ShaderType) {
695 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
696 if (NT->getType() != ShaderType) {
697 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
698 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
702 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
705HLSLParamModifierAttr *
707 HLSLParamModifierAttr::Spelling Spelling) {
710 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
711 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
712 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
713 D->
dropAttr<HLSLParamModifierAttr>();
715 return HLSLParamModifierAttr::Create(
717 HLSLParamModifierAttr::Keyword_inout);
719 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
720 Diag(PA->getLocation(), diag::note_conflicting_attribute);
746 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
747 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
750 if (Shader->getType() != Env) {
751 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
763 case llvm::Triple::UnknownEnvironment:
764 case llvm::Triple::Library:
766 case llvm::Triple::RootSignature:
767 llvm_unreachable(
"rootsig environment has no functions");
769 llvm_unreachable(
"Unhandled environment in triple");
778 if (SemanticName ==
"SV_DISPATCHTHREADID") {
780 *Info.Semantic, TargetDecl, Info.Index);
781 }
else if (SemanticName ==
"SV_GROUPINDEX") {
784 }
else if (SemanticName ==
"SV_GROUPTHREADID") {
786 TargetDecl, Info.Index);
787 }
else if (SemanticName ==
"SV_GROUPID") {
790 }
else if (SemanticName ==
"SV_POSITION") {
794 Diag(Info.Semantic->getLoc(), diag::err_hlsl_unknown_semantic)
800bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
802 SemanticInfo &ActiveSemantic) {
803 if (ActiveSemantic.Semantic ==
nullptr) {
804 ActiveSemantic.Semantic = D->
getAttr<HLSLSemanticAttr>();
805 if (ActiveSemantic.Semantic &&
806 ActiveSemantic.Semantic->isSemanticIndexExplicit())
807 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
810 if (!ActiveSemantic.Semantic) {
815 auto *A = createSemantic(ActiveSemantic, D);
819 checkSemanticAnnotation(FD, D, A);
825 SemanticInfo &ActiveSemantic) {
826 if (ActiveSemantic.Semantic ==
nullptr) {
827 ActiveSemantic.Semantic = D->
getAttr<HLSLSemanticAttr>();
828 if (ActiveSemantic.Semantic &&
829 ActiveSemantic.Semantic->isSemanticIndexExplicit())
830 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
834 const RecordType *RT = dyn_cast<RecordType>(
T);
836 return determineActiveSemanticOnScalar(FD, D, ActiveSemantic);
838 const RecordDecl *RD = RT->getDecl();
839 for (FieldDecl *Field : RD->
fields()) {
840 SemanticInfo Info = ActiveSemantic;
841 if (!determineActiveSemantic(FD, Field, Info)) {
842 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
845 if (ActiveSemantic.Semantic)
846 ActiveSemantic = Info;
853 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
854 assert(ShaderAttr &&
"Entry point has no shader attribute");
855 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
859 case llvm::Triple::Pixel:
860 case llvm::Triple::Vertex:
861 case llvm::Triple::Geometry:
862 case llvm::Triple::Hull:
863 case llvm::Triple::Domain:
864 case llvm::Triple::RayGeneration:
865 case llvm::Triple::Intersection:
866 case llvm::Triple::AnyHit:
867 case llvm::Triple::ClosestHit:
868 case llvm::Triple::Miss:
869 case llvm::Triple::Callable:
870 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
872 {llvm::Triple::Compute,
873 llvm::Triple::Amplification,
874 llvm::Triple::Mesh});
877 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
879 {llvm::Triple::Compute,
880 llvm::Triple::Amplification,
881 llvm::Triple::Mesh});
886 case llvm::Triple::Compute:
887 case llvm::Triple::Amplification:
888 case llvm::Triple::Mesh:
889 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
891 << llvm::Triple::getEnvironmentTypeName(ST);
894 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
895 if (Ver < VersionTuple(6, 6)) {
896 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
899 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
902 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
903 << WS << WS->getSpelledArgsCount() <<
"6.8";
908 case llvm::Triple::RootSignature:
909 llvm_unreachable(
"rootsig environment has no function entry point");
911 llvm_unreachable(
"Unhandled environment in triple");
915 SemanticInfo ActiveSemantic;
916 ActiveSemantic.Semantic =
nullptr;
917 ActiveSemantic.Index = std::nullopt;
919 if (!determineActiveSemantic(FD, Param, ActiveSemantic)) {
920 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
927void SemaHLSL::checkSemanticAnnotation(
FunctionDecl *EntryPoint,
930 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
931 assert(ShaderAttr &&
"Entry point has no shader attribute");
932 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
934 switch (SemanticAttr->
getKind()) {
935 case attr::HLSLSV_DispatchThreadID:
936 case attr::HLSLSV_GroupIndex:
937 case attr::HLSLSV_GroupThreadID:
938 case attr::HLSLSV_GroupID:
939 if (ST == llvm::Triple::Compute)
943 case attr::HLSLSV_Position:
946 if (ST == llvm::Triple::Pixel)
951 llvm_unreachable(
"Unknown SemanticAttr");
956 const Attr *A, llvm::Triple::EnvironmentType Stage,
957 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
959 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
960 [](llvm::Triple::EnvironmentType ST) {
962 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
964 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
965 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
966 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
969template <CastKind Kind>
972 Ty = VTy->getElementType();
977template <CastKind Kind>
989 if (LHSFloat && RHSFloat) {
1017 if (LHSSigned == RHSSigned) {
1018 if (IsCompAssign || IntOrder >= 0)
1026 if (IntOrder != (LHSSigned ? 1 : -1)) {
1027 if (IsCompAssign || RHSSigned)
1035 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1036 if (IsCompAssign || LHSSigned)
1052 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1053 QualType NewTy = Ctx.getExtVectorType(
1063 return CK_FloatingCast;
1065 return CK_IntegralCast;
1067 return CK_IntegralToFloating;
1069 return CK_FloatingToIntegral;
1075 bool IsCompAssign) {
1082 if (!LVecTy && IsCompAssign) {
1084 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1086 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1088 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1093 unsigned EndSz = std::numeric_limits<unsigned>::max();
1096 LSz = EndSz = LVecTy->getNumElements();
1099 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1100 "one of the above should have had a value");
1104 if (IsCompAssign && LSz != EndSz) {
1106 diag::err_hlsl_vector_compound_assignment_truncation)
1107 << LHSType << RHSType;
1113 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1118 if (!IsCompAssign && !LVecTy)
1122 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1123 return Ctx.getCommonSugaredType(LHSType, RHSType);
1131 LElTy, RElTy, IsCompAssign);
1134 "HLSL Vectors can only contain integer or floating point types");
1136 LElTy, RElTy, IsCompAssign);
1141 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1142 "Called with non-logical operator");
1144 llvm::raw_svector_ostream OS(Buff);
1146 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1147 OS << NewFnName <<
"(";
1157std::pair<IdentifierInfo *, bool>
1160 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1167 return {DeclIdent,
Found};
1178 for (
auto &RootSigElement : RootElements)
1179 Elements.push_back(RootSigElement.getElement());
1183 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1185 SignatureDecl->setImplicit();
1191 if (RootSigOverrideIdent) {
1194 if (
SemaRef.LookupQualifiedName(R, DC))
1195 return dyn_cast<HLSLRootSignatureDecl>(R.
getFoundDecl());
1203struct PerVisibilityBindingChecker {
1206 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1210 llvm::dxbc::ShaderVisibility Vis;
1215 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1217 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1218 llvm::dxil::ResourceClass RC, uint32_t Space,
1219 uint32_t LowerBound, uint32_t UpperBound,
1220 const hlsl::RootSignatureElement *Elem) {
1222 assert(BuilderIndex < Builders.size() &&
1223 "Not enough builders for visibility type");
1224 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1225 static_cast<const void *
>(Elem));
1227 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1228 "'All' visibility must come first");
1229 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1230 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1231 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1232 static_cast<const void *
>(Elem));
1234 ElemInfoMap.push_back({Elem,
Visibility,
false});
1237 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1238 auto It = llvm::lower_bound(
1240 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1241 assert(It->Elem == Elem &&
"Element not in map");
1245 bool checkOverlap() {
1246 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1247 return LHS.Elem < RHS.Elem;
1250 bool HadOverlap =
false;
1252 using llvm::hlsl::BindingInfoBuilder;
1253 auto ReportOverlap = [
this,
1254 &HadOverlap](
const BindingInfoBuilder &Builder,
1255 const llvm::hlsl::Binding &Reported) {
1259 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1260 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1261 const auto *PrevElem =
1262 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1264 ElemInfo &Info =
getInfo(Elem);
1269 Info.Diagnosed =
true;
1271 ElemInfo &PrevInfo =
getInfo(PrevElem);
1272 llvm::dxbc::ShaderVisibility CommonVis =
1273 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1276 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1277 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1278 << Reported.isUnbounded() << Reported.UpperBound
1283 this->S->
Diag(PrevElem->getLocation(),
1284 diag::note_hlsl_resource_range_here);
1287 for (BindingInfoBuilder &Builder : Builders)
1288 Builder.calculateBindingInfo(ReportOverlap);
1312 if (
const auto *ResTy =
1313 SecondField->
getType()->
getAs<HLSLAttributedResourceType>()) {
1314 return ResTy->getAttrs().IsCounter;
1322 bool HadError =
false;
1323 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1324 uint32_t UpperBound) {
1326 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1327 << LowerBound << UpperBound;
1334 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1335 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1336 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1339 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1340 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1341 ReportError(Loc, 0, 0xfffffffe);
1344 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1345 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1346 ReportError(Loc, 0, 0xffffffef);
1349 const uint32_t Version =
1350 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1351 const uint32_t VersionEnum = Version - 1;
1352 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1354 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1361 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1362 if (
const auto *Descriptor =
1363 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1364 VerifyRegister(Loc, Descriptor->Reg.Number);
1365 VerifySpace(Loc, Descriptor->Space);
1367 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1369 ReportFlagError(Loc);
1370 }
else if (
const auto *Constants =
1371 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1372 VerifyRegister(Loc, Constants->Reg.Number);
1373 VerifySpace(Loc, Constants->Space);
1374 }
else if (
const auto *Sampler =
1375 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1376 VerifyRegister(Loc, Sampler->Reg.Number);
1377 VerifySpace(Loc, Sampler->Space);
1380 "By construction, parseFloatParam can't produce a NaN from a "
1381 "float_literal token");
1383 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1384 ReportError(Loc, 0, 16);
1385 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1386 ReportFloatError(Loc, -16.f, 15.99f);
1387 }
else if (
const auto *Clause =
1388 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1390 VerifyRegister(Loc, Clause->Reg.Number);
1391 VerifySpace(Loc, Clause->Space);
1393 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1397 ReportError(Loc, 1, 0xfffffffe);
1400 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1402 ReportFlagError(Loc);
1406 PerVisibilityBindingChecker BindingChecker(
this);
1407 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1412 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1413 if (
const auto *Descriptor =
1414 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1415 uint32_t LowerBound(Descriptor->Reg.Number);
1416 uint32_t UpperBound(LowerBound);
1418 BindingChecker.trackBinding(
1419 Descriptor->Visibility,
1420 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1421 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1422 }
else if (
const auto *Constants =
1423 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1424 uint32_t LowerBound(Constants->Reg.Number);
1425 uint32_t UpperBound(LowerBound);
1427 BindingChecker.trackBinding(
1428 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1429 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1430 }
else if (
const auto *Sampler =
1431 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1432 uint32_t LowerBound(Sampler->Reg.Number);
1433 uint32_t UpperBound(LowerBound);
1435 BindingChecker.trackBinding(
1436 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1437 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1438 }
else if (
const auto *Clause =
1439 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1442 UnboundClauses.emplace_back(Clause, &RootSigElem);
1443 }
else if (
const auto *Table =
1444 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1445 assert(UnboundClauses.size() == Table->NumClauses &&
1446 "Number of unbound elements must match the number of clauses");
1447 bool HasAnySampler =
false;
1448 bool HasAnyNonSampler =
false;
1449 uint64_t Offset = 0;
1450 bool IsPrevUnbound =
false;
1451 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1453 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1454 HasAnySampler =
true;
1456 HasAnyNonSampler =
true;
1458 if (HasAnySampler && HasAnyNonSampler)
1459 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1464 if (Clause->NumDescriptors == 0)
1468 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1470 Offset = Clause->Offset;
1472 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1473 Offset, Clause->NumDescriptors);
1475 if (IsPrevUnbound && IsAppending)
1476 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1477 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1478 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1481 Offset = RangeBound + 1;
1482 IsPrevUnbound = Clause->NumDescriptors ==
1483 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1486 uint32_t LowerBound(Clause->Reg.Number);
1487 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1488 LowerBound, Clause->NumDescriptors);
1490 BindingChecker.trackBinding(
1492 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1493 LowerBound, UpperBound, ClauseElem);
1495 UnboundClauses.clear();
1499 return BindingChecker.checkOverlap();
1504 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1509 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1510 if (RS->getSignatureIdent() != Ident) {
1511 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1515 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1521 if (
auto *SignatureDecl =
1529 llvm::VersionTuple SMVersion =
1534 uint32_t ZMax = 1024;
1535 uint32_t ThreadMax = 1024;
1536 if (IsDXIL && SMVersion.getMajor() <= 4) {
1539 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1549 diag::err_hlsl_numthreads_argument_oor)
1558 diag::err_hlsl_numthreads_argument_oor)
1567 diag::err_hlsl_numthreads_argument_oor)
1572 if (
X * Y * Z > ThreadMax) {
1573 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1590 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1598 if (SpelledArgsCount > 1 &&
1602 uint32_t Preferred = 0;
1603 if (SpelledArgsCount > 2 &&
1607 if (SpelledArgsCount > 2) {
1610 diag::err_attribute_power_of_two_in_range)
1611 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1616 if (Preferred < Min || Preferred >
Max) {
1618 diag::err_attribute_power_of_two_in_range)
1619 << AL <<
Min <<
Max << Preferred;
1622 }
else if (SpelledArgsCount > 1) {
1625 diag::err_attribute_power_of_two_in_range)
1626 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1630 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1633 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1638 diag::err_attribute_power_of_two_in_range)
1639 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1644 HLSLWaveSizeAttr *NewAttr =
1668 uint32_t Binding = 0;
1683 if (!
T->hasUnsignedIntegerRepresentation() ||
1684 (VT && VT->getNumElements() > 3)) {
1685 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1686 << AL <<
"uint/uint2/uint3";
1695 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1696 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1697 << AL <<
"float/float1/float2/float3/float4";
1705 std::optional<unsigned> Index) {
1709 QualType ValueType = VD->getType();
1710 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1713 bool IsOutput =
false;
1714 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1721 Attr *Attribute =
nullptr;
1722 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1725 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1728 }
else if (SemanticName ==
"SV_GROUPINDEX") {
1730 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1732 }
else if (SemanticName ==
"SV_GROUPTHREADID") {
1735 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1738 }
else if (SemanticName ==
"SV_GROUPID") {
1741 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1743 }
else if (SemanticName ==
"SV_POSITION") {
1744 const auto *VT = ValueType->getAs<
VectorType>();
1745 if (!ValueType->hasFloatingRepresentation() ||
1746 (VT && VT->getNumElements() > 4))
1747 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1748 << AL <<
"float/float1/float2/float3/float4";
1751 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1759 uint32_t IndexValue, ExplicitIndex;
1762 assert(IndexValue > 0 ? ExplicitIndex :
true);
1763 std::optional<unsigned> Index =
1764 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1769 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1774 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1775 << AL <<
"shader constant in a constant buffer";
1779 uint32_t SubComponent;
1789 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1794 if (IsAggregateTy || Size > 128) {
1795 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1799 if ((Component * 32 + Size) > 128) {
1800 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1805 EltTy = VT->getElementType();
1807 if (Align > 32 && Component == 1) {
1810 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1824 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1827 llvm::Triple::EnvironmentType ShaderType;
1828 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1829 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1830 << AL << Str << ArgLoc;
1844 assert(AttrList.size() &&
"expected list of resource attributes");
1851 HLSLAttributedResourceType::Attributes ResAttrs;
1853 bool HasResourceClass =
false;
1854 for (
const Attr *A : AttrList) {
1857 LocEnd = A->getRange().getEnd();
1858 switch (A->getKind()) {
1859 case attr::HLSLResourceClass: {
1861 if (HasResourceClass) {
1862 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1863 ? diag::warn_duplicate_attribute_exact
1864 : diag::warn_duplicate_attribute)
1868 ResAttrs.ResourceClass = RC;
1869 HasResourceClass =
true;
1873 if (ResAttrs.IsROV) {
1874 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1877 ResAttrs.IsROV =
true;
1879 case attr::HLSLRawBuffer:
1880 if (ResAttrs.RawBuffer) {
1881 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1884 ResAttrs.RawBuffer =
true;
1886 case attr::HLSLIsCounter:
1887 if (ResAttrs.IsCounter) {
1888 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1891 ResAttrs.IsCounter =
true;
1893 case attr::HLSLContainedType: {
1896 if (!ContainedTy.
isNull()) {
1897 S.
Diag(A->getLocation(), ContainedTy == Ty
1898 ? diag::warn_duplicate_attribute_exact
1899 : diag::warn_duplicate_attribute)
1908 llvm_unreachable(
"unhandled resource attribute type");
1912 if (!HasResourceClass) {
1913 S.
Diag(AttrList.back()->getRange().getEnd(),
1914 diag::err_hlsl_missing_resource_class);
1919 Wrapped, ContainedTy, ResAttrs);
1921 if (LocInfo && ContainedTyInfo) {
1934 if (!
T->isHLSLResourceType()) {
1935 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1950 AttributeCommonInfo::AS_CXX11, 0, false ,
1955 case ParsedAttr::AT_HLSLResourceClass: {
1957 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1968 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1969 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1970 <<
"ResourceClass" << Identifier;
1973 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
1977 case ParsedAttr::AT_HLSLROV:
1981 case ParsedAttr::AT_HLSLRawBuffer:
1985 case ParsedAttr::AT_HLSLIsCounter:
1989 case ParsedAttr::AT_HLSLContainedType: {
1991 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1997 assert(TSI &&
"no type source info for attribute argument");
1999 diag::err_incomplete_type))
2001 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2006 llvm_unreachable(
"unhandled HLSL attribute");
2009 HLSLResourcesTypeAttrs.emplace_back(A);
2015 if (!HLSLResourcesTypeAttrs.size())
2021 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2022 const HLSLAttributedResourceType *RT =
2029 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2031 HLSLResourcesTypeAttrs.clear();
2039 auto I = LocsForHLSLAttributedResources.find(RT);
2040 if (I != LocsForHLSLAttributedResources.end()) {
2041 LocInfo = I->second;
2042 LocsForHLSLAttributedResources.erase(I);
2051void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2052 const RecordType *RT) {
2053 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
2060 "incomplete arrays inside user defined types are not supported");
2069 if (
const HLSLAttributedResourceType *AttrResType =
2070 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2075 Bindings.addDeclBindingInfo(VD, RC);
2076 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2082 collectResourceBindingsOnUserRecordDecl(VD, RT);
2094 bool SpecifiedSpace) {
2095 int RegTypeNum =
static_cast<int>(RegType);
2098 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2099 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2104 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2105 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2106 : ResourceClass::SRV;
2116 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2120 if (
const HLSLAttributedResourceType *AttrResType =
2121 HLSLAttributedResourceType::findHandleTypeOnResource(
2138 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2139 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2144 if (RegType == RegisterType::CBuffer)
2145 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2146 else if (RegType != RegisterType::C)
2147 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2151 if (RegType == RegisterType::C)
2152 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2154 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2164 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2172 bool RegisterTypesDetected[5] = {
false};
2173 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2176 if (HLSLResourceBindingAttr *
attr =
2177 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2180 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2181 int otherRegTypeNum =
static_cast<int>(otherRegType);
2183 diag::err_hlsl_duplicate_register_annotation)
2187 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2195 bool SpecifiedSpace) {
2200 "expecting VarDecl or HLSLBufferDecl");
2211 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2213 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2214 Ty = IAT->getElementType();
2216 diag::err_incomplete_type))
2220 StringRef Slot =
"";
2221 StringRef Space =
"";
2225 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2235 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2241 SpaceLoc = Loc->
getLoc();
2244 if (Str.starts_with(
"space")) {
2246 SpaceLoc = Loc->
getLoc();
2255 std::optional<unsigned> SlotNum;
2256 unsigned SpaceNum = 0;
2259 if (!Slot.empty()) {
2261 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2264 if (RegType == RegisterType::I) {
2265 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2268 StringRef SlotNumStr = Slot.substr(1);
2270 if (SlotNumStr.getAsInteger(10, N)) {
2271 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2278 if (!Space.starts_with(
"space")) {
2279 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2282 StringRef SpaceNumStr = Space.substr(5);
2283 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2284 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2289 if (SlotNum.has_value())
2294 HLSLResourceBindingAttr *NewAttr =
2295 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2297 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2352 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2356 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2357 unsigned CurrentShaderStageBit;
2362 bool ReportOnlyShaderStageIssues;
2365 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2366 static_assert(
sizeof(
unsigned) >= 4);
2367 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2368 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2369 "ShaderType is too big for this bitmap");
2372 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2373 CurrentShaderEnvironment = ShaderType;
2374 CurrentShaderStageBit = (1 << bitmapIndex);
2377 void SetUnknownShaderStageContext() {
2378 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2379 CurrentShaderStageBit = (1 << 31);
2382 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2383 return CurrentShaderEnvironment;
2386 bool InUnknownShaderStageContext()
const {
2387 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2391 void AddToScannedFunctions(
const FunctionDecl *FD) {
2392 unsigned &ScannedStages = ScannedDecls[FD];
2393 ScannedStages |= CurrentShaderStageBit;
2396 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2398 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2399 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2402 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2403 return ScannerStages & CurrentShaderStageBit;
2406 static bool NeverBeenScanned(
unsigned ScannedStages) {
2407 return ScannedStages == 0;
2411 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2412 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2414 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2415 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2418 DiagnoseHLSLAvailability(Sema &SemaRef)
2420 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2421 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2424 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2425 void RunOnFunction(
const FunctionDecl *FD);
2427 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2428 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2430 HandleFunctionOrMethodRef(FD, DRE);
2434 bool VisitMemberExpr(MemberExpr *ME)
override {
2435 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2437 HandleFunctionOrMethodRef(FD, ME);
2442void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2445 "expected DeclRefExpr or MemberExpr");
2449 if (FD->
hasBody(FDWithBody)) {
2450 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2451 DeclsToScan.push_back(FDWithBody);
2456 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2458 CheckDeclAvailability(
2462void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2471 DeclContextsToScan.push_back(TU);
2473 while (!DeclContextsToScan.empty()) {
2474 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2475 for (
auto &D : DC->
decls()) {
2482 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2483 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2488 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2493 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2494 SetShaderStageContext(ShaderAttr->getType());
2503 for (
const auto *Redecl : FD->
redecls()) {
2504 if (Redecl->isInExportDeclContext()) {
2511 SetUnknownShaderStageContext();
2519void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2520 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2521 DeclsToScan.push_back(FD);
2523 while (!DeclsToScan.empty()) {
2531 const unsigned ScannedStages = GetScannedStages(FD);
2532 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2535 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2537 AddToScannedFunctions(FD);
2542bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2543 const AvailabilityAttr *AA) {
2548 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2549 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2552 llvm::Triple::EnvironmentType AttrEnv =
2553 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2555 return CurrentEnv == AttrEnv;
2558const AvailabilityAttr *
2559DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2560 AvailabilityAttr
const *PartialMatch =
nullptr;
2564 for (
const auto *A : D->
attrs()) {
2565 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2566 StringRef AttrPlatform = Avail->getPlatform()->getName();
2567 StringRef TargetPlatform =
2571 if (AttrPlatform == TargetPlatform) {
2573 if (HasMatchingEnvironmentOrNone(Avail))
2575 PartialMatch = Avail;
2579 return PartialMatch;
2584void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2585 const AvailabilityAttr *AA,
2604 if (ReportOnlyShaderStageIssues)
2610 if (InUnknownShaderStageContext())
2615 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2616 VersionTuple Introduced = AA->getIntroduced();
2625 llvm::StringRef PlatformName(
2628 llvm::StringRef CurrentEnvStr =
2629 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2631 llvm::StringRef AttrEnvStr =
2632 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2633 bool UseEnvironment = !AttrEnvStr.empty();
2635 if (EnvironmentMatches) {
2636 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2637 <<
Range << D << PlatformName << Introduced.getAsString()
2638 << UseEnvironment << CurrentEnvStr;
2640 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2644 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2645 << D << PlatformName << Introduced.getAsString()
2647 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2654 if (!DefaultCBufferDecls.empty()) {
2657 DefaultCBufferDecls);
2659 getNextImplicitBindingOrderID());
2660 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2664 for (
const Decl *VD : DefaultCBufferDecls) {
2665 const HLSLResourceBindingAttr *RBA =
2666 VD->
getAttr<HLSLResourceBindingAttr>();
2667 if (RBA && RBA->hasRegisterSlot() &&
2668 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2675 SemaRef.Consumer.HandleTopLevelDecl(DG);
2677 diagnoseAvailabilityViolations(TU);
2687 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2690 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2697 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2700 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2725 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2740 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2741 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2742 << ArgOrdinal << 5 << 0
2748 unsigned ArgIndex) {
2749 auto *Arg = TheCall->
getArg(ArgIndex);
2751 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2754 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2764 if (VecTy->getElementType()->isDoubleType())
2765 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2766 << ArgOrdinal << 1 << 0 << 1
2776 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2777 << ArgOrdinal << 5 << 1
2786 if (VecTy->getElementType()->isUnsignedIntegerType())
2789 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2790 << ArgOrdinal << 4 << 3 << 0
2799 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2800 << ArgOrdinal << 5 << 3
2816 unsigned ArgIndex) {
2825 diag::err_typecheck_expect_scalar_or_vector)
2826 << ArgType << Scalar;
2833 unsigned ArgIndex) {
2838 if (!(ArgType->isScalarType() ||
2839 (VTy && VTy->getElementType()->isScalarType()))) {
2841 diag::err_typecheck_expect_any_scalar_or_vector)
2858 diag::err_typecheck_expect_any_scalar_or_vector)
2871 diag::err_typecheck_call_different_arg_types)
2890 Arg1ScalarTy = VTy->getElementType();
2894 Arg2ScalarTy = VTy->getElementType();
2897 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2898 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2908 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2910 diag::err_typecheck_vector_lengths_not_equal)
2916 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2918 diag::err_typecheck_vector_lengths_not_equal)
2931 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2935 const HLSLAttributedResourceType *ResTy =
2939 diag::err_typecheck_expect_hlsl_resource)
2943 if (Check && Check(ResTy)) {
2945 diag::err_invalid_hlsl_resource_type)
2955 switch (BuiltinID) {
2956 case Builtin::BI__builtin_hlsl_adduint64: {
2957 if (
SemaRef.checkArgCount(TheCall, 2))
2970 if (ElementBitCount != 32) {
2972 diag::err_integer_incorrect_bit_count)
2973 << 32 << ElementBitCount;
2978 int NumElementsArg = VTy->getNumElements();
2979 if (NumElementsArg != 2 && NumElementsArg != 4) {
2981 << 1 << 64 << NumElementsArg * ElementBitCount;
2995 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2996 if (
SemaRef.checkArgCount(TheCall, 2) ||
2999 SemaRef.getASTContext().UnsignedIntTy))
3004 QualType ContainedTy = ResourceTy->getContainedType();
3007 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
3013 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
3014 if (
SemaRef.checkArgCount(TheCall, 1) ||
3022 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
3024 if (
SemaRef.checkArgCount(TheCall, 6) ||
3038 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
3040 if (
SemaRef.checkArgCount(TheCall, 6) ||
3054 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
3056 if (
SemaRef.checkArgCount(TheCall, 3) ||
3063 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3064 auto MainAttrs = MainResType->getAttrs();
3065 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3066 MainAttrs.IsCounter =
true;
3068 MainResType->getWrappedType(), MainResType->getContainedType(),
3070 TheCall->
setType(CounterHandleTy);
3073 case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
3075 if (
SemaRef.checkArgCount(TheCall, 2) ||
3082 case Builtin::BI__builtin_hlsl_resource_getstride: {
3084 if (
SemaRef.checkArgCount(TheCall, 2) ||
3091 case Builtin::BI__builtin_hlsl_and:
3092 case Builtin::BI__builtin_hlsl_or: {
3093 if (
SemaRef.checkArgCount(TheCall, 2))
3106 case Builtin::BI__builtin_hlsl_all:
3107 case Builtin::BI__builtin_hlsl_any: {
3108 if (
SemaRef.checkArgCount(TheCall, 1))
3114 case Builtin::BI__builtin_hlsl_asdouble: {
3115 if (
SemaRef.checkArgCount(TheCall, 2))
3119 SemaRef.Context.UnsignedIntTy,
3124 SemaRef.Context.UnsignedIntTy,
3133 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3134 if (
SemaRef.BuiltinElementwiseTernaryMath(
3140 case Builtin::BI__builtin_hlsl_dot: {
3142 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3148 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3149 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3150 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3160 EltTy = VecTy->getElementType();
3161 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3174 case Builtin::BI__builtin_hlsl_select: {
3175 if (
SemaRef.checkArgCount(TheCall, 3))
3183 if (VTy && VTy->getElementType()->isBooleanType() &&
3188 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3189 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3190 if (
SemaRef.checkArgCount(TheCall, 1))
3196 diag::err_builtin_invalid_arg_type)
3199 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3203 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3204 case Builtin::BI__builtin_hlsl_elementwise_radians:
3205 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3206 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3207 if (
SemaRef.checkArgCount(TheCall, 1))
3212 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3216 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3217 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3218 if (
SemaRef.checkArgCount(TheCall, 1))
3223 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3228 case Builtin::BI__builtin_hlsl_lerp: {
3229 if (
SemaRef.checkArgCount(TheCall, 3))
3236 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3240 case Builtin::BI__builtin_hlsl_mad: {
3241 if (
SemaRef.BuiltinElementwiseTernaryMath(
3247 case Builtin::BI__builtin_hlsl_normalize: {
3248 if (
SemaRef.checkArgCount(TheCall, 1))
3259 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3260 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3268 case Builtin::BI__builtin_hlsl_step: {
3269 if (
SemaRef.checkArgCount(TheCall, 2))
3281 case Builtin::BI__builtin_hlsl_wave_active_max:
3282 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3283 if (
SemaRef.checkArgCount(TheCall, 1))
3298 case Builtin::BI__builtin_elementwise_bitreverse: {
3306 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3307 if (
SemaRef.checkArgCount(TheCall, 2))
3315 diag::err_typecheck_convert_incompatible)
3316 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3329 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3330 if (
SemaRef.checkArgCount(TheCall, 0))
3334 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3335 if (
SemaRef.checkArgCount(TheCall, 3))
3350 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3351 if (
SemaRef.checkArgCount(TheCall, 1))
3358 case Builtin::BI__builtin_elementwise_acos:
3359 case Builtin::BI__builtin_elementwise_asin:
3360 case Builtin::BI__builtin_elementwise_atan:
3361 case Builtin::BI__builtin_elementwise_atan2:
3362 case Builtin::BI__builtin_elementwise_ceil:
3363 case Builtin::BI__builtin_elementwise_cos:
3364 case Builtin::BI__builtin_elementwise_cosh:
3365 case Builtin::BI__builtin_elementwise_exp:
3366 case Builtin::BI__builtin_elementwise_exp2:
3367 case Builtin::BI__builtin_elementwise_exp10:
3368 case Builtin::BI__builtin_elementwise_floor:
3369 case Builtin::BI__builtin_elementwise_fmod:
3370 case Builtin::BI__builtin_elementwise_log:
3371 case Builtin::BI__builtin_elementwise_log2:
3372 case Builtin::BI__builtin_elementwise_log10:
3373 case Builtin::BI__builtin_elementwise_pow:
3374 case Builtin::BI__builtin_elementwise_roundeven:
3375 case Builtin::BI__builtin_elementwise_sin:
3376 case Builtin::BI__builtin_elementwise_sinh:
3377 case Builtin::BI__builtin_elementwise_sqrt:
3378 case Builtin::BI__builtin_elementwise_tan:
3379 case Builtin::BI__builtin_elementwise_tanh:
3380 case Builtin::BI__builtin_elementwise_trunc: {
3386 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3387 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3388 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3389 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3391 if (
SemaRef.checkArgCount(TheCall, 2) ||
3394 SemaRef.getASTContext().IntTy))
3397 std::optional<llvm::APSInt> Offset =
3399 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3401 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3414 WorkList.push_back(BaseTy);
3415 while (!WorkList.empty()) {
3417 T =
T.getCanonicalType().getUnqualifiedType();
3418 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3426 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3427 llvm::append_range(List, ElementFields);
3432 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3433 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3436 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
3437 List.insert(List.end(), MT->getNumElementsFlattened(),
3438 MT->getElementType());
3441 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3442 if (RD->isStandardLayout())
3443 RD = RD->getStandardLayoutBaseWithFields();
3447 if (RD->
isUnion() || !RD->isAggregate()) {
3453 for (
const auto *FD : RD->
fields())
3454 if (!FD->isUnnamedBitField())
3455 FieldTypes.push_back(FD->
getType());
3457 std::reverse(FieldTypes.begin(), FieldTypes.end());
3458 llvm::append_range(WorkList, FieldTypes);
3462 if (!RD->isStandardLayout()) {
3464 for (
const auto &
Base : RD->bases())
3465 FieldTypes.push_back(
Base.getType());
3466 std::reverse(FieldTypes.begin(), FieldTypes.end());
3467 llvm::append_range(WorkList, FieldTypes);
3489 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3495 int ArraySize = VT->getNumElements();
3500 QualType ElTy = VT->getElementType();
3504 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3520 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3529 return llvm::equal(T1Types, T2Types,
3531 return SemaRef.IsLayoutCompatible(LHS, RHS);
3540 bool HadError =
false;
3542 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3550 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3551 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3552 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3553 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3555 if (NSpellingIdx != OSpellingIdx) {
3557 diag::err_hlsl_param_qualifier_mismatch)
3558 << NDAttr << NewParam;
3574 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3589 llvm_unreachable(
"HLSL doesn't support pointers.");
3592 llvm_unreachable(
"HLSL doesn't support complex types.");
3594 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3596 llvm_unreachable(
"Should have returned before this");
3606 llvm_unreachable(
"HLSL doesn't support complex types.");
3608 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3613 llvm_unreachable(
"HLSL doesn't support pointers.");
3615 llvm_unreachable(
"Should have returned before this");
3621 llvm_unreachable(
"HLSL doesn't support pointers.");
3624 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3628 llvm_unreachable(
"HLSL doesn't support complex types.");
3631 llvm_unreachable(
"Unhandled scalar cast");
3658 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3659 if (DestTypes[I]->isUnionType())
3688 if (SrcTypes.size() < DestTypes.size())
3691 unsigned SrcSize = SrcTypes.size();
3692 unsigned DstSize = DestTypes.size();
3694 for (I = 0; I < DstSize && I < SrcSize; I++) {
3695 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3703 for (; I < SrcSize; I++) {
3704 if (SrcTypes[I]->isUnionType())
3711 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3712 "We should not get here without a parameter modifier expression");
3713 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3720 << Arg << (IsInOut ? 1 : 0);
3726 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3733 << Arg << (IsInOut ? 1 : 0);
3745 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3751 auto *OpV =
new (Ctx)
3756 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3757 tok::equal, ArgOpV, OpV);
3773 "Pointer and reference types cannot be inout or out parameters");
3774 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3784 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3790 if (
Decl->getType().hasAddressSpace())
3793 if (
Decl->getType()->isDependentType())
3825 if (
SemaRef.RequireCompleteType(
3828 diag::err_typecheck_decl_incomplete_type)) {
3842 DefaultCBufferDecls.push_back(VD);
3847 collectResourceBindingsOnVarDecl(VD);
3850 VD->
hasAttr<HLSLVkConstantIdAttr>()) {
3858 processExplicitBindingsOnDecl(VD);
3866 uint32_t OrderID = getNextImplicitBindingOrderID();
3884 uint32_t OrderID = getNextImplicitBindingOrderID();
3894bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3896 "expected resource record type");
3912 const char *CreateMethodName;
3913 if (Binding.isExplicit())
3914 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
3915 :
"__createFromBinding";
3917 CreateMethodName = HasCounter
3918 ?
"__createFromImplicitBindingWithImplicitCounter"
3919 :
"__createFromImplicitBinding";
3930 if (Binding.isExplicit()) {
3934 Args.push_back(RegSlot);
3936 uint32_t OrderID = (Binding.hasImplicitOrderID())
3937 ? Binding.getImplicitOrderID()
3938 : getNextImplicitBindingOrderID();
3942 Args.push_back(OrderId);
3945 IntegerLiteral *Space =
3948 Args.push_back(Space);
3951 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
3952 Args.push_back(RangeSize);
3955 AST, llvm::APInt(UIntTySize, 0), AST.
UnsignedIntTy, SourceLocation());
3956 Args.push_back(Index);
3958 StringRef VarName = VD->
getName();
3965 Name,
nullptr,
VK_PRValue, FPOptionsOverride());
3966 Args.push_back(NameCast);
3970 uint32_t CounterOrderID = getNextImplicitBindingOrderID();
3971 IntegerLiteral *CounterId =
3974 Args.push_back(CounterId);
3985 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod,
false,
3990 CK_FunctionToPointerDecay, DRE,
nullptr,
VK_PRValue, FPOptionsOverride());
3992 CallExpr *InitExpr =
3994 SourceLocation(), FPOptionsOverride());
3997 SemaRef.CheckCompleteVariableDeclaration(VD);
4001bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
4003 "expected array of resource records");
4014 ASTContext &AST =
SemaRef.getASTContext();
4017 CXXMethodDecl *CreateMethod =
nullptr;
4020 ResourceBindingAttrs ResourceAttrs(VD);
4021 if (ResourceAttrs.isExplicit())
4024 lookupMethod(
SemaRef, ResourceDecl,
4025 HasCounter ?
"__createFromBindingWithImplicitCounter"
4026 :
"__createFromBinding",
4030 CreateMethod = lookupMethod(
4032 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
4033 :
"__createFromImplicitBinding",
4058 return initGlobalResourceDecl(VD);
4060 return initGlobalResourceArrayDecl(VD);
4070 "expected LHS to be a resource record or array of resource records");
4071 if (Opc != BO_Assign)
4076 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
4084 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
4095void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
4097 "expected global variable that contains HLSL resource");
4100 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
4101 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
4102 ? ResourceClass::CBuffer
4103 : ResourceClass::SRV);
4116 if (
const HLSLAttributedResourceType *AttrResType =
4117 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4118 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4123 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
4124 collectResourceBindingsOnUserRecordDecl(VD, RT);
4130void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
4133 bool HasBinding =
false;
4134 for (Attr *A : VD->
attrs()) {
4138 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4139 if (!RBA || !RBA->hasRegisterSlot())
4144 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
4145 "never have an attribute created");
4147 if (RT == RegisterType::C) {
4148 if (Bindings.hasBindingInfoForDecl(VD))
4150 diag::warn_hlsl_user_defined_type_missing_member)
4151 <<
static_cast<int>(RT);
4159 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4164 diag::warn_hlsl_user_defined_type_missing_member)
4165 <<
static_cast<int>(RT);
4173class InitListTransformer {
4177 QualType *DstIt =
nullptr;
4178 Expr **ArgIt =
nullptr;
4184 bool castInitializer(Expr *E) {
4185 assert(DstIt &&
"This should always be something!");
4186 if (DstIt == DestTypes.end()) {
4188 ArgExprs.push_back(E);
4193 DstIt = DestTypes.begin();
4196 Ctx, *DstIt,
false);
4201 ArgExprs.push_back(
Init);
4206 bool buildInitializerListImpl(Expr *E) {
4208 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4209 for (
auto *SubInit :
Init->inits())
4210 if (!buildInitializerListImpl(SubInit))
4219 return castInitializer(E);
4221 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4226 for (uint64_t I = 0; I <
Size; ++I) {
4228 SizeTy, SourceLocation());
4234 if (!castInitializer(ElExpr.
get()))
4239 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
4240 unsigned Rows = MTy->getNumRows();
4241 unsigned Cols = MTy->getNumColumns();
4242 QualType ElemTy = MTy->getElementType();
4244 for (
unsigned C = 0;
C < Cols; ++
C) {
4245 for (
unsigned R = 0; R < Rows; ++R) {
4258 if (!castInitializer(ElExpr.
get()))
4266 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4270 for (uint64_t I = 0; I <
Size; ++I) {
4272 SizeTy, SourceLocation());
4277 if (!buildInitializerListImpl(ElExpr.
get()))
4284 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4285 RecordDecls.push_back(RD);
4286 while (RecordDecls.back()->getNumBases()) {
4287 CXXRecordDecl *D = RecordDecls.back();
4289 "HLSL doesn't support multiple inheritance");
4290 RecordDecls.push_back(
4293 while (!RecordDecls.empty()) {
4294 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4295 for (
auto *FD : RD->
fields()) {
4296 if (FD->isUnnamedBitField())
4304 if (!buildInitializerListImpl(Res.
get()))
4312 Expr *generateInitListsImpl(QualType Ty) {
4313 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
4317 llvm::SmallVector<Expr *> Inits;
4323 if (
auto *ATy = Ty->
getAs<VectorType>()) {
4324 ElTy = ATy->getElementType();
4325 Size = ATy->getNumElements();
4326 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
4327 ElTy = CMTy->getElementType();
4328 Size = CMTy->getNumElementsFlattened();
4331 ElTy = VTy->getElementType();
4332 Size = VTy->getZExtSize();
4334 for (uint64_t I = 0; I <
Size; ++I)
4335 Inits.push_back(generateInitListsImpl(ElTy));
4338 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4339 RecordDecls.push_back(RD);
4340 while (RecordDecls.back()->getNumBases()) {
4341 CXXRecordDecl *D = RecordDecls.back();
4343 "HLSL doesn't support multiple inheritance");
4344 RecordDecls.push_back(
4347 while (!RecordDecls.empty()) {
4348 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4349 for (
auto *FD : RD->
fields())
4350 if (!FD->isUnnamedBitField())
4351 Inits.push_back(generateInitListsImpl(FD->
getType()));
4354 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4355 Inits, Inits.back()->getEndLoc());
4356 NewInit->setType(Ty);
4361 llvm::SmallVector<QualType, 16> DestTypes;
4362 llvm::SmallVector<Expr *, 16> ArgExprs;
4363 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4364 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4365 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4366 InitTy = Entity.
getType().getNonReferenceType();
4376 DstIt = DestTypes.begin();
4379 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4381 Expr *generateInitLists() {
4382 assert(!ArgExprs.empty() &&
4383 "Call buildInitializerList to generate argument expressions.");
4384 ArgIt = ArgExprs.begin();
4386 return generateInitListsImpl(InitTy);
4387 llvm::SmallVector<Expr *> Inits;
4388 while (ArgIt != ArgExprs.end())
4389 Inits.push_back(generateInitListsImpl(InitTy));
4391 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4392 Inits, Inits.back()->getEndLoc());
4393 llvm::APInt ArySize(64, Inits.size());
4395 ArraySizeModifier::Normal, 0));
4404 if (
Init->getType()->isScalarType())
4407 InitListTransformer ILT(
SemaRef, Entity);
4409 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4417 Init->setInit(I, E);
4419 if (!ILT.buildInitializerList(E))
4422 size_t ExpectedSize = ILT.DestTypes.size();
4423 size_t ActualSize = ILT.ArgExprs.size();
4424 if (ExpectedSize == 0 && ActualSize == 0)
4433 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4440 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4441 if (ExpectedSize != ActualSize) {
4442 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4443 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4444 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4451 Init->resizeInits(Ctx, NewInit->getNumInits());
4452 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4453 Init->updateInit(Ctx, I, NewInit->getInit(I));
4458 const HLSLVkConstantIdAttr *ConstIdAttr =
4459 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4466 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4476 int ConstantID = ConstIdAttr->getId();
4477 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4479 ConstIdAttr->getLocation());
4483 if (
C->getType()->getCanonicalTypeUnqualified() !=
4487 Context.getTrivialTypeSourceInfo(
4488 Init->getType(),
Init->getExprLoc()),
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static 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 bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static bool isResourceRecordTypeOrArrayOf(VarDecl *VD)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static const HLSLAttributedResourceType * getResourceArrayHandleType(VarDecl *VD)
static RegisterType getRegisterType(ResourceClass RC)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool hasCounterHandle(const CXXRecordDecl *RD)
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 ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
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)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool isValidWaveSizeValue(unsigned Value)
static bool IsDefaultBufferConstantDecl(VarDecl *VD)
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)
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)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
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 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 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 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.
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.
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.
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
getQuantity - 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.
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.
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
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.
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.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
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.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
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 ...
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.
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'.
Represents the results of name lookup.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
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.
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
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_iterator field_end() const
field_range fields() const
field_iterator field_begin() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
ASTContext & getASTContext() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)
void handleWaveSizeAttr(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 handleShaderAttr(Decl *D, const ParsedAttr &AL)
void CheckEntryPoint(FunctionDecl *FD)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
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)
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, std::optional< unsigned > Index)
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)
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)
T * createSemanticAttr(const AttributeCommonInfo &ACI, NamedDecl *TargetDecl, std::optional< unsigned > Location)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
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)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
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.
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 BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
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.
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
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.
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
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
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...
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
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 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
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.
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
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
CastKind
CastKind - The kind of operation required for a conversion.
@ 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.
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const