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");
774bool SemaHLSL::determineActiveSemanticOnScalar(
776 SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics) {
777 if (ActiveSemantic.Semantic ==
nullptr) {
778 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
779 if (ActiveSemantic.Semantic)
780 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
783 if (!ActiveSemantic.Semantic) {
789 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
790 ActiveSemantic.Semantic->getAttrName()->getName(),
791 ActiveSemantic.Index.value_or(0));
795 checkSemanticAnnotation(FD, D, A);
796 OutputDecl->addAttr(A);
798 unsigned Location = ActiveSemantic.Index.value_or(0);
800 const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->
getType());
801 unsigned ElementCount = AT ? AT->getZExtSize() : 1;
802 ActiveSemantic.Index = Location + ElementCount;
804 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
805 for (
unsigned I = 0; I < ElementCount; ++I) {
806 Twine VariableName = BaseName.concat(Twine(Location + I));
808 auto [_, Inserted] = ActiveInputSemantics.insert(VariableName.str());
810 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
811 << VariableName.str();
819bool SemaHLSL::determineActiveSemantic(
821 SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics) {
822 if (ActiveSemantic.Semantic ==
nullptr) {
823 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
824 if (ActiveSemantic.Semantic)
825 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
829 const RecordType *RT = dyn_cast<RecordType>(
T);
831 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
832 ActiveInputSemantics);
834 const RecordDecl *RD = RT->getDecl();
835 for (FieldDecl *Field : RD->
fields()) {
836 SemanticInfo Info = ActiveSemantic;
837 if (!determineActiveSemantic(FD, OutputDecl, Field, Info,
838 ActiveInputSemantics)) {
839 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
842 if (ActiveSemantic.Semantic)
843 ActiveSemantic = Info;
850 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
851 assert(ShaderAttr &&
"Entry point has no shader attribute");
852 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
856 case llvm::Triple::Pixel:
857 case llvm::Triple::Vertex:
858 case llvm::Triple::Geometry:
859 case llvm::Triple::Hull:
860 case llvm::Triple::Domain:
861 case llvm::Triple::RayGeneration:
862 case llvm::Triple::Intersection:
863 case llvm::Triple::AnyHit:
864 case llvm::Triple::ClosestHit:
865 case llvm::Triple::Miss:
866 case llvm::Triple::Callable:
867 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
869 {llvm::Triple::Compute,
870 llvm::Triple::Amplification,
871 llvm::Triple::Mesh});
874 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
876 {llvm::Triple::Compute,
877 llvm::Triple::Amplification,
878 llvm::Triple::Mesh});
883 case llvm::Triple::Compute:
884 case llvm::Triple::Amplification:
885 case llvm::Triple::Mesh:
886 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
888 << llvm::Triple::getEnvironmentTypeName(ST);
891 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
892 if (Ver < VersionTuple(6, 6)) {
893 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
896 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
899 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
900 << WS << WS->getSpelledArgsCount() <<
"6.8";
905 case llvm::Triple::RootSignature:
906 llvm_unreachable(
"rootsig environment has no function entry point");
908 llvm_unreachable(
"Unhandled environment in triple");
911 llvm::StringSet<> ActiveInputSemantics;
913 SemanticInfo ActiveSemantic;
914 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
915 if (ActiveSemantic.Semantic)
916 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
918 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic,
919 ActiveInputSemantics)) {
920 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
927void SemaHLSL::checkSemanticAnnotation(
929 const HLSLAppliedSemanticAttr *SemanticAttr) {
930 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
931 assert(ShaderAttr &&
"Entry point has no shader attribute");
932 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
934 auto SemanticName = SemanticAttr->getSemanticName().upper();
935 if (SemanticName ==
"SV_DISPATCHTHREADID" ||
936 SemanticName ==
"SV_GROUPINDEX" || SemanticName ==
"SV_GROUPTHREADID" ||
937 SemanticName ==
"SV_GROUPID") {
939 if (ST != llvm::Triple::Compute)
942 if (SemanticAttr->getSemanticIndex() != 0) {
943 std::string PrettyName =
944 "'" + SemanticAttr->getSemanticName().str() +
"'";
945 Diag(SemanticAttr->getLoc(),
946 diag::err_hlsl_semantic_indexing_not_supported)
952 if (SemanticName ==
"SV_POSITION") {
955 if (ST == llvm::Triple::Pixel)
963 if (SemanticAttr->getAttrName()->getName().starts_with_insensitive(
"SV_"))
964 llvm_unreachable(
"Unknown SemanticAttr");
968 const Attr *A, llvm::Triple::EnvironmentType Stage,
969 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
971 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
972 [](llvm::Triple::EnvironmentType ST) {
974 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
976 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
977 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
978 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
981template <CastKind Kind>
984 Ty = VTy->getElementType();
989template <CastKind Kind>
1001 if (LHSFloat && RHSFloat) {
1029 if (LHSSigned == RHSSigned) {
1030 if (IsCompAssign || IntOrder >= 0)
1038 if (IntOrder != (LHSSigned ? 1 : -1)) {
1039 if (IsCompAssign || RHSSigned)
1047 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1048 if (IsCompAssign || LHSSigned)
1064 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1065 QualType NewTy = Ctx.getExtVectorType(
1075 return CK_FloatingCast;
1077 return CK_IntegralCast;
1079 return CK_IntegralToFloating;
1081 return CK_FloatingToIntegral;
1087 bool IsCompAssign) {
1094 if (!LVecTy && IsCompAssign) {
1096 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1098 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1100 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1105 unsigned EndSz = std::numeric_limits<unsigned>::max();
1108 LSz = EndSz = LVecTy->getNumElements();
1111 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1112 "one of the above should have had a value");
1116 if (IsCompAssign && LSz != EndSz) {
1118 diag::err_hlsl_vector_compound_assignment_truncation)
1119 << LHSType << RHSType;
1125 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1130 if (!IsCompAssign && !LVecTy)
1134 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1135 return Ctx.getCommonSugaredType(LHSType, RHSType);
1143 LElTy, RElTy, IsCompAssign);
1146 "HLSL Vectors can only contain integer or floating point types");
1148 LElTy, RElTy, IsCompAssign);
1153 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1154 "Called with non-logical operator");
1156 llvm::raw_svector_ostream OS(Buff);
1158 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1159 OS << NewFnName <<
"(";
1169std::pair<IdentifierInfo *, bool>
1172 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1179 return {DeclIdent,
Found};
1190 for (
auto &RootSigElement : RootElements)
1191 Elements.push_back(RootSigElement.getElement());
1195 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1197 SignatureDecl->setImplicit();
1203 if (RootSigOverrideIdent) {
1206 if (
SemaRef.LookupQualifiedName(R, DC))
1207 return dyn_cast<HLSLRootSignatureDecl>(R.
getFoundDecl());
1215struct PerVisibilityBindingChecker {
1218 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1222 llvm::dxbc::ShaderVisibility Vis;
1227 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1229 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1230 llvm::dxil::ResourceClass RC, uint32_t Space,
1231 uint32_t LowerBound, uint32_t UpperBound,
1232 const hlsl::RootSignatureElement *Elem) {
1234 assert(BuilderIndex < Builders.size() &&
1235 "Not enough builders for visibility type");
1236 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1237 static_cast<const void *
>(Elem));
1239 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1240 "'All' visibility must come first");
1241 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1242 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1243 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1244 static_cast<const void *
>(Elem));
1246 ElemInfoMap.push_back({Elem,
Visibility,
false});
1249 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1250 auto It = llvm::lower_bound(
1252 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1253 assert(It->Elem == Elem &&
"Element not in map");
1257 bool checkOverlap() {
1258 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1259 return LHS.Elem < RHS.Elem;
1262 bool HadOverlap =
false;
1264 using llvm::hlsl::BindingInfoBuilder;
1265 auto ReportOverlap = [
this,
1266 &HadOverlap](
const BindingInfoBuilder &Builder,
1267 const llvm::hlsl::Binding &Reported) {
1271 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1272 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1273 const auto *PrevElem =
1274 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1276 ElemInfo &Info =
getInfo(Elem);
1281 Info.Diagnosed =
true;
1283 ElemInfo &PrevInfo =
getInfo(PrevElem);
1284 llvm::dxbc::ShaderVisibility CommonVis =
1285 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1288 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1289 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1290 << Reported.isUnbounded() << Reported.UpperBound
1295 this->S->
Diag(PrevElem->getLocation(),
1296 diag::note_hlsl_resource_range_here);
1299 for (BindingInfoBuilder &Builder : Builders)
1300 Builder.calculateBindingInfo(ReportOverlap);
1324 if (
const auto *ResTy =
1325 SecondField->
getType()->
getAs<HLSLAttributedResourceType>()) {
1326 return ResTy->getAttrs().IsCounter;
1334 bool HadError =
false;
1335 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1336 uint32_t UpperBound) {
1338 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1339 << LowerBound << UpperBound;
1346 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1347 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1348 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1351 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1352 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1353 ReportError(Loc, 0, 0xfffffffe);
1356 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1357 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1358 ReportError(Loc, 0, 0xffffffef);
1361 const uint32_t Version =
1362 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1363 const uint32_t VersionEnum = Version - 1;
1364 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1366 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1373 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1374 if (
const auto *Descriptor =
1375 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1376 VerifyRegister(Loc, Descriptor->Reg.Number);
1377 VerifySpace(Loc, Descriptor->Space);
1379 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1381 ReportFlagError(Loc);
1382 }
else if (
const auto *Constants =
1383 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1384 VerifyRegister(Loc, Constants->Reg.Number);
1385 VerifySpace(Loc, Constants->Space);
1386 }
else if (
const auto *Sampler =
1387 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1388 VerifyRegister(Loc, Sampler->Reg.Number);
1389 VerifySpace(Loc, Sampler->Space);
1392 "By construction, parseFloatParam can't produce a NaN from a "
1393 "float_literal token");
1395 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1396 ReportError(Loc, 0, 16);
1397 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1398 ReportFloatError(Loc, -16.f, 15.99f);
1399 }
else if (
const auto *Clause =
1400 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1402 VerifyRegister(Loc, Clause->Reg.Number);
1403 VerifySpace(Loc, Clause->Space);
1405 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1409 ReportError(Loc, 1, 0xfffffffe);
1412 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1414 ReportFlagError(Loc);
1418 PerVisibilityBindingChecker BindingChecker(
this);
1419 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1424 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1425 if (
const auto *Descriptor =
1426 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1427 uint32_t LowerBound(Descriptor->Reg.Number);
1428 uint32_t UpperBound(LowerBound);
1430 BindingChecker.trackBinding(
1431 Descriptor->Visibility,
1432 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1433 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1434 }
else if (
const auto *Constants =
1435 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1436 uint32_t LowerBound(Constants->Reg.Number);
1437 uint32_t UpperBound(LowerBound);
1439 BindingChecker.trackBinding(
1440 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1441 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1442 }
else if (
const auto *Sampler =
1443 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1444 uint32_t LowerBound(Sampler->Reg.Number);
1445 uint32_t UpperBound(LowerBound);
1447 BindingChecker.trackBinding(
1448 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1449 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1450 }
else if (
const auto *Clause =
1451 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1454 UnboundClauses.emplace_back(Clause, &RootSigElem);
1455 }
else if (
const auto *Table =
1456 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1457 assert(UnboundClauses.size() == Table->NumClauses &&
1458 "Number of unbound elements must match the number of clauses");
1459 bool HasAnySampler =
false;
1460 bool HasAnyNonSampler =
false;
1461 uint64_t Offset = 0;
1462 bool IsPrevUnbound =
false;
1463 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1465 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1466 HasAnySampler =
true;
1468 HasAnyNonSampler =
true;
1470 if (HasAnySampler && HasAnyNonSampler)
1471 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1476 if (Clause->NumDescriptors == 0)
1480 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1482 Offset = Clause->Offset;
1484 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1485 Offset, Clause->NumDescriptors);
1487 if (IsPrevUnbound && IsAppending)
1488 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1489 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1490 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1493 Offset = RangeBound + 1;
1494 IsPrevUnbound = Clause->NumDescriptors ==
1495 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1498 uint32_t LowerBound(Clause->Reg.Number);
1499 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1500 LowerBound, Clause->NumDescriptors);
1502 BindingChecker.trackBinding(
1504 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1505 LowerBound, UpperBound, ClauseElem);
1507 UnboundClauses.clear();
1511 return BindingChecker.checkOverlap();
1516 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1521 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1522 if (RS->getSignatureIdent() != Ident) {
1523 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1527 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1533 if (
auto *SignatureDecl =
1541 llvm::VersionTuple SMVersion =
1546 uint32_t ZMax = 1024;
1547 uint32_t ThreadMax = 1024;
1548 if (IsDXIL && SMVersion.getMajor() <= 4) {
1551 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1561 diag::err_hlsl_numthreads_argument_oor)
1570 diag::err_hlsl_numthreads_argument_oor)
1579 diag::err_hlsl_numthreads_argument_oor)
1584 if (
X * Y * Z > ThreadMax) {
1585 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1602 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1610 if (SpelledArgsCount > 1 &&
1614 uint32_t Preferred = 0;
1615 if (SpelledArgsCount > 2 &&
1619 if (SpelledArgsCount > 2) {
1622 diag::err_attribute_power_of_two_in_range)
1623 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1628 if (Preferred < Min || Preferred >
Max) {
1630 diag::err_attribute_power_of_two_in_range)
1631 << AL <<
Min <<
Max << Preferred;
1634 }
else if (SpelledArgsCount > 1) {
1637 diag::err_attribute_power_of_two_in_range)
1638 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1642 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1645 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1650 diag::err_attribute_power_of_two_in_range)
1651 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1656 HLSLWaveSizeAttr *NewAttr =
1680 uint32_t Binding = 0;
1695 if (!
T->hasUnsignedIntegerRepresentation() ||
1696 (VT && VT->getNumElements() > 3)) {
1697 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1698 << AL <<
"uint/uint2/uint3";
1707 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1708 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1709 << AL <<
"float/float1/float2/float3/float4";
1717 std::optional<unsigned> Index) {
1721 QualType ValueType = VD->getType();
1722 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1725 bool IsOutput =
false;
1726 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1733 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1736 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1737 if (Index.has_value())
1738 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1743 if (SemanticName ==
"SV_GROUPINDEX") {
1745 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1746 if (Index.has_value())
1747 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1752 if (SemanticName ==
"SV_GROUPTHREADID") {
1755 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1756 if (Index.has_value())
1757 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1762 if (SemanticName ==
"SV_GROUPID") {
1765 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1766 if (Index.has_value())
1767 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1772 if (SemanticName ==
"SV_POSITION") {
1773 const auto *VT = ValueType->getAs<
VectorType>();
1774 if (!ValueType->hasFloatingRepresentation() ||
1775 (VT && VT->getNumElements() > 4))
1776 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1777 << AL <<
"float/float1/float2/float3/float4";
1782 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1786 uint32_t IndexValue, ExplicitIndex;
1789 assert(IndexValue > 0 ? ExplicitIndex :
true);
1790 std::optional<unsigned> Index =
1791 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1801 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1802 << AL <<
"shader constant in a constant buffer";
1806 uint32_t SubComponent;
1816 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1821 if (IsAggregateTy || Size > 128) {
1822 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1826 if ((Component * 32 + Size) > 128) {
1827 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1832 EltTy = VT->getElementType();
1834 if (Align > 32 && Component == 1) {
1837 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1851 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1854 llvm::Triple::EnvironmentType ShaderType;
1855 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1856 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1857 << AL << Str << ArgLoc;
1871 assert(AttrList.size() &&
"expected list of resource attributes");
1878 HLSLAttributedResourceType::Attributes ResAttrs;
1880 bool HasResourceClass =
false;
1881 for (
const Attr *A : AttrList) {
1884 LocEnd = A->getRange().getEnd();
1885 switch (A->getKind()) {
1886 case attr::HLSLResourceClass: {
1888 if (HasResourceClass) {
1889 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1890 ? diag::warn_duplicate_attribute_exact
1891 : diag::warn_duplicate_attribute)
1895 ResAttrs.ResourceClass = RC;
1896 HasResourceClass =
true;
1900 if (ResAttrs.IsROV) {
1901 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1904 ResAttrs.IsROV =
true;
1906 case attr::HLSLRawBuffer:
1907 if (ResAttrs.RawBuffer) {
1908 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1911 ResAttrs.RawBuffer =
true;
1913 case attr::HLSLIsCounter:
1914 if (ResAttrs.IsCounter) {
1915 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1918 ResAttrs.IsCounter =
true;
1920 case attr::HLSLContainedType: {
1923 if (!ContainedTy.
isNull()) {
1924 S.
Diag(A->getLocation(), ContainedTy == Ty
1925 ? diag::warn_duplicate_attribute_exact
1926 : diag::warn_duplicate_attribute)
1935 llvm_unreachable(
"unhandled resource attribute type");
1939 if (!HasResourceClass) {
1940 S.
Diag(AttrList.back()->getRange().getEnd(),
1941 diag::err_hlsl_missing_resource_class);
1946 Wrapped, ContainedTy, ResAttrs);
1948 if (LocInfo && ContainedTyInfo) {
1961 if (!
T->isHLSLResourceType()) {
1962 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1977 AttributeCommonInfo::AS_CXX11, 0, false ,
1982 case ParsedAttr::AT_HLSLResourceClass: {
1984 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1995 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1996 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1997 <<
"ResourceClass" << Identifier;
2000 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2004 case ParsedAttr::AT_HLSLROV:
2008 case ParsedAttr::AT_HLSLRawBuffer:
2012 case ParsedAttr::AT_HLSLIsCounter:
2016 case ParsedAttr::AT_HLSLContainedType: {
2018 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2024 assert(TSI &&
"no type source info for attribute argument");
2026 diag::err_incomplete_type))
2028 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2033 llvm_unreachable(
"unhandled HLSL attribute");
2036 HLSLResourcesTypeAttrs.emplace_back(A);
2042 if (!HLSLResourcesTypeAttrs.size())
2048 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2049 const HLSLAttributedResourceType *RT =
2056 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2058 HLSLResourcesTypeAttrs.clear();
2066 auto I = LocsForHLSLAttributedResources.find(RT);
2067 if (I != LocsForHLSLAttributedResources.end()) {
2068 LocInfo = I->second;
2069 LocsForHLSLAttributedResources.erase(I);
2078void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2079 const RecordType *RT) {
2080 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
2087 "incomplete arrays inside user defined types are not supported");
2096 if (
const HLSLAttributedResourceType *AttrResType =
2097 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2102 Bindings.addDeclBindingInfo(VD, RC);
2103 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2109 collectResourceBindingsOnUserRecordDecl(VD, RT);
2121 bool SpecifiedSpace) {
2122 int RegTypeNum =
static_cast<int>(RegType);
2125 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2126 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2131 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2132 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2133 : ResourceClass::SRV;
2143 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2147 if (
const HLSLAttributedResourceType *AttrResType =
2148 HLSLAttributedResourceType::findHandleTypeOnResource(
2165 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2166 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2171 if (RegType == RegisterType::CBuffer)
2172 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2173 else if (RegType != RegisterType::C)
2174 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2178 if (RegType == RegisterType::C)
2179 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2181 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2191 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2199 bool RegisterTypesDetected[5] = {
false};
2200 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2203 if (HLSLResourceBindingAttr *
attr =
2204 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2207 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2208 int otherRegTypeNum =
static_cast<int>(otherRegType);
2210 diag::err_hlsl_duplicate_register_annotation)
2214 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2222 bool SpecifiedSpace) {
2227 "expecting VarDecl or HLSLBufferDecl");
2238 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2240 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2241 Ty = IAT->getElementType();
2243 diag::err_incomplete_type))
2247 StringRef Slot =
"";
2248 StringRef Space =
"";
2252 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2262 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2268 SpaceLoc = Loc->
getLoc();
2271 if (Str.starts_with(
"space")) {
2273 SpaceLoc = Loc->
getLoc();
2282 std::optional<unsigned> SlotNum;
2283 unsigned SpaceNum = 0;
2286 if (!Slot.empty()) {
2288 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2291 if (RegType == RegisterType::I) {
2292 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2295 StringRef SlotNumStr = Slot.substr(1);
2297 if (SlotNumStr.getAsInteger(10, N)) {
2298 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2305 if (!Space.starts_with(
"space")) {
2306 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2309 StringRef SpaceNumStr = Space.substr(5);
2310 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2311 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2316 if (SlotNum.has_value())
2321 HLSLResourceBindingAttr *NewAttr =
2322 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2324 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2379 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2383 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2384 unsigned CurrentShaderStageBit;
2389 bool ReportOnlyShaderStageIssues;
2392 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2393 static_assert(
sizeof(
unsigned) >= 4);
2394 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2395 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2396 "ShaderType is too big for this bitmap");
2399 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2400 CurrentShaderEnvironment = ShaderType;
2401 CurrentShaderStageBit = (1 << bitmapIndex);
2404 void SetUnknownShaderStageContext() {
2405 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2406 CurrentShaderStageBit = (1 << 31);
2409 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2410 return CurrentShaderEnvironment;
2413 bool InUnknownShaderStageContext()
const {
2414 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2418 void AddToScannedFunctions(
const FunctionDecl *FD) {
2419 unsigned &ScannedStages = ScannedDecls[FD];
2420 ScannedStages |= CurrentShaderStageBit;
2423 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2425 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2426 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2429 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2430 return ScannerStages & CurrentShaderStageBit;
2433 static bool NeverBeenScanned(
unsigned ScannedStages) {
2434 return ScannedStages == 0;
2438 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2439 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2441 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2442 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2445 DiagnoseHLSLAvailability(Sema &SemaRef)
2447 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2448 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2451 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2452 void RunOnFunction(
const FunctionDecl *FD);
2454 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2455 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2457 HandleFunctionOrMethodRef(FD, DRE);
2461 bool VisitMemberExpr(MemberExpr *ME)
override {
2462 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2464 HandleFunctionOrMethodRef(FD, ME);
2469void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2472 "expected DeclRefExpr or MemberExpr");
2476 if (FD->
hasBody(FDWithBody)) {
2477 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2478 DeclsToScan.push_back(FDWithBody);
2483 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2485 CheckDeclAvailability(
2489void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2498 DeclContextsToScan.push_back(TU);
2500 while (!DeclContextsToScan.empty()) {
2501 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2502 for (
auto &D : DC->
decls()) {
2509 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2510 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2515 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2520 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2521 SetShaderStageContext(ShaderAttr->getType());
2530 for (
const auto *Redecl : FD->
redecls()) {
2531 if (Redecl->isInExportDeclContext()) {
2538 SetUnknownShaderStageContext();
2546void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2547 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2548 DeclsToScan.push_back(FD);
2550 while (!DeclsToScan.empty()) {
2558 const unsigned ScannedStages = GetScannedStages(FD);
2559 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2562 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2564 AddToScannedFunctions(FD);
2569bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2570 const AvailabilityAttr *AA) {
2575 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2576 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2579 llvm::Triple::EnvironmentType AttrEnv =
2580 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2582 return CurrentEnv == AttrEnv;
2585const AvailabilityAttr *
2586DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2587 AvailabilityAttr
const *PartialMatch =
nullptr;
2591 for (
const auto *A : D->
attrs()) {
2592 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2593 StringRef AttrPlatform = Avail->getPlatform()->getName();
2594 StringRef TargetPlatform =
2598 if (AttrPlatform == TargetPlatform) {
2600 if (HasMatchingEnvironmentOrNone(Avail))
2602 PartialMatch = Avail;
2606 return PartialMatch;
2611void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2612 const AvailabilityAttr *AA,
2631 if (ReportOnlyShaderStageIssues)
2637 if (InUnknownShaderStageContext())
2642 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2643 VersionTuple Introduced = AA->getIntroduced();
2652 llvm::StringRef PlatformName(
2655 llvm::StringRef CurrentEnvStr =
2656 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2658 llvm::StringRef AttrEnvStr =
2659 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2660 bool UseEnvironment = !AttrEnvStr.empty();
2662 if (EnvironmentMatches) {
2663 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2664 <<
Range << D << PlatformName << Introduced.getAsString()
2665 << UseEnvironment << CurrentEnvStr;
2667 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2671 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2672 << D << PlatformName << Introduced.getAsString()
2674 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2681 if (!DefaultCBufferDecls.empty()) {
2684 DefaultCBufferDecls);
2686 getNextImplicitBindingOrderID());
2687 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2691 for (
const Decl *VD : DefaultCBufferDecls) {
2692 const HLSLResourceBindingAttr *RBA =
2693 VD->
getAttr<HLSLResourceBindingAttr>();
2694 if (RBA && RBA->hasRegisterSlot() &&
2695 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2702 SemaRef.Consumer.HandleTopLevelDecl(DG);
2704 diagnoseAvailabilityViolations(TU);
2714 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2717 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2724 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2727 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2752 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2767 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2768 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2769 << ArgOrdinal << 5 << 0
2775 unsigned ArgIndex) {
2776 auto *Arg = TheCall->
getArg(ArgIndex);
2778 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2781 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2791 if (VecTy->getElementType()->isDoubleType())
2792 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2793 << ArgOrdinal << 1 << 0 << 1
2803 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2804 << ArgOrdinal << 5 << 1
2813 if (VecTy->getElementType()->isUnsignedIntegerType())
2816 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2817 << ArgOrdinal << 4 << 3 << 0
2826 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2827 << ArgOrdinal << 5 << 3
2833 unsigned ArgOrdinal,
unsigned Width) {
2836 ArgTy = VTy->getElementType();
2838 uint64_t ElementBitCount =
2840 if (ElementBitCount != Width) {
2842 diag::err_integer_incorrect_bit_count)
2843 << Width << ElementBitCount;
2860 unsigned ArgIndex) {
2869 diag::err_typecheck_expect_scalar_or_vector)
2870 << ArgType << Scalar;
2877 unsigned ArgIndex) {
2882 if (!(ArgType->isScalarType() ||
2883 (VTy && VTy->getElementType()->isScalarType()))) {
2885 diag::err_typecheck_expect_any_scalar_or_vector)
2902 diag::err_typecheck_expect_any_scalar_or_vector)
2915 diag::err_typecheck_call_different_arg_types)
2934 Arg1ScalarTy = VTy->getElementType();
2938 Arg2ScalarTy = VTy->getElementType();
2941 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2942 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2952 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2954 diag::err_typecheck_vector_lengths_not_equal)
2960 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2962 diag::err_typecheck_vector_lengths_not_equal)
2975 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2979 const HLSLAttributedResourceType *ResTy =
2983 diag::err_typecheck_expect_hlsl_resource)
2987 if (Check && Check(ResTy)) {
2989 diag::err_invalid_hlsl_resource_type)
2999 switch (BuiltinID) {
3000 case Builtin::BI__builtin_hlsl_adduint64: {
3001 if (
SemaRef.checkArgCount(TheCall, 2))
3015 if (NumElementsArg != 2 && NumElementsArg != 4) {
3017 << 1 << 64 << NumElementsArg * 32;
3031 case Builtin::BI__builtin_hlsl_resource_getpointer: {
3032 if (
SemaRef.checkArgCount(TheCall, 2) ||
3035 SemaRef.getASTContext().UnsignedIntTy))
3040 QualType ContainedTy = ResourceTy->getContainedType();
3043 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
3049 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
3050 if (
SemaRef.checkArgCount(TheCall, 1) ||
3058 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
3060 if (
SemaRef.checkArgCount(TheCall, 6) ||
3074 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
3076 if (
SemaRef.checkArgCount(TheCall, 6) ||
3090 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
3092 if (
SemaRef.checkArgCount(TheCall, 3) ||
3099 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3100 auto MainAttrs = MainResType->getAttrs();
3101 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3102 MainAttrs.IsCounter =
true;
3104 MainResType->getWrappedType(), MainResType->getContainedType(),
3106 TheCall->
setType(CounterHandleTy);
3109 case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
3111 if (
SemaRef.checkArgCount(TheCall, 2) ||
3118 case Builtin::BI__builtin_hlsl_resource_getstride: {
3120 if (
SemaRef.checkArgCount(TheCall, 2) ||
3127 case Builtin::BI__builtin_hlsl_and:
3128 case Builtin::BI__builtin_hlsl_or: {
3129 if (
SemaRef.checkArgCount(TheCall, 2))
3142 case Builtin::BI__builtin_hlsl_all:
3143 case Builtin::BI__builtin_hlsl_any: {
3144 if (
SemaRef.checkArgCount(TheCall, 1))
3150 case Builtin::BI__builtin_hlsl_asdouble: {
3151 if (
SemaRef.checkArgCount(TheCall, 2))
3155 SemaRef.Context.UnsignedIntTy,
3160 SemaRef.Context.UnsignedIntTy,
3169 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3170 if (
SemaRef.BuiltinElementwiseTernaryMath(
3176 case Builtin::BI__builtin_hlsl_dot: {
3178 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3184 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3185 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3186 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3196 EltTy = VecTy->getElementType();
3197 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3210 case Builtin::BI__builtin_hlsl_select: {
3211 if (
SemaRef.checkArgCount(TheCall, 3))
3219 if (VTy && VTy->getElementType()->isBooleanType() &&
3224 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3225 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3226 if (
SemaRef.checkArgCount(TheCall, 1))
3232 diag::err_builtin_invalid_arg_type)
3235 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3239 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3240 case Builtin::BI__builtin_hlsl_elementwise_radians:
3241 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3242 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3243 if (
SemaRef.checkArgCount(TheCall, 1))
3248 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3252 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3253 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3254 if (
SemaRef.checkArgCount(TheCall, 1))
3259 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3264 case Builtin::BI__builtin_hlsl_lerp: {
3265 if (
SemaRef.checkArgCount(TheCall, 3))
3272 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3276 case Builtin::BI__builtin_hlsl_mad: {
3277 if (
SemaRef.BuiltinElementwiseTernaryMath(
3283 case Builtin::BI__builtin_hlsl_normalize: {
3284 if (
SemaRef.checkArgCount(TheCall, 1))
3295 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3296 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3304 case Builtin::BI__builtin_hlsl_step: {
3305 if (
SemaRef.checkArgCount(TheCall, 2))
3317 case Builtin::BI__builtin_hlsl_wave_active_max:
3318 case Builtin::BI__builtin_hlsl_wave_active_min:
3319 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3320 if (
SemaRef.checkArgCount(TheCall, 1))
3335 case Builtin::BI__builtin_elementwise_bitreverse: {
3343 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3344 if (
SemaRef.checkArgCount(TheCall, 2))
3352 diag::err_typecheck_convert_incompatible)
3353 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3366 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3367 if (
SemaRef.checkArgCount(TheCall, 0))
3371 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3372 if (
SemaRef.checkArgCount(TheCall, 3))
3387 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3388 if (
SemaRef.checkArgCount(TheCall, 1))
3395 case Builtin::BI__builtin_elementwise_acos:
3396 case Builtin::BI__builtin_elementwise_asin:
3397 case Builtin::BI__builtin_elementwise_atan:
3398 case Builtin::BI__builtin_elementwise_atan2:
3399 case Builtin::BI__builtin_elementwise_ceil:
3400 case Builtin::BI__builtin_elementwise_cos:
3401 case Builtin::BI__builtin_elementwise_cosh:
3402 case Builtin::BI__builtin_elementwise_exp:
3403 case Builtin::BI__builtin_elementwise_exp2:
3404 case Builtin::BI__builtin_elementwise_exp10:
3405 case Builtin::BI__builtin_elementwise_floor:
3406 case Builtin::BI__builtin_elementwise_fmod:
3407 case Builtin::BI__builtin_elementwise_log:
3408 case Builtin::BI__builtin_elementwise_log2:
3409 case Builtin::BI__builtin_elementwise_log10:
3410 case Builtin::BI__builtin_elementwise_pow:
3411 case Builtin::BI__builtin_elementwise_roundeven:
3412 case Builtin::BI__builtin_elementwise_sin:
3413 case Builtin::BI__builtin_elementwise_sinh:
3414 case Builtin::BI__builtin_elementwise_sqrt:
3415 case Builtin::BI__builtin_elementwise_tan:
3416 case Builtin::BI__builtin_elementwise_tanh:
3417 case Builtin::BI__builtin_elementwise_trunc: {
3423 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3424 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3425 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3426 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3428 if (
SemaRef.checkArgCount(TheCall, 2) ||
3431 SemaRef.getASTContext().IntTy))
3434 std::optional<llvm::APSInt> Offset =
3436 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3438 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3444 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
3445 if (
SemaRef.checkArgCount(TheCall, 1))
3456 ArgTy = VTy->getElementType();
3459 diag::err_builtin_invalid_arg_type)
3475 WorkList.push_back(BaseTy);
3476 while (!WorkList.empty()) {
3478 T =
T.getCanonicalType().getUnqualifiedType();
3479 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3487 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3488 llvm::append_range(List, ElementFields);
3493 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3494 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3497 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
3498 List.insert(List.end(), MT->getNumElementsFlattened(),
3499 MT->getElementType());
3502 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3503 if (RD->isStandardLayout())
3504 RD = RD->getStandardLayoutBaseWithFields();
3508 if (RD->
isUnion() || !RD->isAggregate()) {
3514 for (
const auto *FD : RD->
fields())
3515 if (!FD->isUnnamedBitField())
3516 FieldTypes.push_back(FD->
getType());
3518 std::reverse(FieldTypes.begin(), FieldTypes.end());
3519 llvm::append_range(WorkList, FieldTypes);
3523 if (!RD->isStandardLayout()) {
3525 for (
const auto &
Base : RD->bases())
3526 FieldTypes.push_back(
Base.getType());
3527 std::reverse(FieldTypes.begin(), FieldTypes.end());
3528 llvm::append_range(WorkList, FieldTypes);
3550 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3556 int ArraySize = VT->getNumElements();
3561 QualType ElTy = VT->getElementType();
3565 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3581 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3590 return llvm::equal(T1Types, T2Types,
3592 return SemaRef.IsLayoutCompatible(LHS, RHS);
3601 bool HadError =
false;
3603 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3611 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3612 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3613 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3614 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3616 if (NSpellingIdx != OSpellingIdx) {
3618 diag::err_hlsl_param_qualifier_mismatch)
3619 << NDAttr << NewParam;
3635 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3650 llvm_unreachable(
"HLSL doesn't support pointers.");
3653 llvm_unreachable(
"HLSL doesn't support complex types.");
3655 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3657 llvm_unreachable(
"Should have returned before this");
3667 llvm_unreachable(
"HLSL doesn't support complex types.");
3669 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3674 llvm_unreachable(
"HLSL doesn't support pointers.");
3676 llvm_unreachable(
"Should have returned before this");
3682 llvm_unreachable(
"HLSL doesn't support pointers.");
3685 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3689 llvm_unreachable(
"HLSL doesn't support complex types.");
3692 llvm_unreachable(
"Unhandled scalar cast");
3719 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3720 if (DestTypes[I]->isUnionType())
3749 if (SrcTypes.size() < DestTypes.size())
3752 unsigned SrcSize = SrcTypes.size();
3753 unsigned DstSize = DestTypes.size();
3755 for (I = 0; I < DstSize && I < SrcSize; I++) {
3756 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3764 for (; I < SrcSize; I++) {
3765 if (SrcTypes[I]->isUnionType())
3772 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3773 "We should not get here without a parameter modifier expression");
3774 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3781 << Arg << (IsInOut ? 1 : 0);
3787 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3794 << Arg << (IsInOut ? 1 : 0);
3806 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3812 auto *OpV =
new (Ctx)
3817 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3818 tok::equal, ArgOpV, OpV);
3834 "Pointer and reference types cannot be inout or out parameters");
3835 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3845 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3851 if (
Decl->getType().hasAddressSpace())
3854 if (
Decl->getType()->isDependentType())
3886 if (
SemaRef.RequireCompleteType(
3889 diag::err_typecheck_decl_incomplete_type)) {
3903 DefaultCBufferDecls.push_back(VD);
3908 collectResourceBindingsOnVarDecl(VD);
3910 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
3922 processExplicitBindingsOnDecl(VD);
3930 uint32_t OrderID = getNextImplicitBindingOrderID();
3948 uint32_t OrderID = getNextImplicitBindingOrderID();
3958bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3960 "expected resource record type");
3976 const char *CreateMethodName;
3977 if (Binding.isExplicit())
3978 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
3979 :
"__createFromBinding";
3981 CreateMethodName = HasCounter
3982 ?
"__createFromImplicitBindingWithImplicitCounter"
3983 :
"__createFromImplicitBinding";
3994 if (Binding.isExplicit()) {
3998 Args.push_back(RegSlot);
4000 uint32_t OrderID = (Binding.hasImplicitOrderID())
4001 ? Binding.getImplicitOrderID()
4002 : getNextImplicitBindingOrderID();
4006 Args.push_back(OrderId);
4009 IntegerLiteral *Space =
4012 Args.push_back(Space);
4015 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
4016 Args.push_back(RangeSize);
4019 AST, llvm::APInt(UIntTySize, 0), AST.
UnsignedIntTy, SourceLocation());
4020 Args.push_back(Index);
4022 StringRef VarName = VD->
getName();
4029 Name,
nullptr,
VK_PRValue, FPOptionsOverride());
4030 Args.push_back(NameCast);
4034 uint32_t CounterOrderID = getNextImplicitBindingOrderID();
4035 IntegerLiteral *CounterId =
4038 Args.push_back(CounterId);
4049 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod,
false,
4054 CK_FunctionToPointerDecay, DRE,
nullptr,
VK_PRValue, FPOptionsOverride());
4056 CallExpr *InitExpr =
4058 SourceLocation(), FPOptionsOverride());
4061 SemaRef.CheckCompleteVariableDeclaration(VD);
4065bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
4067 "expected array of resource records");
4078 ASTContext &AST =
SemaRef.getASTContext();
4081 CXXMethodDecl *CreateMethod =
nullptr;
4084 ResourceBindingAttrs ResourceAttrs(VD);
4085 if (ResourceAttrs.isExplicit())
4088 lookupMethod(
SemaRef, ResourceDecl,
4089 HasCounter ?
"__createFromBindingWithImplicitCounter"
4090 :
"__createFromBinding",
4094 CreateMethod = lookupMethod(
4096 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
4097 :
"__createFromImplicitBinding",
4122 return initGlobalResourceDecl(VD);
4124 return initGlobalResourceArrayDecl(VD);
4134 "expected LHS to be a resource record or array of resource records");
4135 if (Opc != BO_Assign)
4140 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
4148 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
4159void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
4161 "expected global variable that contains HLSL resource");
4164 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
4165 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
4166 ? ResourceClass::CBuffer
4167 : ResourceClass::SRV);
4180 if (
const HLSLAttributedResourceType *AttrResType =
4181 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4182 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4187 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
4188 collectResourceBindingsOnUserRecordDecl(VD, RT);
4194void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
4197 bool HasBinding =
false;
4198 for (Attr *A : VD->
attrs()) {
4202 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4203 if (!RBA || !RBA->hasRegisterSlot())
4208 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
4209 "never have an attribute created");
4211 if (RT == RegisterType::C) {
4212 if (Bindings.hasBindingInfoForDecl(VD))
4214 diag::warn_hlsl_user_defined_type_missing_member)
4215 <<
static_cast<int>(RT);
4223 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4228 diag::warn_hlsl_user_defined_type_missing_member)
4229 <<
static_cast<int>(RT);
4237class InitListTransformer {
4241 QualType *DstIt =
nullptr;
4242 Expr **ArgIt =
nullptr;
4248 bool castInitializer(Expr *E) {
4249 assert(DstIt &&
"This should always be something!");
4250 if (DstIt == DestTypes.end()) {
4252 ArgExprs.push_back(E);
4257 DstIt = DestTypes.begin();
4260 Ctx, *DstIt,
false);
4265 ArgExprs.push_back(
Init);
4270 bool buildInitializerListImpl(Expr *E) {
4272 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4273 for (
auto *SubInit :
Init->inits())
4274 if (!buildInitializerListImpl(SubInit))
4283 return castInitializer(E);
4285 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4290 for (uint64_t I = 0; I <
Size; ++I) {
4292 SizeTy, SourceLocation());
4298 if (!castInitializer(ElExpr.
get()))
4303 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
4304 unsigned Rows = MTy->getNumRows();
4305 unsigned Cols = MTy->getNumColumns();
4306 QualType ElemTy = MTy->getElementType();
4308 for (
unsigned C = 0;
C < Cols; ++
C) {
4309 for (
unsigned R = 0; R < Rows; ++R) {
4322 if (!castInitializer(ElExpr.
get()))
4330 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4334 for (uint64_t I = 0; I <
Size; ++I) {
4336 SizeTy, SourceLocation());
4341 if (!buildInitializerListImpl(ElExpr.
get()))
4348 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4349 RecordDecls.push_back(RD);
4350 while (RecordDecls.back()->getNumBases()) {
4351 CXXRecordDecl *D = RecordDecls.back();
4353 "HLSL doesn't support multiple inheritance");
4354 RecordDecls.push_back(
4357 while (!RecordDecls.empty()) {
4358 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4359 for (
auto *FD : RD->
fields()) {
4360 if (FD->isUnnamedBitField())
4368 if (!buildInitializerListImpl(Res.
get()))
4376 Expr *generateInitListsImpl(QualType Ty) {
4377 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
4381 llvm::SmallVector<Expr *> Inits;
4387 if (
auto *ATy = Ty->
getAs<VectorType>()) {
4388 ElTy = ATy->getElementType();
4389 Size = ATy->getNumElements();
4390 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
4391 ElTy = CMTy->getElementType();
4392 Size = CMTy->getNumElementsFlattened();
4395 ElTy = VTy->getElementType();
4396 Size = VTy->getZExtSize();
4398 for (uint64_t I = 0; I <
Size; ++I)
4399 Inits.push_back(generateInitListsImpl(ElTy));
4402 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4403 RecordDecls.push_back(RD);
4404 while (RecordDecls.back()->getNumBases()) {
4405 CXXRecordDecl *D = RecordDecls.back();
4407 "HLSL doesn't support multiple inheritance");
4408 RecordDecls.push_back(
4411 while (!RecordDecls.empty()) {
4412 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4413 for (
auto *FD : RD->
fields())
4414 if (!FD->isUnnamedBitField())
4415 Inits.push_back(generateInitListsImpl(FD->
getType()));
4418 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4419 Inits, Inits.back()->getEndLoc());
4420 NewInit->setType(Ty);
4425 llvm::SmallVector<QualType, 16> DestTypes;
4426 llvm::SmallVector<Expr *, 16> ArgExprs;
4427 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4428 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4429 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4430 InitTy = Entity.
getType().getNonReferenceType();
4440 DstIt = DestTypes.begin();
4443 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4445 Expr *generateInitLists() {
4446 assert(!ArgExprs.empty() &&
4447 "Call buildInitializerList to generate argument expressions.");
4448 ArgIt = ArgExprs.begin();
4450 return generateInitListsImpl(InitTy);
4451 llvm::SmallVector<Expr *> Inits;
4452 while (ArgIt != ArgExprs.end())
4453 Inits.push_back(generateInitListsImpl(InitTy));
4455 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4456 Inits, Inits.back()->getEndLoc());
4457 llvm::APInt ArySize(64, Inits.size());
4459 ArraySizeModifier::Normal, 0));
4468 if (
Init->getType()->isScalarType())
4471 InitListTransformer ILT(
SemaRef, Entity);
4473 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4481 Init->setInit(I, E);
4483 if (!ILT.buildInitializerList(E))
4486 size_t ExpectedSize = ILT.DestTypes.size();
4487 size_t ActualSize = ILT.ArgExprs.size();
4488 if (ExpectedSize == 0 && ActualSize == 0)
4497 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4504 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4505 if (ExpectedSize != ActualSize) {
4506 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4507 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4508 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4515 Init->resizeInits(Ctx, NewInit->getNumInits());
4516 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4517 Init->updateInit(Ctx, I, NewInit->getInit(I));
4522 const HLSLVkConstantIdAttr *ConstIdAttr =
4523 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4530 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4540 int ConstantID = ConstIdAttr->getId();
4541 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4543 ConstIdAttr->getLocation());
4547 if (
C->getType()->getCanonicalTypeUnqualified() !=
4551 Context.getTrivialTypeSourceInfo(
4552 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 CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
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)
return(__x > > __y)|(__x<<(32 - __y))
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.
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)
T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)
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)
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)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ 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.
for(const auto &A :T->param_types())
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