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 uint32_t Offset = 0;
1373 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1375 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1376 HasAnySampler =
true;
1378 HasAnyNonSampler =
true;
1380 if (HasAnySampler && HasAnyNonSampler)
1381 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1386 if (Clause->NumDescriptors == 0)
1389 if (Clause->Offset !=
1390 llvm::hlsl::rootsig::DescriptorTableOffsetAppend) {
1392 Offset = Clause->Offset;
1395 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1396 Offset, Clause->NumDescriptors);
1398 if (!llvm::hlsl::rootsig::verifyBoundOffset(Offset)) {
1400 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1401 }
else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound)) {
1403 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1406 Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded
1407 ? uint32_t(RangeBound)
1408 : uint32_t(RangeBound + 1);
1411 uint32_t LowerBound(Clause->Reg.Number);
1412 uint32_t UpperBound = Clause->NumDescriptors == ~0u
1414 : LowerBound + Clause->NumDescriptors - 1;
1416 BindingChecker.trackBinding(
1418 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1419 LowerBound, UpperBound, ClauseElem);
1421 UnboundClauses.clear();
1425 return BindingChecker.checkOverlap();
1430 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1435 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1436 if (RS->getSignatureIdent() != Ident) {
1437 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1441 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1447 if (
auto *SignatureDecl =
1455 llvm::VersionTuple SMVersion =
1460 uint32_t ZMax = 1024;
1461 uint32_t ThreadMax = 1024;
1462 if (IsDXIL && SMVersion.getMajor() <= 4) {
1465 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1475 diag::err_hlsl_numthreads_argument_oor)
1484 diag::err_hlsl_numthreads_argument_oor)
1493 diag::err_hlsl_numthreads_argument_oor)
1498 if (
X * Y * Z > ThreadMax) {
1499 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1516 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1524 if (SpelledArgsCount > 1 &&
1528 uint32_t Preferred = 0;
1529 if (SpelledArgsCount > 2 &&
1533 if (SpelledArgsCount > 2) {
1536 diag::err_attribute_power_of_two_in_range)
1537 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1542 if (Preferred < Min || Preferred >
Max) {
1544 diag::err_attribute_power_of_two_in_range)
1545 << AL <<
Min <<
Max << Preferred;
1548 }
else if (SpelledArgsCount > 1) {
1551 diag::err_attribute_power_of_two_in_range)
1552 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1556 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1559 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1564 diag::err_attribute_power_of_two_in_range)
1565 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1570 HLSLWaveSizeAttr *NewAttr =
1598 uint32_t Binding = 0;
1613 if (!
T->hasUnsignedIntegerRepresentation() ||
1614 (VT && VT->getNumElements() > 3)) {
1615 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1616 << AL <<
"uint/uint2/uint3";
1625 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1626 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1627 << AL <<
"float/float1/float2/float3/float4";
1635 std::optional<unsigned> Index) {
1639 QualType ValueType = VD->getType();
1640 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1641 ValueType = FD->getReturnType();
1643 bool IsOutput =
false;
1644 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1651 Attr *Attribute =
nullptr;
1652 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1655 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1657 }
else if (SemanticName ==
"SV_GROUPINDEX") {
1659 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1661 }
else if (SemanticName ==
"SV_GROUPTHREADID") {
1664 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1666 }
else if (SemanticName ==
"SV_GROUPID") {
1669 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1671 }
else if (SemanticName ==
"SV_POSITION") {
1672 const auto *VT = ValueType->getAs<
VectorType>();
1673 if (!ValueType->hasFloatingRepresentation() ||
1674 (VT && VT->getNumElements() > 4))
1675 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1676 << AL <<
"float/float1/float2/float3/float4";
1679 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1687 uint32_t IndexValue, ExplicitIndex;
1690 assert(IndexValue > 0 ? ExplicitIndex :
true);
1691 std::optional<unsigned> Index =
1692 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1697 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1702 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1703 << AL <<
"shader constant in a constant buffer";
1707 uint32_t SubComponent;
1717 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1722 if (IsAggregateTy || Size > 128) {
1723 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1727 if ((Component * 32 + Size) > 128) {
1728 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1733 EltTy = VT->getElementType();
1735 if (Align > 32 && Component == 1) {
1738 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1752 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1755 llvm::Triple::EnvironmentType ShaderType;
1756 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1757 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1758 << AL << Str << ArgLoc;
1772 assert(AttrList.size() &&
"expected list of resource attributes");
1779 HLSLAttributedResourceType::Attributes ResAttrs;
1781 bool HasResourceClass =
false;
1782 for (
const Attr *A : AttrList) {
1785 LocEnd = A->getRange().getEnd();
1786 switch (A->getKind()) {
1787 case attr::HLSLResourceClass: {
1789 if (HasResourceClass) {
1790 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1791 ? diag::warn_duplicate_attribute_exact
1792 : diag::warn_duplicate_attribute)
1796 ResAttrs.ResourceClass = RC;
1797 HasResourceClass =
true;
1801 if (ResAttrs.IsROV) {
1802 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1805 ResAttrs.IsROV =
true;
1807 case attr::HLSLRawBuffer:
1808 if (ResAttrs.RawBuffer) {
1809 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1812 ResAttrs.RawBuffer =
true;
1814 case attr::HLSLContainedType: {
1817 if (!ContainedTy.
isNull()) {
1818 S.
Diag(A->getLocation(), ContainedTy == Ty
1819 ? diag::warn_duplicate_attribute_exact
1820 : diag::warn_duplicate_attribute)
1829 llvm_unreachable(
"unhandled resource attribute type");
1833 if (!HasResourceClass) {
1834 S.
Diag(AttrList.back()->getRange().getEnd(),
1835 diag::err_hlsl_missing_resource_class);
1840 Wrapped, ContainedTy, ResAttrs);
1842 if (LocInfo && ContainedTyInfo) {
1855 if (!
T->isHLSLResourceType()) {
1856 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1871 AttributeCommonInfo::AS_CXX11, 0, false ,
1876 case ParsedAttr::AT_HLSLResourceClass: {
1878 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1889 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1890 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1891 <<
"ResourceClass" << Identifier;
1894 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
1898 case ParsedAttr::AT_HLSLROV:
1902 case ParsedAttr::AT_HLSLRawBuffer:
1906 case ParsedAttr::AT_HLSLContainedType: {
1908 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1914 assert(TSI &&
"no type source info for attribute argument");
1916 diag::err_incomplete_type))
1918 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
1923 llvm_unreachable(
"unhandled HLSL attribute");
1926 HLSLResourcesTypeAttrs.emplace_back(A);
1932 if (!HLSLResourcesTypeAttrs.size())
1938 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1939 const HLSLAttributedResourceType *RT =
1946 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1948 HLSLResourcesTypeAttrs.clear();
1956 auto I = LocsForHLSLAttributedResources.find(RT);
1957 if (I != LocsForHLSLAttributedResources.end()) {
1958 LocInfo = I->second;
1959 LocsForHLSLAttributedResources.erase(I);
1968void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
1969 const RecordType *RT) {
1970 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1977 "incomplete arrays inside user defined types are not supported");
1986 if (
const HLSLAttributedResourceType *AttrResType =
1987 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
1992 Bindings.addDeclBindingInfo(VD, RC);
1993 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1999 collectResourceBindingsOnUserRecordDecl(VD, RT);
2011 bool SpecifiedSpace) {
2012 int RegTypeNum =
static_cast<int>(RegType);
2015 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2016 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2021 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2022 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2023 : ResourceClass::SRV;
2033 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2037 if (
const HLSLAttributedResourceType *AttrResType =
2038 HLSLAttributedResourceType::findHandleTypeOnResource(
2055 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2056 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2061 if (RegType == RegisterType::CBuffer)
2062 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2063 else if (RegType != RegisterType::C)
2064 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2068 if (RegType == RegisterType::C)
2069 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2071 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2081 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2089 bool RegisterTypesDetected[5] = {
false};
2090 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2093 if (HLSLResourceBindingAttr *
attr =
2094 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2097 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2098 int otherRegTypeNum =
static_cast<int>(otherRegType);
2100 diag::err_hlsl_duplicate_register_annotation)
2104 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2112 bool SpecifiedSpace) {
2117 "expecting VarDecl or HLSLBufferDecl");
2128 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2130 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2131 Ty = IAT->getElementType();
2133 diag::err_incomplete_type))
2137 StringRef Slot =
"";
2138 StringRef Space =
"";
2142 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2152 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2158 SpaceLoc = Loc->
getLoc();
2161 if (Str.starts_with(
"space")) {
2163 SpaceLoc = Loc->
getLoc();
2172 std::optional<unsigned> SlotNum;
2173 unsigned SpaceNum = 0;
2176 if (!Slot.empty()) {
2178 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2181 if (RegType == RegisterType::I) {
2182 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2185 StringRef SlotNumStr = Slot.substr(1);
2187 if (SlotNumStr.getAsInteger(10, N)) {
2188 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2195 if (!Space.starts_with(
"space")) {
2196 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2199 StringRef SpaceNumStr = Space.substr(5);
2200 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2201 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2206 if (SlotNum.has_value())
2211 HLSLResourceBindingAttr *NewAttr =
2212 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2214 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2269 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2273 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2274 unsigned CurrentShaderStageBit;
2279 bool ReportOnlyShaderStageIssues;
2282 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2283 static_assert(
sizeof(
unsigned) >= 4);
2284 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2285 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2286 "ShaderType is too big for this bitmap");
2289 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2290 CurrentShaderEnvironment = ShaderType;
2291 CurrentShaderStageBit = (1 << bitmapIndex);
2294 void SetUnknownShaderStageContext() {
2295 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2296 CurrentShaderStageBit = (1 << 31);
2299 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2300 return CurrentShaderEnvironment;
2303 bool InUnknownShaderStageContext()
const {
2304 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2308 void AddToScannedFunctions(
const FunctionDecl *FD) {
2309 unsigned &ScannedStages = ScannedDecls[FD];
2310 ScannedStages |= CurrentShaderStageBit;
2313 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2315 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2316 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2319 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2320 return ScannerStages & CurrentShaderStageBit;
2323 static bool NeverBeenScanned(
unsigned ScannedStages) {
2324 return ScannedStages == 0;
2328 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2329 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2331 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2332 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2335 DiagnoseHLSLAvailability(Sema &SemaRef)
2337 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2338 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2341 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2342 void RunOnFunction(
const FunctionDecl *FD);
2344 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2345 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2347 HandleFunctionOrMethodRef(FD, DRE);
2351 bool VisitMemberExpr(MemberExpr *ME)
override {
2352 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2354 HandleFunctionOrMethodRef(FD, ME);
2359void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2362 "expected DeclRefExpr or MemberExpr");
2366 if (FD->
hasBody(FDWithBody)) {
2367 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2368 DeclsToScan.push_back(FDWithBody);
2373 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2375 CheckDeclAvailability(
2379void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2388 DeclContextsToScan.push_back(TU);
2390 while (!DeclContextsToScan.empty()) {
2391 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2392 for (
auto &D : DC->
decls()) {
2394 if (D->isImplicit())
2399 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2400 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2405 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2410 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2411 SetShaderStageContext(ShaderAttr->getType());
2420 for (
const auto *Redecl : FD->
redecls()) {
2421 if (Redecl->isInExportDeclContext()) {
2428 SetUnknownShaderStageContext();
2436void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2437 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2438 DeclsToScan.push_back(FD);
2440 while (!DeclsToScan.empty()) {
2448 const unsigned ScannedStages = GetScannedStages(FD);
2449 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2452 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2454 AddToScannedFunctions(FD);
2459bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2460 const AvailabilityAttr *AA) {
2465 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2466 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2469 llvm::Triple::EnvironmentType AttrEnv =
2470 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2472 return CurrentEnv == AttrEnv;
2475const AvailabilityAttr *
2476DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2477 AvailabilityAttr
const *PartialMatch =
nullptr;
2481 for (
const auto *A : D->
attrs()) {
2482 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2483 StringRef AttrPlatform = Avail->getPlatform()->getName();
2484 StringRef TargetPlatform =
2488 if (AttrPlatform == TargetPlatform) {
2490 if (HasMatchingEnvironmentOrNone(Avail))
2492 PartialMatch = Avail;
2496 return PartialMatch;
2501void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2502 const AvailabilityAttr *AA,
2521 if (ReportOnlyShaderStageIssues)
2527 if (InUnknownShaderStageContext())
2532 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2533 VersionTuple Introduced = AA->getIntroduced();
2542 llvm::StringRef PlatformName(
2545 llvm::StringRef CurrentEnvStr =
2546 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2548 llvm::StringRef AttrEnvStr =
2549 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2550 bool UseEnvironment = !AttrEnvStr.empty();
2552 if (EnvironmentMatches) {
2553 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2554 <<
Range << D << PlatformName << Introduced.getAsString()
2555 << UseEnvironment << CurrentEnvStr;
2557 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2561 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2562 << D << PlatformName << Introduced.getAsString()
2564 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2571 if (!DefaultCBufferDecls.empty()) {
2574 DefaultCBufferDecls);
2576 getNextImplicitBindingOrderID());
2577 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2581 for (
const Decl *VD : DefaultCBufferDecls) {
2582 const HLSLResourceBindingAttr *RBA =
2583 VD->
getAttr<HLSLResourceBindingAttr>();
2584 if (RBA && RBA->hasRegisterSlot() &&
2585 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2592 SemaRef.Consumer.HandleTopLevelDecl(DG);
2594 diagnoseAvailabilityViolations(TU);
2604 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2607 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2614 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2617 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2642 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2657 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2658 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2659 << ArgOrdinal << 5 << 0
2665 unsigned ArgIndex) {
2666 auto *Arg = TheCall->
getArg(ArgIndex);
2668 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2671 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2681 if (VecTy->getElementType()->isDoubleType())
2682 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2683 << ArgOrdinal << 1 << 0 << 1
2693 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2694 << ArgOrdinal << 5 << 1
2703 if (VecTy->getElementType()->isUnsignedIntegerType())
2706 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2707 << ArgOrdinal << 4 << 3 << 0
2716 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2717 << ArgOrdinal << 5 << 3
2733 unsigned ArgIndex) {
2742 diag::err_typecheck_expect_scalar_or_vector)
2743 << ArgType << Scalar;
2750 unsigned ArgIndex) {
2755 if (!(ArgType->isScalarType() ||
2756 (VTy && VTy->getElementType()->isScalarType()))) {
2758 diag::err_typecheck_expect_any_scalar_or_vector)
2775 diag::err_typecheck_expect_any_scalar_or_vector)
2788 diag::err_typecheck_call_different_arg_types)
2807 Arg1ScalarTy = VTy->getElementType();
2811 Arg2ScalarTy = VTy->getElementType();
2814 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2815 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2825 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2827 diag::err_typecheck_vector_lengths_not_equal)
2833 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2835 diag::err_typecheck_vector_lengths_not_equal)
2848 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2852 const HLSLAttributedResourceType *ResTy =
2856 diag::err_typecheck_expect_hlsl_resource)
2860 if (Check && Check(ResTy)) {
2862 diag::err_invalid_hlsl_resource_type)
2872 switch (BuiltinID) {
2873 case Builtin::BI__builtin_hlsl_adduint64: {
2874 if (
SemaRef.checkArgCount(TheCall, 2))
2887 if (ElementBitCount != 32) {
2889 diag::err_integer_incorrect_bit_count)
2890 << 32 << ElementBitCount;
2895 int NumElementsArg = VTy->getNumElements();
2896 if (NumElementsArg != 2 && NumElementsArg != 4) {
2898 << 1 << 64 << NumElementsArg * ElementBitCount;
2912 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2913 if (
SemaRef.checkArgCount(TheCall, 2) ||
2916 SemaRef.getASTContext().UnsignedIntTy))
2921 QualType ContainedTy = ResourceTy->getContainedType();
2924 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
2930 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2931 if (
SemaRef.checkArgCount(TheCall, 1) ||
2939 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2941 if (
SemaRef.checkArgCount(TheCall, 6) ||
2955 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2957 if (
SemaRef.checkArgCount(TheCall, 6) ||
2971 case Builtin::BI__builtin_hlsl_and:
2972 case Builtin::BI__builtin_hlsl_or: {
2973 if (
SemaRef.checkArgCount(TheCall, 2))
2986 case Builtin::BI__builtin_hlsl_all:
2987 case Builtin::BI__builtin_hlsl_any: {
2988 if (
SemaRef.checkArgCount(TheCall, 1))
2994 case Builtin::BI__builtin_hlsl_asdouble: {
2995 if (
SemaRef.checkArgCount(TheCall, 2))
2999 SemaRef.Context.UnsignedIntTy,
3004 SemaRef.Context.UnsignedIntTy,
3013 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3014 if (
SemaRef.BuiltinElementwiseTernaryMath(
3020 case Builtin::BI__builtin_hlsl_dot: {
3022 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3028 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3029 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3030 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3040 EltTy = VecTy->getElementType();
3041 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3054 case Builtin::BI__builtin_hlsl_select: {
3055 if (
SemaRef.checkArgCount(TheCall, 3))
3063 if (VTy && VTy->getElementType()->isBooleanType() &&
3068 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3069 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3070 if (
SemaRef.checkArgCount(TheCall, 1))
3076 diag::err_builtin_invalid_arg_type)
3079 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3083 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3084 case Builtin::BI__builtin_hlsl_elementwise_radians:
3085 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3086 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3087 if (
SemaRef.checkArgCount(TheCall, 1))
3092 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3096 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
3097 if (
SemaRef.checkArgCount(TheCall, 1))
3102 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3107 case Builtin::BI__builtin_hlsl_lerp: {
3108 if (
SemaRef.checkArgCount(TheCall, 3))
3115 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3119 case Builtin::BI__builtin_hlsl_mad: {
3120 if (
SemaRef.BuiltinElementwiseTernaryMath(
3126 case Builtin::BI__builtin_hlsl_normalize: {
3127 if (
SemaRef.checkArgCount(TheCall, 1))
3138 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3139 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3147 case Builtin::BI__builtin_hlsl_step: {
3148 if (
SemaRef.checkArgCount(TheCall, 2))
3160 case Builtin::BI__builtin_hlsl_wave_active_max:
3161 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3162 if (
SemaRef.checkArgCount(TheCall, 1))
3177 case Builtin::BI__builtin_elementwise_bitreverse: {
3185 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3186 if (
SemaRef.checkArgCount(TheCall, 2))
3194 diag::err_typecheck_convert_incompatible)
3195 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3208 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3209 if (
SemaRef.checkArgCount(TheCall, 0))
3213 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3214 if (
SemaRef.checkArgCount(TheCall, 3))
3229 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3230 if (
SemaRef.checkArgCount(TheCall, 1))
3237 case Builtin::BI__builtin_elementwise_acos:
3238 case Builtin::BI__builtin_elementwise_asin:
3239 case Builtin::BI__builtin_elementwise_atan:
3240 case Builtin::BI__builtin_elementwise_atan2:
3241 case Builtin::BI__builtin_elementwise_ceil:
3242 case Builtin::BI__builtin_elementwise_cos:
3243 case Builtin::BI__builtin_elementwise_cosh:
3244 case Builtin::BI__builtin_elementwise_exp:
3245 case Builtin::BI__builtin_elementwise_exp2:
3246 case Builtin::BI__builtin_elementwise_exp10:
3247 case Builtin::BI__builtin_elementwise_floor:
3248 case Builtin::BI__builtin_elementwise_fmod:
3249 case Builtin::BI__builtin_elementwise_log:
3250 case Builtin::BI__builtin_elementwise_log2:
3251 case Builtin::BI__builtin_elementwise_log10:
3252 case Builtin::BI__builtin_elementwise_pow:
3253 case Builtin::BI__builtin_elementwise_roundeven:
3254 case Builtin::BI__builtin_elementwise_sin:
3255 case Builtin::BI__builtin_elementwise_sinh:
3256 case Builtin::BI__builtin_elementwise_sqrt:
3257 case Builtin::BI__builtin_elementwise_tan:
3258 case Builtin::BI__builtin_elementwise_tanh:
3259 case Builtin::BI__builtin_elementwise_trunc: {
3265 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3266 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3267 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3268 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3270 if (
SemaRef.checkArgCount(TheCall, 2) ||
3273 SemaRef.getASTContext().IntTy))
3276 std::optional<llvm::APSInt> Offset =
3278 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3280 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3293 WorkList.push_back(BaseTy);
3294 while (!WorkList.empty()) {
3296 T =
T.getCanonicalType().getUnqualifiedType();
3298 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3306 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3307 llvm::append_range(List, ElementFields);
3312 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3313 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3316 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3317 if (RD->isStandardLayout())
3318 RD = RD->getStandardLayoutBaseWithFields();
3322 if (RD->
isUnion() || !RD->isAggregate()) {
3328 for (
const auto *FD : RD->
fields())
3329 FieldTypes.push_back(FD->
getType());
3331 std::reverse(FieldTypes.begin(), FieldTypes.end());
3332 llvm::append_range(WorkList, FieldTypes);
3336 if (!RD->isStandardLayout()) {
3338 for (
const auto &
Base : RD->bases())
3339 FieldTypes.push_back(
Base.getType());
3340 std::reverse(FieldTypes.begin(), FieldTypes.end());
3341 llvm::append_range(WorkList, FieldTypes);
3363 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3369 int ArraySize = VT->getNumElements();
3374 QualType ElTy = VT->getElementType();
3378 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3394 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3403 return llvm::equal(T1Types, T2Types,
3405 return SemaRef.IsLayoutCompatible(LHS, RHS);
3414 bool HadError =
false;
3416 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3424 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3425 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3426 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3427 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3429 if (NSpellingIdx != OSpellingIdx) {
3431 diag::err_hlsl_param_qualifier_mismatch)
3432 << NDAttr << NewParam;
3448 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3463 llvm_unreachable(
"HLSL doesn't support pointers.");
3466 llvm_unreachable(
"HLSL doesn't support complex types.");
3468 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3470 llvm_unreachable(
"Should have returned before this");
3480 llvm_unreachable(
"HLSL doesn't support complex types.");
3482 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3487 llvm_unreachable(
"HLSL doesn't support pointers.");
3489 llvm_unreachable(
"Should have returned before this");
3495 llvm_unreachable(
"HLSL doesn't support pointers.");
3498 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3502 llvm_unreachable(
"HLSL doesn't support complex types.");
3505 llvm_unreachable(
"Unhandled scalar cast");
3512 WorkList.push_back(BaseTy);
3513 while (!WorkList.empty()) {
3515 T =
T.getCanonicalType().getUnqualifiedType();
3517 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3518 WorkList.push_back(AT->getElementType());
3521 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
3522 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3531 for (
const auto *FD : RD->
fields()) {
3532 if (FD->isBitField())
3534 WorkList.push_back(FD->
getType());
3569 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3570 if (DestTypes[I]->isUnionType())
3602 if (SrcTypes.size() < DestTypes.size())
3605 unsigned SrcSize = SrcTypes.size();
3606 unsigned DstSize = DestTypes.size();
3608 for (I = 0; I < DstSize && I < SrcSize; I++) {
3609 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3617 for (; I < SrcSize; I++) {
3618 if (SrcTypes[I]->isUnionType())
3625 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3626 "We should not get here without a parameter modifier expression");
3627 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3634 << Arg << (IsInOut ? 1 : 0);
3640 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3647 << Arg << (IsInOut ? 1 : 0);
3659 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3665 auto *OpV =
new (Ctx)
3670 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3671 tok::equal, ArgOpV, OpV);
3687 "Pointer and reference types cannot be inout or out parameters");
3688 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3698 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3704 if (
Decl->getType().hasAddressSpace())
3707 if (
Decl->getType()->isDependentType())
3739 if (
SemaRef.RequireCompleteType(
3742 diag::err_typecheck_decl_incomplete_type)) {
3756 DefaultCBufferDecls.push_back(VD);
3761 collectResourceBindingsOnVarDecl(VD);
3764 VD->
hasAttr<HLSLVkConstantIdAttr>()) {
3772 processExplicitBindingsOnDecl(VD);
3778 if (!VD->
hasAttr<HLSLVkBindingAttr>()) {
3779 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3780 if (!RBA || !RBA->hasRegisterSlot()) {
3781 uint32_t OrderID = getNextImplicitBindingOrderID();
3783 RBA->setImplicitBindingOrderID(OrderID);
3796bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3798 "expected resource record type");
3805 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3806 HLSLVkBindingAttr *VkBinding = VD->
getAttr<HLSLVkBindingAttr>();
3807 std::optional<uint32_t> RegisterSlot;
3808 uint32_t SpaceNo = 0;
3810 RegisterSlot = VkBinding->getBinding();
3811 SpaceNo = VkBinding->getSet();
3813 if (RBA->hasRegisterSlot())
3814 RegisterSlot = RBA->getSlotNumber();
3815 SpaceNo = RBA->getSpaceNumber();
3819 QualType ResourceTy = VD->
getType();
3821 CXXMethodDecl *CreateMethod =
nullptr;
3822 llvm::SmallVector<Expr *> Args;
3824 if (RegisterSlot.has_value()) {
3826 CreateMethod = lookupMethod(
SemaRef, ResourceDecl,
"__createFromBinding",
3829 AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.
UnsignedIntTy,
3831 Args.push_back(RegSlot);
3835 lookupMethod(
SemaRef, ResourceDecl,
"__createFromImplicitBinding",
3837 uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
3838 ? RBA->getImplicitBindingOrderID()
3839 : getNextImplicitBindingOrderID();
3840 IntegerLiteral *OrderId =
3843 Args.push_back(OrderId);
3852 IntegerLiteral *Space =
3855 Args.push_back(Space);
3858 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
3859 Args.push_back(RangeSize);
3862 AST, llvm::APInt(UIntTySize, 0), AST.
UnsignedIntTy, SourceLocation());
3863 Args.push_back(Index);
3865 StringRef VarName = VD->
getName();
3872 Name,
nullptr,
VK_PRValue, FPOptionsOverride());
3873 Args.push_back(NameCast);
3883 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod,
false,
3888 CK_FunctionToPointerDecay, DRE,
nullptr,
VK_PRValue, FPOptionsOverride());
3890 CallExpr *InitExpr =
3892 SourceLocation(), FPOptionsOverride());
3895 SemaRef.CheckCompleteVariableDeclaration(VD);
3899bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
3901 "expected array of resource records");
3912 ASTContext &AST =
SemaRef.getASTContext();
3916 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3917 HLSLVkBindingAttr *VkBinding = VD->
getAttr<HLSLVkBindingAttr>();
3918 CXXMethodDecl *CreateMethod =
nullptr;
3920 if (VkBinding || (RBA && RBA->hasRegisterSlot()))
3922 CreateMethod = lookupMethod(
SemaRef, ResourceDecl,
"__createFromBinding",
3927 lookupMethod(
SemaRef, ResourceDecl,
"__createFromImplicitBinding",
3934 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3952 return initGlobalResourceDecl(VD);
3954 return initGlobalResourceArrayDecl(VD);
3964 "expected LHS to be a resource record or array of resource records");
3965 if (Opc != BO_Assign)
3970 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
3978 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
3989void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
3991 "expected global variable that contains HLSL resource");
3994 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
3995 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
3996 ? ResourceClass::CBuffer
3997 : ResourceClass::SRV);
4010 if (
const HLSLAttributedResourceType *AttrResType =
4011 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4012 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4017 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
4018 collectResourceBindingsOnUserRecordDecl(VD, RT);
4024void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
4027 bool HasBinding =
false;
4028 for (Attr *A : VD->
attrs()) {
4032 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4033 if (!RBA || !RBA->hasRegisterSlot())
4038 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
4039 "never have an attribute created");
4041 if (RT == RegisterType::C) {
4042 if (Bindings.hasBindingInfoForDecl(VD))
4044 diag::warn_hlsl_user_defined_type_missing_member)
4045 <<
static_cast<int>(RT);
4053 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4058 diag::warn_hlsl_user_defined_type_missing_member)
4059 <<
static_cast<int>(RT);
4067class InitListTransformer {
4071 QualType *DstIt =
nullptr;
4072 Expr **ArgIt =
nullptr;
4078 bool castInitializer(Expr *E) {
4079 assert(DstIt &&
"This should always be something!");
4080 if (DstIt == DestTypes.end()) {
4082 ArgExprs.push_back(E);
4087 DstIt = DestTypes.begin();
4090 Ctx, *DstIt,
false);
4095 ArgExprs.push_back(
Init);
4100 bool buildInitializerListImpl(Expr *E) {
4102 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4103 for (
auto *SubInit :
Init->inits())
4104 if (!buildInitializerListImpl(SubInit))
4113 return castInitializer(E);
4115 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4120 for (uint64_t I = 0; I <
Size; ++I) {
4122 SizeTy, SourceLocation());
4128 if (!castInitializer(ElExpr.
get()))
4134 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4138 for (uint64_t I = 0; I <
Size; ++I) {
4140 SizeTy, SourceLocation());
4145 if (!buildInitializerListImpl(ElExpr.
get()))
4152 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4153 RecordDecls.push_back(RD);
4154 while (RecordDecls.back()->getNumBases()) {
4155 CXXRecordDecl *D = RecordDecls.back();
4157 "HLSL doesn't support multiple inheritance");
4158 RecordDecls.push_back(
4161 while (!RecordDecls.empty()) {
4162 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4163 for (
auto *FD : RD->
fields()) {
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 Inits.push_back(generateInitListsImpl(FD->
getType()));
4216 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4217 Inits, Inits.back()->getEndLoc());
4218 NewInit->setType(Ty);
4223 llvm::SmallVector<QualType, 16> DestTypes;
4224 llvm::SmallVector<Expr *, 16> ArgExprs;
4225 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4226 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4227 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4228 InitTy = Entity.
getType().getNonReferenceType();
4238 DstIt = DestTypes.begin();
4241 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4243 Expr *generateInitLists() {
4244 assert(!ArgExprs.empty() &&
4245 "Call buildInitializerList to generate argument expressions.");
4246 ArgIt = ArgExprs.begin();
4248 return generateInitListsImpl(InitTy);
4249 llvm::SmallVector<Expr *> Inits;
4250 while (ArgIt != ArgExprs.end())
4251 Inits.push_back(generateInitListsImpl(InitTy));
4253 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4254 Inits, Inits.back()->getEndLoc());
4255 llvm::APInt ArySize(64, Inits.size());
4257 ArraySizeModifier::Normal, 0));
4266 if (
Init->getType()->isScalarType())
4269 InitListTransformer ILT(
SemaRef, Entity);
4271 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4279 Init->setInit(I, E);
4281 if (!ILT.buildInitializerList(E))
4284 size_t ExpectedSize = ILT.DestTypes.size();
4285 size_t ActualSize = ILT.ArgExprs.size();
4292 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4299 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4300 if (ExpectedSize != ActualSize) {
4301 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4302 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4303 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4310 Init->resizeInits(Ctx, NewInit->getNumInits());
4311 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4312 Init->updateInit(Ctx, I, NewInit->getInit(I));
4317 const HLSLVkConstantIdAttr *ConstIdAttr =
4318 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4325 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4335 int ConstantID = ConstIdAttr->getId();
4336 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4338 ConstIdAttr->getLocation());
4342 if (
C->getType()->getCanonicalTypeUnqualified() !=
4346 Context.getTrivialTypeSourceInfo(
4347 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