15#include "clang/AST/Attrs.inc"
36#include "llvm/ADT/ArrayRef.h"
37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/SmallVector.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/ADT/StringRef.h"
41#include "llvm/ADT/Twine.h"
42#include "llvm/Frontend/HLSL/HLSLBinding.h"
43#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
44#include "llvm/Support/Casting.h"
45#include "llvm/Support/DXILABI.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/FormatVariadic.h"
48#include "llvm/TargetParser/Triple.h"
62 case ResourceClass::SRV:
63 return RegisterType::SRV;
64 case ResourceClass::UAV:
65 return RegisterType::UAV;
66 case ResourceClass::CBuffer:
67 return RegisterType::CBuffer;
68 case ResourceClass::Sampler:
69 return RegisterType::Sampler;
71 llvm_unreachable(
"unexpected ResourceClass value");
81 assert(RT !=
nullptr);
85 *RT = RegisterType::SRV;
89 *RT = RegisterType::UAV;
93 *RT = RegisterType::CBuffer;
97 *RT = RegisterType::Sampler;
101 *RT = RegisterType::C;
105 *RT = RegisterType::I;
114 case RegisterType::SRV:
115 return ResourceClass::SRV;
116 case RegisterType::UAV:
117 return ResourceClass::UAV;
118 case RegisterType::CBuffer:
119 return ResourceClass::CBuffer;
120 case RegisterType::Sampler:
121 return ResourceClass::Sampler;
122 case RegisterType::C:
123 case RegisterType::I:
127 llvm_unreachable(
"unexpected RegisterType value");
131 const auto *BT = dyn_cast<BuiltinType>(
Type);
135 return Builtin::BI__builtin_get_spirv_spec_constant_int;
138 switch (BT->getKind()) {
139 case BuiltinType::Bool:
140 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
141 case BuiltinType::Short:
142 return Builtin::BI__builtin_get_spirv_spec_constant_short;
143 case BuiltinType::Int:
144 return Builtin::BI__builtin_get_spirv_spec_constant_int;
145 case BuiltinType::LongLong:
146 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
147 case BuiltinType::UShort:
148 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
149 case BuiltinType::UInt:
150 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
151 case BuiltinType::ULongLong:
152 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
153 case BuiltinType::Half:
154 return Builtin::BI__builtin_get_spirv_spec_constant_half;
155 case BuiltinType::Float:
156 return Builtin::BI__builtin_get_spirv_spec_constant_float;
157 case BuiltinType::Double:
158 return Builtin::BI__builtin_get_spirv_spec_constant_double;
165 ResourceClass ResClass) {
167 "DeclBindingInfo already added");
173 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
174 return &BindingsList.emplace_back(VD, ResClass);
178 ResourceClass ResClass) {
179 auto Entry = DeclToBindingListIndex.find(VD);
180 if (Entry != DeclToBindingListIndex.end()) {
181 for (
unsigned Index = Entry->getSecond();
182 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
184 if (BindingsList[Index].ResClass == ResClass)
185 return &BindingsList[Index];
192 return DeclToBindingListIndex.contains(VD);
204 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
207 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
208 : llvm::hlsl::ResourceClass::SRV;
220 if (
T->isArrayType() ||
T->isStructureType())
227 assert(Context.getTypeSize(
T) <= 64 &&
228 "Scalar bit widths larger than 64 not supported");
231 return Context.getTypeSize(
T) / 8;
238 constexpr unsigned CBufferAlign = 16;
239 if (
const auto *RD =
T->getAsRecordDecl()) {
241 for (
const FieldDecl *Field : RD->fields()) {
248 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
249 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
250 FieldAlign = CBufferAlign;
253 Size = llvm::alignTo(Size, FieldAlign);
260 unsigned ElementCount = AT->getSize().getZExtValue();
261 if (ElementCount == 0)
264 unsigned ElementSize =
266 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
267 return AlignedElementSize * (ElementCount - 1) + ElementSize;
271 unsigned ElementCount = VT->getNumElements();
272 unsigned ElementSize =
274 return ElementSize * ElementCount;
277 return Context.getTypeSize(
T) / 8;
288 bool HasPackOffset =
false;
289 bool HasNonPackOffset =
false;
291 VarDecl *Var = dyn_cast<VarDecl>(Field);
294 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
295 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
296 HasPackOffset =
true;
298 HasNonPackOffset =
true;
305 if (HasNonPackOffset)
312 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
313 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
314 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
315 return LHS.second->getOffsetInBytes() <
316 RHS.second->getOffsetInBytes();
318 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
319 VarDecl *Var = PackOffsetVec[i].first;
320 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
322 unsigned Begin =
Attr->getOffsetInBytes();
323 unsigned End = Begin + Size;
324 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
325 if (End > NextBegin) {
326 VarDecl *NextVar = PackOffsetVec[i + 1].first;
338 CAT = dyn_cast<ConstantArrayType>(
340 return CAT !=
nullptr;
348static const HLSLAttributedResourceType *
351 "expected array of resource records");
353 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
355 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
367 return RD->isEmpty();
396 Base.getType()->castAsCXXRecordDecl()))
407 assert(RD ==
nullptr &&
408 "there should be at most 1 record by a given name in a scope");
425 Name.append(NameBaseII->
getName());
432 size_t NameLength = Name.size();
441 Name.append(llvm::Twine(suffix).str());
442 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
449 Name.truncate(NameLength);
490 "struct is already HLSL buffer compatible");
504 LS->
addAttr(PackedAttr::CreateImplicit(AST));
508 if (
unsigned NumBases = StructDecl->
getNumBases()) {
509 assert(NumBases == 1 &&
"HLSL supports only one base type");
559 LS->
addAttr(PackedAttr::CreateImplicit(AST));
564 VarDecl *VD = dyn_cast<VarDecl>(D);
584 uint32_t ImplicitBindingOrderID) {
586 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
587 Attr->setBinding(RT, std::nullopt, 0);
588 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
595 BufDecl->setRBraceLoc(RBrace);
602 HLSLVkBindingAttr *VkBinding = Dcl->
getAttr<HLSLVkBindingAttr>();
603 HLSLResourceBindingAttr *RBA = Dcl->
getAttr<HLSLResourceBindingAttr>();
604 if (!VkBinding && (!RBA || !RBA->hasRegisterSlot())) {
608 uint32_t OrderID = getNextImplicitBindingOrderID();
610 RBA->setImplicitBindingOrderID(OrderID);
613 BufDecl->isCBuffer() ? RegisterType::CBuffer
623 int X,
int Y,
int Z) {
624 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
625 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
626 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
627 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
637 int Min,
int Max,
int Preferred,
638 int SpelledArgsCount) {
639 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
640 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
641 WS->getPreferred() != Preferred ||
642 WS->getSpelledArgsCount() != SpelledArgsCount) {
643 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
644 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
650 Result->setSpelledArgsCount(SpelledArgsCount);
654HLSLVkConstantIdAttr *
660 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
668 Diag(VD->getLocation(), diag::err_specialization_const);
672 if (!VD->getType().isConstQualified()) {
673 Diag(VD->getLocation(), diag::err_specialization_const);
677 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
678 if (CI->getId() != Id) {
679 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
680 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
685 HLSLVkConstantIdAttr *
Result =
692 llvm::Triple::EnvironmentType ShaderType) {
693 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
694 if (NT->getType() != ShaderType) {
695 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
696 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
700 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
703HLSLParamModifierAttr *
705 HLSLParamModifierAttr::Spelling Spelling) {
708 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
709 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
710 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
711 D->
dropAttr<HLSLParamModifierAttr>();
713 return HLSLParamModifierAttr::Create(
715 HLSLParamModifierAttr::Keyword_inout);
717 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
718 Diag(PA->getLocation(), diag::note_conflicting_attribute);
744 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
745 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
748 if (Shader->getType() != Env) {
749 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
761 case llvm::Triple::UnknownEnvironment:
762 case llvm::Triple::Library:
764 case llvm::Triple::RootSignature:
765 llvm_unreachable(
"rootsig environment has no functions");
767 llvm_unreachable(
"Unhandled environment in triple");
774 if (AnnotationAttr) {
780 const RecordType *RT = dyn_cast<RecordType>(
T);
793 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
794 assert(ShaderAttr &&
"Entry point has no shader attribute");
795 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
799 case llvm::Triple::Pixel:
800 case llvm::Triple::Vertex:
801 case llvm::Triple::Geometry:
802 case llvm::Triple::Hull:
803 case llvm::Triple::Domain:
804 case llvm::Triple::RayGeneration:
805 case llvm::Triple::Intersection:
806 case llvm::Triple::AnyHit:
807 case llvm::Triple::ClosestHit:
808 case llvm::Triple::Miss:
809 case llvm::Triple::Callable:
810 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
812 {llvm::Triple::Compute,
813 llvm::Triple::Amplification,
814 llvm::Triple::Mesh});
817 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
819 {llvm::Triple::Compute,
820 llvm::Triple::Amplification,
821 llvm::Triple::Mesh});
826 case llvm::Triple::Compute:
827 case llvm::Triple::Amplification:
828 case llvm::Triple::Mesh:
829 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
831 << llvm::Triple::getEnvironmentTypeName(ST);
834 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
835 if (Ver < VersionTuple(6, 6)) {
836 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
839 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
842 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
843 << WS << WS->getSpelledArgsCount() <<
"6.8";
848 case llvm::Triple::RootSignature:
849 llvm_unreachable(
"rootsig environment has no function entry point");
851 llvm_unreachable(
"Unhandled environment in triple");
857 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
867 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
868 assert(ShaderAttr &&
"Entry point has no shader attribute");
869 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
871 switch (AnnotationAttr->
getKind()) {
872 case attr::HLSLSV_DispatchThreadID:
873 case attr::HLSLSV_GroupIndex:
874 case attr::HLSLSV_GroupThreadID:
875 case attr::HLSLSV_GroupID:
876 if (ST == llvm::Triple::Compute)
880 case attr::HLSLSV_Position:
883 if (ST == llvm::Triple::Pixel)
888 llvm_unreachable(
"Unknown HLSLAnnotationAttr");
893 const Attr *A, llvm::Triple::EnvironmentType Stage,
894 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
896 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
897 [](llvm::Triple::EnvironmentType ST) {
899 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
901 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
902 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
903 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
906template <CastKind Kind>
909 Ty = VTy->getElementType();
914template <CastKind Kind>
926 if (LHSFloat && RHSFloat) {
954 if (LHSSigned == RHSSigned) {
955 if (IsCompAssign || IntOrder >= 0)
963 if (IntOrder != (LHSSigned ? 1 : -1)) {
964 if (IsCompAssign || RHSSigned)
972 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
973 if (IsCompAssign || LHSSigned)
989 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
990 QualType NewTy = Ctx.getExtVectorType(
1000 return CK_FloatingCast;
1002 return CK_IntegralCast;
1004 return CK_IntegralToFloating;
1006 return CK_FloatingToIntegral;
1012 bool IsCompAssign) {
1019 if (!LVecTy && IsCompAssign) {
1021 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1023 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1025 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1030 unsigned EndSz = std::numeric_limits<unsigned>::max();
1033 LSz = EndSz = LVecTy->getNumElements();
1036 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1037 "one of the above should have had a value");
1041 if (IsCompAssign && LSz != EndSz) {
1043 diag::err_hlsl_vector_compound_assignment_truncation)
1044 << LHSType << RHSType;
1050 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1055 if (!IsCompAssign && !LVecTy)
1059 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1060 return Ctx.getCommonSugaredType(LHSType, RHSType);
1068 LElTy, RElTy, IsCompAssign);
1071 "HLSL Vectors can only contain integer or floating point types");
1073 LElTy, RElTy, IsCompAssign);
1078 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1079 "Called with non-logical operator");
1081 llvm::raw_svector_ostream OS(Buff);
1083 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1084 OS << NewFnName <<
"(";
1094std::pair<IdentifierInfo *, bool>
1097 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1104 return {DeclIdent,
Found};
1115 for (
auto &RootSigElement : RootElements)
1116 Elements.push_back(RootSigElement.getElement());
1120 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1122 SignatureDecl->setImplicit();
1128 if (RootSigOverrideIdent) {
1131 if (
SemaRef.LookupQualifiedName(R, DC))
1132 return dyn_cast<HLSLRootSignatureDecl>(R.
getFoundDecl());
1140struct PerVisibilityBindingChecker {
1143 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1147 llvm::dxbc::ShaderVisibility Vis;
1152 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1154 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1155 llvm::dxil::ResourceClass RC, uint32_t Space,
1156 uint32_t LowerBound, uint32_t UpperBound,
1157 const hlsl::RootSignatureElement *Elem) {
1159 assert(BuilderIndex < Builders.size() &&
1160 "Not enough builders for visibility type");
1161 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1162 static_cast<const void *
>(Elem));
1164 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1165 "'All' visibility must come first");
1166 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1167 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1168 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1169 static_cast<const void *
>(Elem));
1171 ElemInfoMap.push_back({Elem,
Visibility,
false});
1174 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1175 auto It = llvm::lower_bound(
1177 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1178 assert(It->Elem == Elem &&
"Element not in map");
1182 bool checkOverlap() {
1183 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1184 return LHS.Elem < RHS.Elem;
1187 bool HadOverlap =
false;
1189 using llvm::hlsl::BindingInfoBuilder;
1190 auto ReportOverlap = [
this,
1191 &HadOverlap](
const BindingInfoBuilder &Builder,
1192 const llvm::hlsl::Binding &Reported) {
1196 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1197 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1198 const auto *PrevElem =
1199 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1201 ElemInfo &Info =
getInfo(Elem);
1206 Info.Diagnosed =
true;
1208 ElemInfo &PrevInfo =
getInfo(PrevElem);
1209 llvm::dxbc::ShaderVisibility CommonVis =
1210 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1213 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1214 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1215 << Reported.isUnbounded() << Reported.UpperBound
1220 this->S->
Diag(PrevElem->getLocation(),
1221 diag::note_hlsl_resource_range_here);
1224 for (BindingInfoBuilder &Builder : Builders)
1225 Builder.calculateBindingInfo(ReportOverlap);
1245 bool HadError =
false;
1246 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1247 uint32_t UpperBound) {
1249 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1250 << LowerBound << UpperBound;
1257 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1258 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1259 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1262 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1263 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1264 ReportError(Loc, 0, 0xfffffffe);
1267 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1268 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1269 ReportError(Loc, 0, 0xffffffef);
1272 const uint32_t Version =
1273 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1274 const uint32_t VersionEnum = Version - 1;
1275 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1277 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1284 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1285 if (
const auto *Descriptor =
1286 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1287 VerifyRegister(Loc, Descriptor->Reg.Number);
1288 VerifySpace(Loc, Descriptor->Space);
1290 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(
1291 Version, llvm::to_underlying(Descriptor->Flags)))
1292 ReportFlagError(Loc);
1293 }
else if (
const auto *Constants =
1294 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1295 VerifyRegister(Loc, Constants->Reg.Number);
1296 VerifySpace(Loc, Constants->Space);
1297 }
else if (
const auto *Sampler =
1298 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1299 VerifyRegister(Loc, Sampler->Reg.Number);
1300 VerifySpace(Loc, Sampler->Space);
1303 "By construction, parseFloatParam can't produce a NaN from a "
1304 "float_literal token");
1306 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1307 ReportError(Loc, 0, 16);
1308 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1309 ReportFloatError(Loc, -16.f, 15.99f);
1310 }
else if (
const auto *Clause =
1311 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1313 VerifyRegister(Loc, Clause->Reg.Number);
1314 VerifySpace(Loc, Clause->Space);
1316 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1320 ReportError(Loc, 1, 0xfffffffe);
1323 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1325 ReportFlagError(Loc);
1329 PerVisibilityBindingChecker BindingChecker(
this);
1330 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1335 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1336 if (
const auto *Descriptor =
1337 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1338 uint32_t LowerBound(Descriptor->Reg.Number);
1339 uint32_t UpperBound(LowerBound);
1341 BindingChecker.trackBinding(
1342 Descriptor->Visibility,
1343 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1344 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1345 }
else if (
const auto *Constants =
1346 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1347 uint32_t LowerBound(Constants->Reg.Number);
1348 uint32_t UpperBound(LowerBound);
1350 BindingChecker.trackBinding(
1351 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1352 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1353 }
else if (
const auto *Sampler =
1354 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1355 uint32_t LowerBound(Sampler->Reg.Number);
1356 uint32_t UpperBound(LowerBound);
1358 BindingChecker.trackBinding(
1359 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1360 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1361 }
else if (
const auto *Clause =
1362 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1365 UnboundClauses.emplace_back(Clause, &RootSigElem);
1366 }
else if (
const auto *Table =
1367 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1368 assert(UnboundClauses.size() == Table->NumClauses &&
1369 "Number of unbound elements must match the number of clauses");
1370 bool HasAnySampler =
false;
1371 bool HasAnyNonSampler =
false;
1372 uint64_t Offset = 0;
1373 bool IsPrevUnbound =
false;
1374 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1376 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1377 HasAnySampler =
true;
1379 HasAnyNonSampler =
true;
1381 if (HasAnySampler && HasAnyNonSampler)
1382 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1387 if (Clause->NumDescriptors == 0)
1391 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1393 Offset = Clause->Offset;
1395 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1396 Offset, Clause->NumDescriptors);
1398 if (IsPrevUnbound && IsAppending)
1399 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1400 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1401 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1404 Offset = RangeBound + 1;
1405 IsPrevUnbound = Clause->NumDescriptors ==
1406 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1409 uint32_t LowerBound(Clause->Reg.Number);
1410 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1411 LowerBound, Clause->NumDescriptors);
1413 BindingChecker.trackBinding(
1415 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1416 LowerBound, UpperBound, ClauseElem);
1418 UnboundClauses.clear();
1422 return BindingChecker.checkOverlap();
1427 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1432 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1433 if (RS->getSignatureIdent() != Ident) {
1434 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1438 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1444 if (
auto *SignatureDecl =
1452 llvm::VersionTuple SMVersion =
1457 uint32_t ZMax = 1024;
1458 uint32_t ThreadMax = 1024;
1459 if (IsDXIL && SMVersion.getMajor() <= 4) {
1462 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1472 diag::err_hlsl_numthreads_argument_oor)
1481 diag::err_hlsl_numthreads_argument_oor)
1490 diag::err_hlsl_numthreads_argument_oor)
1495 if (
X * Y * Z > ThreadMax) {
1496 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1513 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1521 if (SpelledArgsCount > 1 &&
1525 uint32_t Preferred = 0;
1526 if (SpelledArgsCount > 2 &&
1530 if (SpelledArgsCount > 2) {
1533 diag::err_attribute_power_of_two_in_range)
1534 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1539 if (Preferred < Min || Preferred >
Max) {
1541 diag::err_attribute_power_of_two_in_range)
1542 << AL <<
Min <<
Max << Preferred;
1545 }
else if (SpelledArgsCount > 1) {
1548 diag::err_attribute_power_of_two_in_range)
1549 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1553 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1556 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1561 diag::err_attribute_power_of_two_in_range)
1562 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1567 HLSLWaveSizeAttr *NewAttr =
1595 uint32_t Binding = 0;
1610 if (!
T->hasUnsignedIntegerRepresentation() ||
1611 (VT && VT->getNumElements() > 3)) {
1612 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1613 << AL <<
"uint/uint2/uint3";
1622 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1623 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1624 << AL <<
"float/float1/float2/float3/float4";
1632 std::optional<unsigned> Index) {
1636 QualType ValueType = VD->getType();
1637 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1638 ValueType = FD->getReturnType();
1640 bool IsOutput =
false;
1641 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1648 Attr *Attribute =
nullptr;
1649 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1652 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1654 }
else if (SemanticName ==
"SV_GROUPINDEX") {
1656 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1658 }
else if (SemanticName ==
"SV_GROUPTHREADID") {
1661 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1663 }
else if (SemanticName ==
"SV_GROUPID") {
1666 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1668 }
else if (SemanticName ==
"SV_POSITION") {
1669 const auto *VT = ValueType->getAs<
VectorType>();
1670 if (!ValueType->hasFloatingRepresentation() ||
1671 (VT && VT->getNumElements() > 4))
1672 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1673 << AL <<
"float/float1/float2/float3/float4";
1676 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1684 uint32_t IndexValue, ExplicitIndex;
1687 assert(IndexValue > 0 ? ExplicitIndex :
true);
1688 std::optional<unsigned> Index =
1689 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1694 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1699 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1700 << AL <<
"shader constant in a constant buffer";
1704 uint32_t SubComponent;
1714 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1719 if (IsAggregateTy || Size > 128) {
1720 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1724 if ((Component * 32 + Size) > 128) {
1725 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1730 EltTy = VT->getElementType();
1732 if (Align > 32 && Component == 1) {
1735 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1749 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1752 llvm::Triple::EnvironmentType ShaderType;
1753 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1754 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1755 << AL << Str << ArgLoc;
1769 assert(AttrList.size() &&
"expected list of resource attributes");
1776 HLSLAttributedResourceType::Attributes ResAttrs;
1778 bool HasResourceClass =
false;
1779 for (
const Attr *A : AttrList) {
1782 LocEnd = A->getRange().getEnd();
1783 switch (A->getKind()) {
1784 case attr::HLSLResourceClass: {
1786 if (HasResourceClass) {
1787 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1788 ? diag::warn_duplicate_attribute_exact
1789 : diag::warn_duplicate_attribute)
1793 ResAttrs.ResourceClass = RC;
1794 HasResourceClass =
true;
1798 if (ResAttrs.IsROV) {
1799 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1802 ResAttrs.IsROV =
true;
1804 case attr::HLSLRawBuffer:
1805 if (ResAttrs.RawBuffer) {
1806 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1809 ResAttrs.RawBuffer =
true;
1811 case attr::HLSLContainedType: {
1814 if (!ContainedTy.
isNull()) {
1815 S.
Diag(A->getLocation(), ContainedTy == Ty
1816 ? diag::warn_duplicate_attribute_exact
1817 : diag::warn_duplicate_attribute)
1826 llvm_unreachable(
"unhandled resource attribute type");
1830 if (!HasResourceClass) {
1831 S.
Diag(AttrList.back()->getRange().getEnd(),
1832 diag::err_hlsl_missing_resource_class);
1837 Wrapped, ContainedTy, ResAttrs);
1839 if (LocInfo && ContainedTyInfo) {
1852 if (!
T->isHLSLResourceType()) {
1853 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1868 AttributeCommonInfo::AS_CXX11, 0, false ,
1873 case ParsedAttr::AT_HLSLResourceClass: {
1875 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1886 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1887 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1888 <<
"ResourceClass" << Identifier;
1891 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
1895 case ParsedAttr::AT_HLSLROV:
1899 case ParsedAttr::AT_HLSLRawBuffer:
1903 case ParsedAttr::AT_HLSLContainedType: {
1905 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1911 assert(TSI &&
"no type source info for attribute argument");
1913 diag::err_incomplete_type))
1915 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
1920 llvm_unreachable(
"unhandled HLSL attribute");
1923 HLSLResourcesTypeAttrs.emplace_back(A);
1929 if (!HLSLResourcesTypeAttrs.size())
1935 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1936 const HLSLAttributedResourceType *RT =
1943 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1945 HLSLResourcesTypeAttrs.clear();
1953 auto I = LocsForHLSLAttributedResources.find(RT);
1954 if (I != LocsForHLSLAttributedResources.end()) {
1955 LocInfo = I->second;
1956 LocsForHLSLAttributedResources.erase(I);
1965void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
1966 const RecordType *RT) {
1967 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1974 "incomplete arrays inside user defined types are not supported");
1983 if (
const HLSLAttributedResourceType *AttrResType =
1984 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
1989 Bindings.addDeclBindingInfo(VD, RC);
1990 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1996 collectResourceBindingsOnUserRecordDecl(VD, RT);
2008 bool SpecifiedSpace) {
2009 int RegTypeNum =
static_cast<int>(RegType);
2012 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2013 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2018 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2019 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2020 : ResourceClass::SRV;
2030 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2034 if (
const HLSLAttributedResourceType *AttrResType =
2035 HLSLAttributedResourceType::findHandleTypeOnResource(
2052 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2053 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2058 if (RegType == RegisterType::CBuffer)
2059 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2060 else if (RegType != RegisterType::C)
2061 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2065 if (RegType == RegisterType::C)
2066 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2068 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2078 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2086 bool RegisterTypesDetected[5] = {
false};
2087 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2090 if (HLSLResourceBindingAttr *
attr =
2091 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2094 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2095 int otherRegTypeNum =
static_cast<int>(otherRegType);
2097 diag::err_hlsl_duplicate_register_annotation)
2101 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2109 bool SpecifiedSpace) {
2114 "expecting VarDecl or HLSLBufferDecl");
2125 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2127 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2128 Ty = IAT->getElementType();
2130 diag::err_incomplete_type))
2134 StringRef Slot =
"";
2135 StringRef Space =
"";
2139 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2149 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2155 SpaceLoc = Loc->
getLoc();
2158 if (Str.starts_with(
"space")) {
2160 SpaceLoc = Loc->
getLoc();
2169 std::optional<unsigned> SlotNum;
2170 unsigned SpaceNum = 0;
2173 if (!Slot.empty()) {
2175 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2178 if (RegType == RegisterType::I) {
2179 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2182 StringRef SlotNumStr = Slot.substr(1);
2184 if (SlotNumStr.getAsInteger(10, N)) {
2185 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2192 if (!Space.starts_with(
"space")) {
2193 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2196 StringRef SpaceNumStr = Space.substr(5);
2197 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2198 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2203 if (SlotNum.has_value())
2208 HLSLResourceBindingAttr *NewAttr =
2209 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2211 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2266 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2270 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2271 unsigned CurrentShaderStageBit;
2276 bool ReportOnlyShaderStageIssues;
2279 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2280 static_assert(
sizeof(
unsigned) >= 4);
2281 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2282 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2283 "ShaderType is too big for this bitmap");
2286 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2287 CurrentShaderEnvironment = ShaderType;
2288 CurrentShaderStageBit = (1 << bitmapIndex);
2291 void SetUnknownShaderStageContext() {
2292 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2293 CurrentShaderStageBit = (1 << 31);
2296 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2297 return CurrentShaderEnvironment;
2300 bool InUnknownShaderStageContext()
const {
2301 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2305 void AddToScannedFunctions(
const FunctionDecl *FD) {
2306 unsigned &ScannedStages = ScannedDecls[FD];
2307 ScannedStages |= CurrentShaderStageBit;
2310 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2312 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2313 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2316 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2317 return ScannerStages & CurrentShaderStageBit;
2320 static bool NeverBeenScanned(
unsigned ScannedStages) {
2321 return ScannedStages == 0;
2325 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2326 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2328 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2329 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2332 DiagnoseHLSLAvailability(Sema &SemaRef)
2334 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2335 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2338 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2339 void RunOnFunction(
const FunctionDecl *FD);
2341 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2342 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2344 HandleFunctionOrMethodRef(FD, DRE);
2348 bool VisitMemberExpr(MemberExpr *ME)
override {
2349 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2351 HandleFunctionOrMethodRef(FD, ME);
2356void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2359 "expected DeclRefExpr or MemberExpr");
2363 if (FD->
hasBody(FDWithBody)) {
2364 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2365 DeclsToScan.push_back(FDWithBody);
2370 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2372 CheckDeclAvailability(
2376void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2385 DeclContextsToScan.push_back(TU);
2387 while (!DeclContextsToScan.empty()) {
2388 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2389 for (
auto &D : DC->
decls()) {
2391 if (D->isImplicit())
2396 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2397 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2402 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2407 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2408 SetShaderStageContext(ShaderAttr->getType());
2417 for (
const auto *Redecl : FD->
redecls()) {
2418 if (Redecl->isInExportDeclContext()) {
2425 SetUnknownShaderStageContext();
2433void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2434 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2435 DeclsToScan.push_back(FD);
2437 while (!DeclsToScan.empty()) {
2445 const unsigned ScannedStages = GetScannedStages(FD);
2446 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2449 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2451 AddToScannedFunctions(FD);
2456bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2457 const AvailabilityAttr *AA) {
2462 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2463 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2466 llvm::Triple::EnvironmentType AttrEnv =
2467 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2469 return CurrentEnv == AttrEnv;
2472const AvailabilityAttr *
2473DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2474 AvailabilityAttr
const *PartialMatch =
nullptr;
2478 for (
const auto *A : D->
attrs()) {
2479 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2480 StringRef AttrPlatform = Avail->getPlatform()->getName();
2481 StringRef TargetPlatform =
2485 if (AttrPlatform == TargetPlatform) {
2487 if (HasMatchingEnvironmentOrNone(Avail))
2489 PartialMatch = Avail;
2493 return PartialMatch;
2498void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2499 const AvailabilityAttr *AA,
2518 if (ReportOnlyShaderStageIssues)
2524 if (InUnknownShaderStageContext())
2529 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2530 VersionTuple Introduced = AA->getIntroduced();
2539 llvm::StringRef PlatformName(
2542 llvm::StringRef CurrentEnvStr =
2543 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2545 llvm::StringRef AttrEnvStr =
2546 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2547 bool UseEnvironment = !AttrEnvStr.empty();
2549 if (EnvironmentMatches) {
2550 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2551 <<
Range << D << PlatformName << Introduced.getAsString()
2552 << UseEnvironment << CurrentEnvStr;
2554 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2558 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2559 << D << PlatformName << Introduced.getAsString()
2561 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2568 if (!DefaultCBufferDecls.empty()) {
2571 DefaultCBufferDecls);
2573 getNextImplicitBindingOrderID());
2574 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2578 for (
const Decl *VD : DefaultCBufferDecls) {
2579 const HLSLResourceBindingAttr *RBA =
2580 VD->
getAttr<HLSLResourceBindingAttr>();
2581 if (RBA && RBA->hasRegisterSlot() &&
2582 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2589 SemaRef.Consumer.HandleTopLevelDecl(DG);
2591 diagnoseAvailabilityViolations(TU);
2601 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2604 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2611 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2614 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2639 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2654 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2655 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2656 << ArgOrdinal << 5 << 0
2662 unsigned ArgIndex) {
2663 auto *Arg = TheCall->
getArg(ArgIndex);
2665 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2668 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2678 if (VecTy->getElementType()->isDoubleType())
2679 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2680 << ArgOrdinal << 1 << 0 << 1
2690 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2691 << ArgOrdinal << 5 << 1
2700 if (VecTy->getElementType()->isUnsignedIntegerType())
2703 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2704 << ArgOrdinal << 4 << 3 << 0
2713 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2714 << ArgOrdinal << 5 << 3
2730 unsigned ArgIndex) {
2739 diag::err_typecheck_expect_scalar_or_vector)
2740 << ArgType << Scalar;
2747 unsigned ArgIndex) {
2752 if (!(ArgType->isScalarType() ||
2753 (VTy && VTy->getElementType()->isScalarType()))) {
2755 diag::err_typecheck_expect_any_scalar_or_vector)
2772 diag::err_typecheck_expect_any_scalar_or_vector)
2785 diag::err_typecheck_call_different_arg_types)
2804 Arg1ScalarTy = VTy->getElementType();
2808 Arg2ScalarTy = VTy->getElementType();
2811 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2812 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2822 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2824 diag::err_typecheck_vector_lengths_not_equal)
2830 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2832 diag::err_typecheck_vector_lengths_not_equal)
2845 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2849 const HLSLAttributedResourceType *ResTy =
2853 diag::err_typecheck_expect_hlsl_resource)
2857 if (Check && Check(ResTy)) {
2859 diag::err_invalid_hlsl_resource_type)
2869 switch (BuiltinID) {
2870 case Builtin::BI__builtin_hlsl_adduint64: {
2871 if (
SemaRef.checkArgCount(TheCall, 2))
2884 if (ElementBitCount != 32) {
2886 diag::err_integer_incorrect_bit_count)
2887 << 32 << ElementBitCount;
2892 int NumElementsArg = VTy->getNumElements();
2893 if (NumElementsArg != 2 && NumElementsArg != 4) {
2895 << 1 << 64 << NumElementsArg * ElementBitCount;
2909 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2910 if (
SemaRef.checkArgCount(TheCall, 2) ||
2913 SemaRef.getASTContext().UnsignedIntTy))
2918 QualType ContainedTy = ResourceTy->getContainedType();
2921 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
2927 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2928 if (
SemaRef.checkArgCount(TheCall, 1) ||
2936 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2938 if (
SemaRef.checkArgCount(TheCall, 6) ||
2952 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2954 if (
SemaRef.checkArgCount(TheCall, 6) ||
2968 case Builtin::BI__builtin_hlsl_and:
2969 case Builtin::BI__builtin_hlsl_or: {
2970 if (
SemaRef.checkArgCount(TheCall, 2))
2983 case Builtin::BI__builtin_hlsl_all:
2984 case Builtin::BI__builtin_hlsl_any: {
2985 if (
SemaRef.checkArgCount(TheCall, 1))
2991 case Builtin::BI__builtin_hlsl_asdouble: {
2992 if (
SemaRef.checkArgCount(TheCall, 2))
2996 SemaRef.Context.UnsignedIntTy,
3001 SemaRef.Context.UnsignedIntTy,
3010 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3011 if (
SemaRef.BuiltinElementwiseTernaryMath(
3017 case Builtin::BI__builtin_hlsl_dot: {
3019 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3025 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3026 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3027 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3037 EltTy = VecTy->getElementType();
3038 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3051 case Builtin::BI__builtin_hlsl_select: {
3052 if (
SemaRef.checkArgCount(TheCall, 3))
3060 if (VTy && VTy->getElementType()->isBooleanType() &&
3065 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3066 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3067 if (
SemaRef.checkArgCount(TheCall, 1))
3073 diag::err_builtin_invalid_arg_type)
3076 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3080 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3081 case Builtin::BI__builtin_hlsl_elementwise_radians:
3082 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3083 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3084 if (
SemaRef.checkArgCount(TheCall, 1))
3089 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3093 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3094 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3095 if (
SemaRef.checkArgCount(TheCall, 1))
3100 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3105 case Builtin::BI__builtin_hlsl_lerp: {
3106 if (
SemaRef.checkArgCount(TheCall, 3))
3113 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3117 case Builtin::BI__builtin_hlsl_mad: {
3118 if (
SemaRef.BuiltinElementwiseTernaryMath(
3124 case Builtin::BI__builtin_hlsl_normalize: {
3125 if (
SemaRef.checkArgCount(TheCall, 1))
3136 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3137 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3145 case Builtin::BI__builtin_hlsl_step: {
3146 if (
SemaRef.checkArgCount(TheCall, 2))
3158 case Builtin::BI__builtin_hlsl_wave_active_max:
3159 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3160 if (
SemaRef.checkArgCount(TheCall, 1))
3175 case Builtin::BI__builtin_elementwise_bitreverse: {
3183 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3184 if (
SemaRef.checkArgCount(TheCall, 2))
3192 diag::err_typecheck_convert_incompatible)
3193 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3206 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3207 if (
SemaRef.checkArgCount(TheCall, 0))
3211 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3212 if (
SemaRef.checkArgCount(TheCall, 3))
3227 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3228 if (
SemaRef.checkArgCount(TheCall, 1))
3235 case Builtin::BI__builtin_elementwise_acos:
3236 case Builtin::BI__builtin_elementwise_asin:
3237 case Builtin::BI__builtin_elementwise_atan:
3238 case Builtin::BI__builtin_elementwise_atan2:
3239 case Builtin::BI__builtin_elementwise_ceil:
3240 case Builtin::BI__builtin_elementwise_cos:
3241 case Builtin::BI__builtin_elementwise_cosh:
3242 case Builtin::BI__builtin_elementwise_exp:
3243 case Builtin::BI__builtin_elementwise_exp2:
3244 case Builtin::BI__builtin_elementwise_exp10:
3245 case Builtin::BI__builtin_elementwise_floor:
3246 case Builtin::BI__builtin_elementwise_fmod:
3247 case Builtin::BI__builtin_elementwise_log:
3248 case Builtin::BI__builtin_elementwise_log2:
3249 case Builtin::BI__builtin_elementwise_log10:
3250 case Builtin::BI__builtin_elementwise_pow:
3251 case Builtin::BI__builtin_elementwise_roundeven:
3252 case Builtin::BI__builtin_elementwise_sin:
3253 case Builtin::BI__builtin_elementwise_sinh:
3254 case Builtin::BI__builtin_elementwise_sqrt:
3255 case Builtin::BI__builtin_elementwise_tan:
3256 case Builtin::BI__builtin_elementwise_tanh:
3257 case Builtin::BI__builtin_elementwise_trunc: {
3263 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3264 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3265 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3266 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3268 if (
SemaRef.checkArgCount(TheCall, 2) ||
3271 SemaRef.getASTContext().IntTy))
3274 std::optional<llvm::APSInt> Offset =
3276 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3278 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3291 WorkList.push_back(BaseTy);
3292 while (!WorkList.empty()) {
3294 T =
T.getCanonicalType().getUnqualifiedType();
3295 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3303 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3304 llvm::append_range(List, ElementFields);
3309 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3310 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3313 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3314 if (RD->isStandardLayout())
3315 RD = RD->getStandardLayoutBaseWithFields();
3319 if (RD->
isUnion() || !RD->isAggregate()) {
3325 for (
const auto *FD : RD->
fields())
3326 if (!FD->isUnnamedBitField())
3327 FieldTypes.push_back(FD->
getType());
3329 std::reverse(FieldTypes.begin(), FieldTypes.end());
3330 llvm::append_range(WorkList, FieldTypes);
3334 if (!RD->isStandardLayout()) {
3336 for (
const auto &
Base : RD->bases())
3337 FieldTypes.push_back(
Base.getType());
3338 std::reverse(FieldTypes.begin(), FieldTypes.end());
3339 llvm::append_range(WorkList, FieldTypes);
3361 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3367 int ArraySize = VT->getNumElements();
3372 QualType ElTy = VT->getElementType();
3376 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3392 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3401 return llvm::equal(T1Types, T2Types,
3403 return SemaRef.IsLayoutCompatible(LHS, RHS);
3412 bool HadError =
false;
3414 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3422 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3423 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3424 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3425 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3427 if (NSpellingIdx != OSpellingIdx) {
3429 diag::err_hlsl_param_qualifier_mismatch)
3430 << NDAttr << NewParam;
3446 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3461 llvm_unreachable(
"HLSL doesn't support pointers.");
3464 llvm_unreachable(
"HLSL doesn't support complex types.");
3466 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3468 llvm_unreachable(
"Should have returned before this");
3478 llvm_unreachable(
"HLSL doesn't support complex types.");
3480 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3485 llvm_unreachable(
"HLSL doesn't support pointers.");
3487 llvm_unreachable(
"Should have returned before this");
3493 llvm_unreachable(
"HLSL doesn't support pointers.");
3496 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3500 llvm_unreachable(
"HLSL doesn't support complex types.");
3503 llvm_unreachable(
"Unhandled scalar cast");
3510 WorkList.push_back(BaseTy);
3511 while (!WorkList.empty()) {
3513 T =
T.getCanonicalType().getUnqualifiedType();
3515 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3516 WorkList.push_back(AT->getElementType());
3519 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
3520 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3529 for (
const auto *FD : RD->
fields()) {
3530 if (FD->isBitField())
3532 WorkList.push_back(FD->
getType());
3567 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3568 if (DestTypes[I]->isUnionType())
3600 if (SrcTypes.size() < DestTypes.size())
3603 unsigned SrcSize = SrcTypes.size();
3604 unsigned DstSize = DestTypes.size();
3606 for (I = 0; I < DstSize && I < SrcSize; I++) {
3607 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3615 for (; I < SrcSize; I++) {
3616 if (SrcTypes[I]->isUnionType())
3623 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3624 "We should not get here without a parameter modifier expression");
3625 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3632 << Arg << (IsInOut ? 1 : 0);
3638 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3645 << Arg << (IsInOut ? 1 : 0);
3657 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3663 auto *OpV =
new (Ctx)
3668 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3669 tok::equal, ArgOpV, OpV);
3685 "Pointer and reference types cannot be inout or out parameters");
3686 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3696 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3702 if (
Decl->getType().hasAddressSpace())
3705 if (
Decl->getType()->isDependentType())
3737 if (
SemaRef.RequireCompleteType(
3740 diag::err_typecheck_decl_incomplete_type)) {
3754 DefaultCBufferDecls.push_back(VD);
3759 collectResourceBindingsOnVarDecl(VD);
3762 VD->
hasAttr<HLSLVkConstantIdAttr>()) {
3770 processExplicitBindingsOnDecl(VD);
3776 if (!VD->
hasAttr<HLSLVkBindingAttr>()) {
3777 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3778 if (!RBA || !RBA->hasRegisterSlot()) {
3779 uint32_t OrderID = getNextImplicitBindingOrderID();
3781 RBA->setImplicitBindingOrderID(OrderID);
3794bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3796 "expected resource record type");
3803 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3804 HLSLVkBindingAttr *VkBinding = VD->
getAttr<HLSLVkBindingAttr>();
3805 std::optional<uint32_t> RegisterSlot;
3806 uint32_t SpaceNo = 0;
3808 RegisterSlot = VkBinding->getBinding();
3809 SpaceNo = VkBinding->getSet();
3811 if (RBA->hasRegisterSlot())
3812 RegisterSlot = RBA->getSlotNumber();
3813 SpaceNo = RBA->getSpaceNumber();
3817 QualType ResourceTy = VD->
getType();
3819 CXXMethodDecl *CreateMethod =
nullptr;
3820 llvm::SmallVector<Expr *> Args;
3822 if (RegisterSlot.has_value()) {
3824 CreateMethod = lookupMethod(
SemaRef, ResourceDecl,
"__createFromBinding",
3827 AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.
UnsignedIntTy,
3829 Args.push_back(RegSlot);
3833 lookupMethod(
SemaRef, ResourceDecl,
"__createFromImplicitBinding",
3835 uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
3836 ? RBA->getImplicitBindingOrderID()
3837 : getNextImplicitBindingOrderID();
3838 IntegerLiteral *OrderId =
3841 Args.push_back(OrderId);
3850 IntegerLiteral *Space =
3853 Args.push_back(Space);
3856 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
3857 Args.push_back(RangeSize);
3860 AST, llvm::APInt(UIntTySize, 0), AST.
UnsignedIntTy, SourceLocation());
3861 Args.push_back(Index);
3863 StringRef VarName = VD->
getName();
3870 Name,
nullptr,
VK_PRValue, FPOptionsOverride());
3871 Args.push_back(NameCast);
3881 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod,
false,
3886 CK_FunctionToPointerDecay, DRE,
nullptr,
VK_PRValue, FPOptionsOverride());
3888 CallExpr *InitExpr =
3890 SourceLocation(), FPOptionsOverride());
3893 SemaRef.CheckCompleteVariableDeclaration(VD);
3897bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
3899 "expected array of resource records");
3910 ASTContext &AST =
SemaRef.getASTContext();
3914 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3915 HLSLVkBindingAttr *VkBinding = VD->
getAttr<HLSLVkBindingAttr>();
3916 CXXMethodDecl *CreateMethod =
nullptr;
3918 if (VkBinding || (RBA && RBA->hasRegisterSlot()))
3920 CreateMethod = lookupMethod(
SemaRef, ResourceDecl,
"__createFromBinding",
3925 lookupMethod(
SemaRef, ResourceDecl,
"__createFromImplicitBinding",
3932 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3950 return initGlobalResourceDecl(VD);
3952 return initGlobalResourceArrayDecl(VD);
3962 "expected LHS to be a resource record or array of resource records");
3963 if (Opc != BO_Assign)
3968 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
3976 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
3987void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
3989 "expected global variable that contains HLSL resource");
3992 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
3993 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
3994 ? ResourceClass::CBuffer
3995 : ResourceClass::SRV);
4008 if (
const HLSLAttributedResourceType *AttrResType =
4009 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4010 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4015 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
4016 collectResourceBindingsOnUserRecordDecl(VD, RT);
4022void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
4025 bool HasBinding =
false;
4026 for (Attr *A : VD->
attrs()) {
4030 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4031 if (!RBA || !RBA->hasRegisterSlot())
4036 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
4037 "never have an attribute created");
4039 if (RT == RegisterType::C) {
4040 if (Bindings.hasBindingInfoForDecl(VD))
4042 diag::warn_hlsl_user_defined_type_missing_member)
4043 <<
static_cast<int>(RT);
4051 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4056 diag::warn_hlsl_user_defined_type_missing_member)
4057 <<
static_cast<int>(RT);
4065class InitListTransformer {
4069 QualType *DstIt =
nullptr;
4070 Expr **ArgIt =
nullptr;
4076 bool castInitializer(Expr *E) {
4077 assert(DstIt &&
"This should always be something!");
4078 if (DstIt == DestTypes.end()) {
4080 ArgExprs.push_back(E);
4085 DstIt = DestTypes.begin();
4088 Ctx, *DstIt,
false);
4093 ArgExprs.push_back(
Init);
4098 bool buildInitializerListImpl(Expr *E) {
4100 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4101 for (
auto *SubInit :
Init->inits())
4102 if (!buildInitializerListImpl(SubInit))
4111 return castInitializer(E);
4113 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4118 for (uint64_t I = 0; I <
Size; ++I) {
4120 SizeTy, SourceLocation());
4126 if (!castInitializer(ElExpr.
get()))
4132 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4136 for (uint64_t I = 0; I <
Size; ++I) {
4138 SizeTy, SourceLocation());
4143 if (!buildInitializerListImpl(ElExpr.
get()))
4150 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4151 RecordDecls.push_back(RD);
4152 while (RecordDecls.back()->getNumBases()) {
4153 CXXRecordDecl *D = RecordDecls.back();
4155 "HLSL doesn't support multiple inheritance");
4156 RecordDecls.push_back(
4159 while (!RecordDecls.empty()) {
4160 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4161 for (
auto *FD : RD->
fields()) {
4162 if (FD->isUnnamedBitField())
4170 if (!buildInitializerListImpl(Res.
get()))
4178 Expr *generateInitListsImpl(QualType Ty) {
4179 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
4183 llvm::SmallVector<Expr *> Inits;
4184 assert(!
isa<MatrixType>(Ty) &&
"Matrix types not yet supported in HLSL");
4189 if (
auto *ATy = Ty->
getAs<VectorType>()) {
4190 ElTy = ATy->getElementType();
4191 Size = ATy->getNumElements();
4194 ElTy = VTy->getElementType();
4195 Size = VTy->getZExtSize();
4197 for (uint64_t I = 0; I <
Size; ++I)
4198 Inits.push_back(generateInitListsImpl(ElTy));
4201 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4202 RecordDecls.push_back(RD);
4203 while (RecordDecls.back()->getNumBases()) {
4204 CXXRecordDecl *D = RecordDecls.back();
4206 "HLSL doesn't support multiple inheritance");
4207 RecordDecls.push_back(
4210 while (!RecordDecls.empty()) {
4211 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4212 for (
auto *FD : RD->
fields())
4213 if (!FD->isUnnamedBitField())
4214 Inits.push_back(generateInitListsImpl(FD->
getType()));
4217 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4218 Inits, Inits.back()->getEndLoc());
4219 NewInit->setType(Ty);
4224 llvm::SmallVector<QualType, 16> DestTypes;
4225 llvm::SmallVector<Expr *, 16> ArgExprs;
4226 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4227 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4228 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4229 InitTy = Entity.
getType().getNonReferenceType();
4239 DstIt = DestTypes.begin();
4242 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4244 Expr *generateInitLists() {
4245 assert(!ArgExprs.empty() &&
4246 "Call buildInitializerList to generate argument expressions.");
4247 ArgIt = ArgExprs.begin();
4249 return generateInitListsImpl(InitTy);
4250 llvm::SmallVector<Expr *> Inits;
4251 while (ArgIt != ArgExprs.end())
4252 Inits.push_back(generateInitListsImpl(InitTy));
4254 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4255 Inits, Inits.back()->getEndLoc());
4256 llvm::APInt ArySize(64, Inits.size());
4258 ArraySizeModifier::Normal, 0));
4267 if (
Init->getType()->isScalarType())
4270 InitListTransformer ILT(
SemaRef, Entity);
4272 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4280 Init->setInit(I, E);
4282 if (!ILT.buildInitializerList(E))
4285 size_t ExpectedSize = ILT.DestTypes.size();
4286 size_t ActualSize = ILT.ArgExprs.size();
4287 if (ExpectedSize == 0 && ActualSize == 0)
4296 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4303 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4304 if (ExpectedSize != ActualSize) {
4305 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4306 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4307 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4314 Init->resizeInits(Ctx, NewInit->getNumInits());
4315 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4316 Init->updateInit(Ctx, I, NewInit->getInit(I));
4321 const HLSLVkConstantIdAttr *ConstIdAttr =
4322 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4329 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4339 int ConstantID = ConstIdAttr->getId();
4340 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4342 ConstIdAttr->getLocation());
4346 if (
C->getType()->getCanonicalTypeUnqualified() !=
4350 Context.getTrivialTypeSourceInfo(
4351 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 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.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
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.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
void completeDefinition() override
Indicates that the definition of this class is now complete.
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
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]).
const CXXRecordDecl * getStandardLayoutBaseWithFields() const
If this is a standard-layout class or union, any and all data members will be declared in the same ty...
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
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 ...
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_range fields() 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.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
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)
bool isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
void CheckEntryPoint(FunctionDecl *FD)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
bool ContainsBitField(QualType BaseTy)
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
T * createSemanticAttr(const ParsedAttr &AL, std::optional< unsigned > Location)
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)
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 isHLSLBuiltinIntangibleType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const