15#include "clang/AST/Attrs.inc"
37#include "llvm/ADT/ArrayRef.h"
38#include "llvm/ADT/STLExtras.h"
39#include "llvm/ADT/SmallVector.h"
40#include "llvm/ADT/StringExtras.h"
41#include "llvm/ADT/StringRef.h"
42#include "llvm/ADT/Twine.h"
43#include "llvm/Frontend/HLSL/HLSLBinding.h"
44#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
45#include "llvm/Support/Casting.h"
46#include "llvm/Support/DXILABI.h"
47#include "llvm/Support/ErrorHandling.h"
48#include "llvm/Support/FormatVariadic.h"
49#include "llvm/TargetParser/Triple.h"
64 case ResourceClass::SRV:
65 return RegisterType::SRV;
66 case ResourceClass::UAV:
67 return RegisterType::UAV;
68 case ResourceClass::CBuffer:
69 return RegisterType::CBuffer;
70 case ResourceClass::Sampler:
71 return RegisterType::Sampler;
73 llvm_unreachable(
"unexpected ResourceClass value");
83 assert(RT !=
nullptr);
87 *RT = RegisterType::SRV;
91 *RT = RegisterType::UAV;
95 *RT = RegisterType::CBuffer;
99 *RT = RegisterType::Sampler;
103 *RT = RegisterType::C;
107 *RT = RegisterType::I;
116 case RegisterType::SRV:
117 return ResourceClass::SRV;
118 case RegisterType::UAV:
119 return ResourceClass::UAV;
120 case RegisterType::CBuffer:
121 return ResourceClass::CBuffer;
122 case RegisterType::Sampler:
123 return ResourceClass::Sampler;
124 case RegisterType::C:
125 case RegisterType::I:
129 llvm_unreachable(
"unexpected RegisterType value");
133 const auto *BT = dyn_cast<BuiltinType>(
Type);
137 return Builtin::BI__builtin_get_spirv_spec_constant_int;
140 switch (BT->getKind()) {
141 case BuiltinType::Bool:
142 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
143 case BuiltinType::Short:
144 return Builtin::BI__builtin_get_spirv_spec_constant_short;
145 case BuiltinType::Int:
146 return Builtin::BI__builtin_get_spirv_spec_constant_int;
147 case BuiltinType::LongLong:
148 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
149 case BuiltinType::UShort:
150 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
151 case BuiltinType::UInt:
152 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
153 case BuiltinType::ULongLong:
154 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
155 case BuiltinType::Half:
156 return Builtin::BI__builtin_get_spirv_spec_constant_half;
157 case BuiltinType::Float:
158 return Builtin::BI__builtin_get_spirv_spec_constant_float;
159 case BuiltinType::Double:
160 return Builtin::BI__builtin_get_spirv_spec_constant_double;
167 ResourceClass ResClass) {
169 "DeclBindingInfo already added");
175 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
176 return &BindingsList.emplace_back(VD, ResClass);
180 ResourceClass ResClass) {
181 auto Entry = DeclToBindingListIndex.find(VD);
182 if (Entry != DeclToBindingListIndex.end()) {
183 for (
unsigned Index = Entry->getSecond();
184 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
186 if (BindingsList[Index].ResClass == ResClass)
187 return &BindingsList[Index];
194 return DeclToBindingListIndex.contains(VD);
206 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
209 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
210 : llvm::hlsl::ResourceClass::SRV;
222 if (
T->isArrayType() ||
T->isStructureType())
229 assert(Context.getTypeSize(
T) <= 64 &&
230 "Scalar bit widths larger than 64 not supported");
233 return Context.getTypeSize(
T) / 8;
240 constexpr unsigned CBufferAlign = 16;
241 if (
const auto *RD =
T->getAsRecordDecl()) {
243 for (
const FieldDecl *Field : RD->fields()) {
250 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
251 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
252 FieldAlign = CBufferAlign;
255 Size = llvm::alignTo(Size, FieldAlign);
262 unsigned ElementCount = AT->getSize().getZExtValue();
263 if (ElementCount == 0)
266 unsigned ElementSize =
268 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
269 return AlignedElementSize * (ElementCount - 1) + ElementSize;
273 unsigned ElementCount = VT->getNumElements();
274 unsigned ElementSize =
276 return ElementSize * ElementCount;
279 return Context.getTypeSize(
T) / 8;
290 bool HasPackOffset =
false;
291 bool HasNonPackOffset =
false;
293 VarDecl *Var = dyn_cast<VarDecl>(Field);
296 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
297 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
298 HasPackOffset =
true;
300 HasNonPackOffset =
true;
307 if (HasNonPackOffset)
314 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
315 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
316 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
317 return LHS.second->getOffsetInBytes() <
318 RHS.second->getOffsetInBytes();
320 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
321 VarDecl *Var = PackOffsetVec[i].first;
322 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
324 unsigned Begin =
Attr->getOffsetInBytes();
325 unsigned End = Begin + Size;
326 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
327 if (End > NextBegin) {
328 VarDecl *NextVar = PackOffsetVec[i + 1].first;
340 CAT = dyn_cast<ConstantArrayType>(
342 return CAT !=
nullptr;
350static const HLSLAttributedResourceType *
353 "expected array of resource records");
355 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
357 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
369 return RD->isEmpty();
398 Base.getType()->castAsCXXRecordDecl()))
409 assert(RD ==
nullptr &&
410 "there should be at most 1 record by a given name in a scope");
427 Name.append(NameBaseII->
getName());
434 size_t NameLength = Name.size();
443 Name.append(llvm::Twine(suffix).str());
444 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
451 Name.truncate(NameLength);
492 "struct is already HLSL buffer compatible");
506 LS->
addAttr(PackedAttr::CreateImplicit(AST));
510 if (
unsigned NumBases = StructDecl->
getNumBases()) {
511 assert(NumBases == 1 &&
"HLSL supports only one base type");
561 LS->
addAttr(PackedAttr::CreateImplicit(AST));
566 VarDecl *VD = dyn_cast<VarDecl>(D);
586 uint32_t ImplicitBindingOrderID) {
588 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
589 Attr->setBinding(RT, std::nullopt, 0);
590 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
597 BufDecl->setRBraceLoc(RBrace);
609 uint32_t OrderID = getNextImplicitBindingOrderID();
614 BufDecl->isCBuffer() ? RegisterType::CBuffer
624 int X,
int Y,
int Z) {
625 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
626 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
627 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
628 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
638 int Min,
int Max,
int Preferred,
639 int SpelledArgsCount) {
640 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
641 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
642 WS->getPreferred() != Preferred ||
643 WS->getSpelledArgsCount() != SpelledArgsCount) {
644 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
645 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
651 Result->setSpelledArgsCount(SpelledArgsCount);
655HLSLVkConstantIdAttr *
661 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
669 Diag(VD->getLocation(), diag::err_specialization_const);
673 if (!VD->getType().isConstQualified()) {
674 Diag(VD->getLocation(), diag::err_specialization_const);
678 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
679 if (CI->getId() != Id) {
680 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
681 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
686 HLSLVkConstantIdAttr *
Result =
693 llvm::Triple::EnvironmentType ShaderType) {
694 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
695 if (NT->getType() != ShaderType) {
696 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
697 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
701 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
704HLSLParamModifierAttr *
706 HLSLParamModifierAttr::Spelling Spelling) {
709 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
710 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
711 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
712 D->
dropAttr<HLSLParamModifierAttr>();
714 return HLSLParamModifierAttr::Create(
716 HLSLParamModifierAttr::Keyword_inout);
718 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
719 Diag(PA->getLocation(), diag::note_conflicting_attribute);
745 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
746 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
749 if (Shader->getType() != Env) {
750 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
762 case llvm::Triple::UnknownEnvironment:
763 case llvm::Triple::Library:
765 case llvm::Triple::RootSignature:
766 llvm_unreachable(
"rootsig environment has no functions");
768 llvm_unreachable(
"Unhandled environment in triple");
775 if (AnnotationAttr) {
781 const RecordType *RT = dyn_cast<RecordType>(
T);
794 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
795 assert(ShaderAttr &&
"Entry point has no shader attribute");
796 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
800 case llvm::Triple::Pixel:
801 case llvm::Triple::Vertex:
802 case llvm::Triple::Geometry:
803 case llvm::Triple::Hull:
804 case llvm::Triple::Domain:
805 case llvm::Triple::RayGeneration:
806 case llvm::Triple::Intersection:
807 case llvm::Triple::AnyHit:
808 case llvm::Triple::ClosestHit:
809 case llvm::Triple::Miss:
810 case llvm::Triple::Callable:
811 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
813 {llvm::Triple::Compute,
814 llvm::Triple::Amplification,
815 llvm::Triple::Mesh});
818 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
820 {llvm::Triple::Compute,
821 llvm::Triple::Amplification,
822 llvm::Triple::Mesh});
827 case llvm::Triple::Compute:
828 case llvm::Triple::Amplification:
829 case llvm::Triple::Mesh:
830 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
832 << llvm::Triple::getEnvironmentTypeName(ST);
835 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
836 if (Ver < VersionTuple(6, 6)) {
837 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
840 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
843 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
844 << WS << WS->getSpelledArgsCount() <<
"6.8";
849 case llvm::Triple::RootSignature:
850 llvm_unreachable(
"rootsig environment has no function entry point");
852 llvm_unreachable(
"Unhandled environment in triple");
858 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
868 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
869 assert(ShaderAttr &&
"Entry point has no shader attribute");
870 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
872 switch (AnnotationAttr->
getKind()) {
873 case attr::HLSLSV_DispatchThreadID:
874 case attr::HLSLSV_GroupIndex:
875 case attr::HLSLSV_GroupThreadID:
876 case attr::HLSLSV_GroupID:
877 if (ST == llvm::Triple::Compute)
881 case attr::HLSLSV_Position:
884 if (ST == llvm::Triple::Pixel)
889 llvm_unreachable(
"Unknown HLSLAnnotationAttr");
894 const Attr *A, llvm::Triple::EnvironmentType Stage,
895 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
897 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
898 [](llvm::Triple::EnvironmentType ST) {
900 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
902 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
903 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
904 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
907template <CastKind Kind>
910 Ty = VTy->getElementType();
915template <CastKind Kind>
927 if (LHSFloat && RHSFloat) {
955 if (LHSSigned == RHSSigned) {
956 if (IsCompAssign || IntOrder >= 0)
964 if (IntOrder != (LHSSigned ? 1 : -1)) {
965 if (IsCompAssign || RHSSigned)
973 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
974 if (IsCompAssign || LHSSigned)
990 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
991 QualType NewTy = Ctx.getExtVectorType(
1001 return CK_FloatingCast;
1003 return CK_IntegralCast;
1005 return CK_IntegralToFloating;
1007 return CK_FloatingToIntegral;
1013 bool IsCompAssign) {
1020 if (!LVecTy && IsCompAssign) {
1022 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1024 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1026 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1031 unsigned EndSz = std::numeric_limits<unsigned>::max();
1034 LSz = EndSz = LVecTy->getNumElements();
1037 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1038 "one of the above should have had a value");
1042 if (IsCompAssign && LSz != EndSz) {
1044 diag::err_hlsl_vector_compound_assignment_truncation)
1045 << LHSType << RHSType;
1051 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1056 if (!IsCompAssign && !LVecTy)
1060 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1061 return Ctx.getCommonSugaredType(LHSType, RHSType);
1069 LElTy, RElTy, IsCompAssign);
1072 "HLSL Vectors can only contain integer or floating point types");
1074 LElTy, RElTy, IsCompAssign);
1079 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1080 "Called with non-logical operator");
1082 llvm::raw_svector_ostream OS(Buff);
1084 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1085 OS << NewFnName <<
"(";
1095std::pair<IdentifierInfo *, bool>
1098 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1105 return {DeclIdent,
Found};
1116 for (
auto &RootSigElement : RootElements)
1117 Elements.push_back(RootSigElement.getElement());
1121 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1123 SignatureDecl->setImplicit();
1129 if (RootSigOverrideIdent) {
1132 if (
SemaRef.LookupQualifiedName(R, DC))
1133 return dyn_cast<HLSLRootSignatureDecl>(R.
getFoundDecl());
1141struct PerVisibilityBindingChecker {
1144 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1148 llvm::dxbc::ShaderVisibility Vis;
1153 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1155 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1156 llvm::dxil::ResourceClass RC, uint32_t Space,
1157 uint32_t LowerBound, uint32_t UpperBound,
1158 const hlsl::RootSignatureElement *Elem) {
1160 assert(BuilderIndex < Builders.size() &&
1161 "Not enough builders for visibility type");
1162 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1163 static_cast<const void *
>(Elem));
1165 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1166 "'All' visibility must come first");
1167 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1168 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1169 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1170 static_cast<const void *
>(Elem));
1172 ElemInfoMap.push_back({Elem,
Visibility,
false});
1175 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1176 auto It = llvm::lower_bound(
1178 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1179 assert(It->Elem == Elem &&
"Element not in map");
1183 bool checkOverlap() {
1184 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1185 return LHS.Elem < RHS.Elem;
1188 bool HadOverlap =
false;
1190 using llvm::hlsl::BindingInfoBuilder;
1191 auto ReportOverlap = [
this,
1192 &HadOverlap](
const BindingInfoBuilder &Builder,
1193 const llvm::hlsl::Binding &Reported) {
1197 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1198 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1199 const auto *PrevElem =
1200 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1202 ElemInfo &Info =
getInfo(Elem);
1207 Info.Diagnosed =
true;
1209 ElemInfo &PrevInfo =
getInfo(PrevElem);
1210 llvm::dxbc::ShaderVisibility CommonVis =
1211 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1214 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1215 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1216 << Reported.isUnbounded() << Reported.UpperBound
1221 this->S->
Diag(PrevElem->getLocation(),
1222 diag::note_hlsl_resource_range_here);
1225 for (BindingInfoBuilder &Builder : Builders)
1226 Builder.calculateBindingInfo(ReportOverlap);
1250 if (
const auto *ResTy =
1251 SecondField->
getType()->
getAs<HLSLAttributedResourceType>()) {
1252 return ResTy->getAttrs().IsCounter;
1260 bool HadError =
false;
1261 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1262 uint32_t UpperBound) {
1264 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1265 << LowerBound << UpperBound;
1272 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1273 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1274 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1277 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1278 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1279 ReportError(Loc, 0, 0xfffffffe);
1282 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1283 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1284 ReportError(Loc, 0, 0xffffffef);
1287 const uint32_t Version =
1288 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1289 const uint32_t VersionEnum = Version - 1;
1290 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1292 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1299 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1300 if (
const auto *Descriptor =
1301 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1302 VerifyRegister(Loc, Descriptor->Reg.Number);
1303 VerifySpace(Loc, Descriptor->Space);
1305 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1307 ReportFlagError(Loc);
1308 }
else if (
const auto *Constants =
1309 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1310 VerifyRegister(Loc, Constants->Reg.Number);
1311 VerifySpace(Loc, Constants->Space);
1312 }
else if (
const auto *Sampler =
1313 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1314 VerifyRegister(Loc, Sampler->Reg.Number);
1315 VerifySpace(Loc, Sampler->Space);
1318 "By construction, parseFloatParam can't produce a NaN from a "
1319 "float_literal token");
1321 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1322 ReportError(Loc, 0, 16);
1323 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1324 ReportFloatError(Loc, -16.f, 15.99f);
1325 }
else if (
const auto *Clause =
1326 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1328 VerifyRegister(Loc, Clause->Reg.Number);
1329 VerifySpace(Loc, Clause->Space);
1331 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1335 ReportError(Loc, 1, 0xfffffffe);
1338 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1340 ReportFlagError(Loc);
1344 PerVisibilityBindingChecker BindingChecker(
this);
1345 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1350 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1351 if (
const auto *Descriptor =
1352 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1353 uint32_t LowerBound(Descriptor->Reg.Number);
1354 uint32_t UpperBound(LowerBound);
1356 BindingChecker.trackBinding(
1357 Descriptor->Visibility,
1358 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1359 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1360 }
else if (
const auto *Constants =
1361 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1362 uint32_t LowerBound(Constants->Reg.Number);
1363 uint32_t UpperBound(LowerBound);
1365 BindingChecker.trackBinding(
1366 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1367 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1368 }
else if (
const auto *Sampler =
1369 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1370 uint32_t LowerBound(Sampler->Reg.Number);
1371 uint32_t UpperBound(LowerBound);
1373 BindingChecker.trackBinding(
1374 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1375 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1376 }
else if (
const auto *Clause =
1377 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1380 UnboundClauses.emplace_back(Clause, &RootSigElem);
1381 }
else if (
const auto *Table =
1382 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1383 assert(UnboundClauses.size() == Table->NumClauses &&
1384 "Number of unbound elements must match the number of clauses");
1385 bool HasAnySampler =
false;
1386 bool HasAnyNonSampler =
false;
1387 uint64_t Offset = 0;
1388 bool IsPrevUnbound =
false;
1389 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1391 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1392 HasAnySampler =
true;
1394 HasAnyNonSampler =
true;
1396 if (HasAnySampler && HasAnyNonSampler)
1397 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1402 if (Clause->NumDescriptors == 0)
1406 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1408 Offset = Clause->Offset;
1410 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1411 Offset, Clause->NumDescriptors);
1413 if (IsPrevUnbound && IsAppending)
1414 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1415 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1416 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1419 Offset = RangeBound + 1;
1420 IsPrevUnbound = Clause->NumDescriptors ==
1421 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1424 uint32_t LowerBound(Clause->Reg.Number);
1425 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1426 LowerBound, Clause->NumDescriptors);
1428 BindingChecker.trackBinding(
1430 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1431 LowerBound, UpperBound, ClauseElem);
1433 UnboundClauses.clear();
1437 return BindingChecker.checkOverlap();
1442 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1447 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1448 if (RS->getSignatureIdent() != Ident) {
1449 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1453 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1459 if (
auto *SignatureDecl =
1467 llvm::VersionTuple SMVersion =
1472 uint32_t ZMax = 1024;
1473 uint32_t ThreadMax = 1024;
1474 if (IsDXIL && SMVersion.getMajor() <= 4) {
1477 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1487 diag::err_hlsl_numthreads_argument_oor)
1496 diag::err_hlsl_numthreads_argument_oor)
1505 diag::err_hlsl_numthreads_argument_oor)
1510 if (
X * Y * Z > ThreadMax) {
1511 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1528 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1536 if (SpelledArgsCount > 1 &&
1540 uint32_t Preferred = 0;
1541 if (SpelledArgsCount > 2 &&
1545 if (SpelledArgsCount > 2) {
1548 diag::err_attribute_power_of_two_in_range)
1549 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1554 if (Preferred < Min || Preferred >
Max) {
1556 diag::err_attribute_power_of_two_in_range)
1557 << AL <<
Min <<
Max << Preferred;
1560 }
else if (SpelledArgsCount > 1) {
1563 diag::err_attribute_power_of_two_in_range)
1564 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1568 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1571 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1576 diag::err_attribute_power_of_two_in_range)
1577 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1582 HLSLWaveSizeAttr *NewAttr =
1606 uint32_t Binding = 0;
1621 if (!
T->hasUnsignedIntegerRepresentation() ||
1622 (VT && VT->getNumElements() > 3)) {
1623 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1624 << AL <<
"uint/uint2/uint3";
1633 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1634 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1635 << AL <<
"float/float1/float2/float3/float4";
1643 std::optional<unsigned> Index) {
1647 QualType ValueType = VD->getType();
1648 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1649 ValueType = FD->getReturnType();
1651 bool IsOutput =
false;
1652 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1659 Attr *Attribute =
nullptr;
1660 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1663 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1665 }
else if (SemanticName ==
"SV_GROUPINDEX") {
1667 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1669 }
else if (SemanticName ==
"SV_GROUPTHREADID") {
1672 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1674 }
else if (SemanticName ==
"SV_GROUPID") {
1677 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1679 }
else if (SemanticName ==
"SV_POSITION") {
1680 const auto *VT = ValueType->getAs<
VectorType>();
1681 if (!ValueType->hasFloatingRepresentation() ||
1682 (VT && VT->getNumElements() > 4))
1683 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1684 << AL <<
"float/float1/float2/float3/float4";
1687 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1695 uint32_t IndexValue, ExplicitIndex;
1698 assert(IndexValue > 0 ? ExplicitIndex :
true);
1699 std::optional<unsigned> Index =
1700 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1705 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1710 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1711 << AL <<
"shader constant in a constant buffer";
1715 uint32_t SubComponent;
1725 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1730 if (IsAggregateTy || Size > 128) {
1731 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1735 if ((Component * 32 + Size) > 128) {
1736 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1741 EltTy = VT->getElementType();
1743 if (Align > 32 && Component == 1) {
1746 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1760 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1763 llvm::Triple::EnvironmentType ShaderType;
1764 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1765 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1766 << AL << Str << ArgLoc;
1780 assert(AttrList.size() &&
"expected list of resource attributes");
1787 HLSLAttributedResourceType::Attributes ResAttrs;
1789 bool HasResourceClass =
false;
1790 for (
const Attr *A : AttrList) {
1793 LocEnd = A->getRange().getEnd();
1794 switch (A->getKind()) {
1795 case attr::HLSLResourceClass: {
1797 if (HasResourceClass) {
1798 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1799 ? diag::warn_duplicate_attribute_exact
1800 : diag::warn_duplicate_attribute)
1804 ResAttrs.ResourceClass = RC;
1805 HasResourceClass =
true;
1809 if (ResAttrs.IsROV) {
1810 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1813 ResAttrs.IsROV =
true;
1815 case attr::HLSLRawBuffer:
1816 if (ResAttrs.RawBuffer) {
1817 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1820 ResAttrs.RawBuffer =
true;
1822 case attr::HLSLIsCounter:
1823 if (ResAttrs.IsCounter) {
1824 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1827 ResAttrs.IsCounter =
true;
1829 case attr::HLSLContainedType: {
1832 if (!ContainedTy.
isNull()) {
1833 S.
Diag(A->getLocation(), ContainedTy == Ty
1834 ? diag::warn_duplicate_attribute_exact
1835 : diag::warn_duplicate_attribute)
1844 llvm_unreachable(
"unhandled resource attribute type");
1848 if (!HasResourceClass) {
1849 S.
Diag(AttrList.back()->getRange().getEnd(),
1850 diag::err_hlsl_missing_resource_class);
1855 Wrapped, ContainedTy, ResAttrs);
1857 if (LocInfo && ContainedTyInfo) {
1870 if (!
T->isHLSLResourceType()) {
1871 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1886 AttributeCommonInfo::AS_CXX11, 0, false ,
1891 case ParsedAttr::AT_HLSLResourceClass: {
1893 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1904 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1905 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1906 <<
"ResourceClass" << Identifier;
1909 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
1913 case ParsedAttr::AT_HLSLROV:
1917 case ParsedAttr::AT_HLSLRawBuffer:
1921 case ParsedAttr::AT_HLSLIsCounter:
1925 case ParsedAttr::AT_HLSLContainedType: {
1927 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1933 assert(TSI &&
"no type source info for attribute argument");
1935 diag::err_incomplete_type))
1937 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
1942 llvm_unreachable(
"unhandled HLSL attribute");
1945 HLSLResourcesTypeAttrs.emplace_back(A);
1951 if (!HLSLResourcesTypeAttrs.size())
1957 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1958 const HLSLAttributedResourceType *RT =
1965 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1967 HLSLResourcesTypeAttrs.clear();
1975 auto I = LocsForHLSLAttributedResources.find(RT);
1976 if (I != LocsForHLSLAttributedResources.end()) {
1977 LocInfo = I->second;
1978 LocsForHLSLAttributedResources.erase(I);
1987void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
1988 const RecordType *RT) {
1989 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1996 "incomplete arrays inside user defined types are not supported");
2005 if (
const HLSLAttributedResourceType *AttrResType =
2006 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2011 Bindings.addDeclBindingInfo(VD, RC);
2012 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2018 collectResourceBindingsOnUserRecordDecl(VD, RT);
2030 bool SpecifiedSpace) {
2031 int RegTypeNum =
static_cast<int>(RegType);
2034 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2035 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2040 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2041 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2042 : ResourceClass::SRV;
2052 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2056 if (
const HLSLAttributedResourceType *AttrResType =
2057 HLSLAttributedResourceType::findHandleTypeOnResource(
2074 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2075 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2080 if (RegType == RegisterType::CBuffer)
2081 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2082 else if (RegType != RegisterType::C)
2083 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2087 if (RegType == RegisterType::C)
2088 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2090 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2100 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2108 bool RegisterTypesDetected[5] = {
false};
2109 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2112 if (HLSLResourceBindingAttr *
attr =
2113 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2116 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2117 int otherRegTypeNum =
static_cast<int>(otherRegType);
2119 diag::err_hlsl_duplicate_register_annotation)
2123 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2131 bool SpecifiedSpace) {
2136 "expecting VarDecl or HLSLBufferDecl");
2147 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2149 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2150 Ty = IAT->getElementType();
2152 diag::err_incomplete_type))
2156 StringRef Slot =
"";
2157 StringRef Space =
"";
2161 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2171 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2177 SpaceLoc = Loc->
getLoc();
2180 if (Str.starts_with(
"space")) {
2182 SpaceLoc = Loc->
getLoc();
2191 std::optional<unsigned> SlotNum;
2192 unsigned SpaceNum = 0;
2195 if (!Slot.empty()) {
2197 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2200 if (RegType == RegisterType::I) {
2201 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2204 StringRef SlotNumStr = Slot.substr(1);
2206 if (SlotNumStr.getAsInteger(10, N)) {
2207 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2214 if (!Space.starts_with(
"space")) {
2215 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2218 StringRef SpaceNumStr = Space.substr(5);
2219 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2220 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2225 if (SlotNum.has_value())
2230 HLSLResourceBindingAttr *NewAttr =
2231 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2233 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2288 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2292 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2293 unsigned CurrentShaderStageBit;
2298 bool ReportOnlyShaderStageIssues;
2301 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2302 static_assert(
sizeof(
unsigned) >= 4);
2303 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2304 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2305 "ShaderType is too big for this bitmap");
2308 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2309 CurrentShaderEnvironment = ShaderType;
2310 CurrentShaderStageBit = (1 << bitmapIndex);
2313 void SetUnknownShaderStageContext() {
2314 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2315 CurrentShaderStageBit = (1 << 31);
2318 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2319 return CurrentShaderEnvironment;
2322 bool InUnknownShaderStageContext()
const {
2323 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2327 void AddToScannedFunctions(
const FunctionDecl *FD) {
2328 unsigned &ScannedStages = ScannedDecls[FD];
2329 ScannedStages |= CurrentShaderStageBit;
2332 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2334 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2335 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2338 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2339 return ScannerStages & CurrentShaderStageBit;
2342 static bool NeverBeenScanned(
unsigned ScannedStages) {
2343 return ScannedStages == 0;
2347 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2348 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2350 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2351 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2354 DiagnoseHLSLAvailability(Sema &SemaRef)
2356 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2357 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2360 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2361 void RunOnFunction(
const FunctionDecl *FD);
2363 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2364 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2366 HandleFunctionOrMethodRef(FD, DRE);
2370 bool VisitMemberExpr(MemberExpr *ME)
override {
2371 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2373 HandleFunctionOrMethodRef(FD, ME);
2378void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2381 "expected DeclRefExpr or MemberExpr");
2385 if (FD->
hasBody(FDWithBody)) {
2386 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2387 DeclsToScan.push_back(FDWithBody);
2392 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2394 CheckDeclAvailability(
2398void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2407 DeclContextsToScan.push_back(TU);
2409 while (!DeclContextsToScan.empty()) {
2410 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2411 for (
auto &D : DC->
decls()) {
2413 if (D->isImplicit())
2418 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2419 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2424 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2429 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2430 SetShaderStageContext(ShaderAttr->getType());
2439 for (
const auto *Redecl : FD->
redecls()) {
2440 if (Redecl->isInExportDeclContext()) {
2447 SetUnknownShaderStageContext();
2455void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2456 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2457 DeclsToScan.push_back(FD);
2459 while (!DeclsToScan.empty()) {
2467 const unsigned ScannedStages = GetScannedStages(FD);
2468 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2471 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2473 AddToScannedFunctions(FD);
2478bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2479 const AvailabilityAttr *AA) {
2484 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2485 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2488 llvm::Triple::EnvironmentType AttrEnv =
2489 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2491 return CurrentEnv == AttrEnv;
2494const AvailabilityAttr *
2495DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2496 AvailabilityAttr
const *PartialMatch =
nullptr;
2500 for (
const auto *A : D->
attrs()) {
2501 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2502 StringRef AttrPlatform = Avail->getPlatform()->getName();
2503 StringRef TargetPlatform =
2507 if (AttrPlatform == TargetPlatform) {
2509 if (HasMatchingEnvironmentOrNone(Avail))
2511 PartialMatch = Avail;
2515 return PartialMatch;
2520void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2521 const AvailabilityAttr *AA,
2540 if (ReportOnlyShaderStageIssues)
2546 if (InUnknownShaderStageContext())
2551 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2552 VersionTuple Introduced = AA->getIntroduced();
2561 llvm::StringRef PlatformName(
2564 llvm::StringRef CurrentEnvStr =
2565 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2567 llvm::StringRef AttrEnvStr =
2568 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2569 bool UseEnvironment = !AttrEnvStr.empty();
2571 if (EnvironmentMatches) {
2572 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2573 <<
Range << D << PlatformName << Introduced.getAsString()
2574 << UseEnvironment << CurrentEnvStr;
2576 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2580 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2581 << D << PlatformName << Introduced.getAsString()
2583 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2590 if (!DefaultCBufferDecls.empty()) {
2593 DefaultCBufferDecls);
2595 getNextImplicitBindingOrderID());
2596 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2600 for (
const Decl *VD : DefaultCBufferDecls) {
2601 const HLSLResourceBindingAttr *RBA =
2602 VD->
getAttr<HLSLResourceBindingAttr>();
2603 if (RBA && RBA->hasRegisterSlot() &&
2604 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2611 SemaRef.Consumer.HandleTopLevelDecl(DG);
2613 diagnoseAvailabilityViolations(TU);
2623 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2626 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2633 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2636 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2661 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2676 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2677 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2678 << ArgOrdinal << 5 << 0
2684 unsigned ArgIndex) {
2685 auto *Arg = TheCall->
getArg(ArgIndex);
2687 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2690 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2700 if (VecTy->getElementType()->isDoubleType())
2701 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2702 << ArgOrdinal << 1 << 0 << 1
2712 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2713 << ArgOrdinal << 5 << 1
2722 if (VecTy->getElementType()->isUnsignedIntegerType())
2725 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2726 << ArgOrdinal << 4 << 3 << 0
2735 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2736 << ArgOrdinal << 5 << 3
2752 unsigned ArgIndex) {
2761 diag::err_typecheck_expect_scalar_or_vector)
2762 << ArgType << Scalar;
2769 unsigned ArgIndex) {
2774 if (!(ArgType->isScalarType() ||
2775 (VTy && VTy->getElementType()->isScalarType()))) {
2777 diag::err_typecheck_expect_any_scalar_or_vector)
2794 diag::err_typecheck_expect_any_scalar_or_vector)
2807 diag::err_typecheck_call_different_arg_types)
2826 Arg1ScalarTy = VTy->getElementType();
2830 Arg2ScalarTy = VTy->getElementType();
2833 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2834 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2844 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2846 diag::err_typecheck_vector_lengths_not_equal)
2852 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2854 diag::err_typecheck_vector_lengths_not_equal)
2867 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2871 const HLSLAttributedResourceType *ResTy =
2875 diag::err_typecheck_expect_hlsl_resource)
2879 if (Check && Check(ResTy)) {
2881 diag::err_invalid_hlsl_resource_type)
2891 switch (BuiltinID) {
2892 case Builtin::BI__builtin_hlsl_adduint64: {
2893 if (
SemaRef.checkArgCount(TheCall, 2))
2906 if (ElementBitCount != 32) {
2908 diag::err_integer_incorrect_bit_count)
2909 << 32 << ElementBitCount;
2914 int NumElementsArg = VTy->getNumElements();
2915 if (NumElementsArg != 2 && NumElementsArg != 4) {
2917 << 1 << 64 << NumElementsArg * ElementBitCount;
2931 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2932 if (
SemaRef.checkArgCount(TheCall, 2) ||
2935 SemaRef.getASTContext().UnsignedIntTy))
2940 QualType ContainedTy = ResourceTy->getContainedType();
2943 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
2949 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2950 if (
SemaRef.checkArgCount(TheCall, 1) ||
2958 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2960 if (
SemaRef.checkArgCount(TheCall, 6) ||
2974 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2976 if (
SemaRef.checkArgCount(TheCall, 6) ||
2990 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
2992 if (
SemaRef.checkArgCount(TheCall, 3) ||
2999 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3000 auto MainAttrs = MainResType->getAttrs();
3001 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3002 MainAttrs.IsCounter =
true;
3004 MainResType->getWrappedType(), MainResType->getContainedType(),
3006 TheCall->
setType(CounterHandleTy);
3009 case Builtin::BI__builtin_hlsl_and:
3010 case Builtin::BI__builtin_hlsl_or: {
3011 if (
SemaRef.checkArgCount(TheCall, 2))
3024 case Builtin::BI__builtin_hlsl_all:
3025 case Builtin::BI__builtin_hlsl_any: {
3026 if (
SemaRef.checkArgCount(TheCall, 1))
3032 case Builtin::BI__builtin_hlsl_asdouble: {
3033 if (
SemaRef.checkArgCount(TheCall, 2))
3037 SemaRef.Context.UnsignedIntTy,
3042 SemaRef.Context.UnsignedIntTy,
3051 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3052 if (
SemaRef.BuiltinElementwiseTernaryMath(
3058 case Builtin::BI__builtin_hlsl_dot: {
3060 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3066 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3067 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3068 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3078 EltTy = VecTy->getElementType();
3079 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3092 case Builtin::BI__builtin_hlsl_select: {
3093 if (
SemaRef.checkArgCount(TheCall, 3))
3101 if (VTy && VTy->getElementType()->isBooleanType() &&
3106 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3107 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3108 if (
SemaRef.checkArgCount(TheCall, 1))
3114 diag::err_builtin_invalid_arg_type)
3117 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3121 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3122 case Builtin::BI__builtin_hlsl_elementwise_radians:
3123 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3124 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3125 if (
SemaRef.checkArgCount(TheCall, 1))
3130 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3134 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3135 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3136 if (
SemaRef.checkArgCount(TheCall, 1))
3141 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3146 case Builtin::BI__builtin_hlsl_lerp: {
3147 if (
SemaRef.checkArgCount(TheCall, 3))
3154 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3158 case Builtin::BI__builtin_hlsl_mad: {
3159 if (
SemaRef.BuiltinElementwiseTernaryMath(
3165 case Builtin::BI__builtin_hlsl_normalize: {
3166 if (
SemaRef.checkArgCount(TheCall, 1))
3177 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3178 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3186 case Builtin::BI__builtin_hlsl_step: {
3187 if (
SemaRef.checkArgCount(TheCall, 2))
3199 case Builtin::BI__builtin_hlsl_wave_active_max:
3200 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3201 if (
SemaRef.checkArgCount(TheCall, 1))
3216 case Builtin::BI__builtin_elementwise_bitreverse: {
3224 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3225 if (
SemaRef.checkArgCount(TheCall, 2))
3233 diag::err_typecheck_convert_incompatible)
3234 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3247 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3248 if (
SemaRef.checkArgCount(TheCall, 0))
3252 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3253 if (
SemaRef.checkArgCount(TheCall, 3))
3268 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3269 if (
SemaRef.checkArgCount(TheCall, 1))
3276 case Builtin::BI__builtin_elementwise_acos:
3277 case Builtin::BI__builtin_elementwise_asin:
3278 case Builtin::BI__builtin_elementwise_atan:
3279 case Builtin::BI__builtin_elementwise_atan2:
3280 case Builtin::BI__builtin_elementwise_ceil:
3281 case Builtin::BI__builtin_elementwise_cos:
3282 case Builtin::BI__builtin_elementwise_cosh:
3283 case Builtin::BI__builtin_elementwise_exp:
3284 case Builtin::BI__builtin_elementwise_exp2:
3285 case Builtin::BI__builtin_elementwise_exp10:
3286 case Builtin::BI__builtin_elementwise_floor:
3287 case Builtin::BI__builtin_elementwise_fmod:
3288 case Builtin::BI__builtin_elementwise_log:
3289 case Builtin::BI__builtin_elementwise_log2:
3290 case Builtin::BI__builtin_elementwise_log10:
3291 case Builtin::BI__builtin_elementwise_pow:
3292 case Builtin::BI__builtin_elementwise_roundeven:
3293 case Builtin::BI__builtin_elementwise_sin:
3294 case Builtin::BI__builtin_elementwise_sinh:
3295 case Builtin::BI__builtin_elementwise_sqrt:
3296 case Builtin::BI__builtin_elementwise_tan:
3297 case Builtin::BI__builtin_elementwise_tanh:
3298 case Builtin::BI__builtin_elementwise_trunc: {
3304 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3305 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3306 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3307 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3309 if (
SemaRef.checkArgCount(TheCall, 2) ||
3312 SemaRef.getASTContext().IntTy))
3315 std::optional<llvm::APSInt> Offset =
3317 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3319 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3332 WorkList.push_back(BaseTy);
3333 while (!WorkList.empty()) {
3335 T =
T.getCanonicalType().getUnqualifiedType();
3336 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3344 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3345 llvm::append_range(List, ElementFields);
3350 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3351 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3354 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3355 if (RD->isStandardLayout())
3356 RD = RD->getStandardLayoutBaseWithFields();
3360 if (RD->
isUnion() || !RD->isAggregate()) {
3366 for (
const auto *FD : RD->
fields())
3367 if (!FD->isUnnamedBitField())
3368 FieldTypes.push_back(FD->
getType());
3370 std::reverse(FieldTypes.begin(), FieldTypes.end());
3371 llvm::append_range(WorkList, FieldTypes);
3375 if (!RD->isStandardLayout()) {
3377 for (
const auto &
Base : RD->bases())
3378 FieldTypes.push_back(
Base.getType());
3379 std::reverse(FieldTypes.begin(), FieldTypes.end());
3380 llvm::append_range(WorkList, FieldTypes);
3402 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3408 int ArraySize = VT->getNumElements();
3413 QualType ElTy = VT->getElementType();
3417 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3433 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3442 return llvm::equal(T1Types, T2Types,
3444 return SemaRef.IsLayoutCompatible(LHS, RHS);
3453 bool HadError =
false;
3455 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3463 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3464 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3465 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3466 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3468 if (NSpellingIdx != OSpellingIdx) {
3470 diag::err_hlsl_param_qualifier_mismatch)
3471 << NDAttr << NewParam;
3487 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3502 llvm_unreachable(
"HLSL doesn't support pointers.");
3505 llvm_unreachable(
"HLSL doesn't support complex types.");
3507 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3509 llvm_unreachable(
"Should have returned before this");
3519 llvm_unreachable(
"HLSL doesn't support complex types.");
3521 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3526 llvm_unreachable(
"HLSL doesn't support pointers.");
3528 llvm_unreachable(
"Should have returned before this");
3534 llvm_unreachable(
"HLSL doesn't support pointers.");
3537 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3541 llvm_unreachable(
"HLSL doesn't support complex types.");
3544 llvm_unreachable(
"Unhandled scalar cast");
3551 WorkList.push_back(BaseTy);
3552 while (!WorkList.empty()) {
3554 T =
T.getCanonicalType().getUnqualifiedType();
3556 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3557 WorkList.push_back(AT->getElementType());
3560 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
3561 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3570 for (
const auto *FD : RD->
fields()) {
3571 if (FD->isBitField())
3573 WorkList.push_back(FD->
getType());
3605 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3606 if (DestTypes[I]->isUnionType())
3635 if (SrcTypes.size() < DestTypes.size())
3638 unsigned SrcSize = SrcTypes.size();
3639 unsigned DstSize = DestTypes.size();
3641 for (I = 0; I < DstSize && I < SrcSize; I++) {
3642 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3650 for (; I < SrcSize; I++) {
3651 if (SrcTypes[I]->isUnionType())
3658 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3659 "We should not get here without a parameter modifier expression");
3660 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3667 << Arg << (IsInOut ? 1 : 0);
3673 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3680 << Arg << (IsInOut ? 1 : 0);
3692 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3698 auto *OpV =
new (Ctx)
3703 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3704 tok::equal, ArgOpV, OpV);
3720 "Pointer and reference types cannot be inout or out parameters");
3721 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3731 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3737 if (
Decl->getType().hasAddressSpace())
3740 if (
Decl->getType()->isDependentType())
3772 if (
SemaRef.RequireCompleteType(
3775 diag::err_typecheck_decl_incomplete_type)) {
3789 DefaultCBufferDecls.push_back(VD);
3794 collectResourceBindingsOnVarDecl(VD);
3797 VD->
hasAttr<HLSLVkConstantIdAttr>()) {
3805 processExplicitBindingsOnDecl(VD);
3813 uint32_t OrderID = getNextImplicitBindingOrderID();
3831 uint32_t OrderID = getNextImplicitBindingOrderID();
3841bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3843 "expected resource record type");
3859 const char *CreateMethodName;
3860 if (Binding.isExplicit())
3861 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
3862 :
"__createFromBinding";
3864 CreateMethodName = HasCounter
3865 ?
"__createFromImplicitBindingWithImplicitCounter"
3866 :
"__createFromImplicitBinding";
3877 if (Binding.isExplicit()) {
3881 Args.push_back(RegSlot);
3883 uint32_t OrderID = (Binding.hasImplicitOrderID())
3884 ? Binding.getImplicitOrderID()
3885 : getNextImplicitBindingOrderID();
3889 Args.push_back(OrderId);
3892 IntegerLiteral *Space =
3895 Args.push_back(Space);
3898 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
3899 Args.push_back(RangeSize);
3902 AST, llvm::APInt(UIntTySize, 0), AST.
UnsignedIntTy, SourceLocation());
3903 Args.push_back(Index);
3905 StringRef VarName = VD->
getName();
3912 Name,
nullptr,
VK_PRValue, FPOptionsOverride());
3913 Args.push_back(NameCast);
3917 uint32_t CounterOrderID = getNextImplicitBindingOrderID();
3918 IntegerLiteral *CounterId =
3921 Args.push_back(CounterId);
3932 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod,
false,
3937 CK_FunctionToPointerDecay, DRE,
nullptr,
VK_PRValue, FPOptionsOverride());
3939 CallExpr *InitExpr =
3941 SourceLocation(), FPOptionsOverride());
3944 SemaRef.CheckCompleteVariableDeclaration(VD);
3948bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
3950 "expected array of resource records");
3961 ASTContext &AST =
SemaRef.getASTContext();
3964 CXXMethodDecl *CreateMethod =
nullptr;
3967 ResourceBindingAttrs ResourceAttrs(VD);
3968 if (ResourceAttrs.isExplicit())
3971 lookupMethod(
SemaRef, ResourceDecl,
3972 HasCounter ?
"__createFromBindingWithImplicitCounter"
3973 :
"__createFromBinding",
3977 CreateMethod = lookupMethod(
3979 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
3980 :
"__createFromImplicitBinding",
4005 return initGlobalResourceDecl(VD);
4007 return initGlobalResourceArrayDecl(VD);
4017 "expected LHS to be a resource record or array of resource records");
4018 if (Opc != BO_Assign)
4023 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
4031 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
4042void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
4044 "expected global variable that contains HLSL resource");
4047 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
4048 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
4049 ? ResourceClass::CBuffer
4050 : ResourceClass::SRV);
4063 if (
const HLSLAttributedResourceType *AttrResType =
4064 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4065 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4070 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
4071 collectResourceBindingsOnUserRecordDecl(VD, RT);
4077void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
4080 bool HasBinding =
false;
4081 for (Attr *A : VD->
attrs()) {
4085 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4086 if (!RBA || !RBA->hasRegisterSlot())
4091 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
4092 "never have an attribute created");
4094 if (RT == RegisterType::C) {
4095 if (Bindings.hasBindingInfoForDecl(VD))
4097 diag::warn_hlsl_user_defined_type_missing_member)
4098 <<
static_cast<int>(RT);
4106 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4111 diag::warn_hlsl_user_defined_type_missing_member)
4112 <<
static_cast<int>(RT);
4120class InitListTransformer {
4124 QualType *DstIt =
nullptr;
4125 Expr **ArgIt =
nullptr;
4131 bool castInitializer(Expr *E) {
4132 assert(DstIt &&
"This should always be something!");
4133 if (DstIt == DestTypes.end()) {
4135 ArgExprs.push_back(E);
4140 DstIt = DestTypes.begin();
4143 Ctx, *DstIt,
false);
4148 ArgExprs.push_back(
Init);
4153 bool buildInitializerListImpl(Expr *E) {
4155 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4156 for (
auto *SubInit :
Init->inits())
4157 if (!buildInitializerListImpl(SubInit))
4166 return castInitializer(E);
4168 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4173 for (uint64_t I = 0; I <
Size; ++I) {
4175 SizeTy, SourceLocation());
4181 if (!castInitializer(ElExpr.
get()))
4187 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4191 for (uint64_t I = 0; I <
Size; ++I) {
4193 SizeTy, SourceLocation());
4198 if (!buildInitializerListImpl(ElExpr.
get()))
4205 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4206 RecordDecls.push_back(RD);
4207 while (RecordDecls.back()->getNumBases()) {
4208 CXXRecordDecl *D = RecordDecls.back();
4210 "HLSL doesn't support multiple inheritance");
4211 RecordDecls.push_back(
4214 while (!RecordDecls.empty()) {
4215 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4216 for (
auto *FD : RD->
fields()) {
4217 if (FD->isUnnamedBitField())
4225 if (!buildInitializerListImpl(Res.
get()))
4233 Expr *generateInitListsImpl(QualType Ty) {
4234 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
4238 llvm::SmallVector<Expr *> Inits;
4239 assert(!
isa<MatrixType>(Ty) &&
"Matrix types not yet supported in HLSL");
4244 if (
auto *ATy = Ty->
getAs<VectorType>()) {
4245 ElTy = ATy->getElementType();
4246 Size = ATy->getNumElements();
4249 ElTy = VTy->getElementType();
4250 Size = VTy->getZExtSize();
4252 for (uint64_t I = 0; I <
Size; ++I)
4253 Inits.push_back(generateInitListsImpl(ElTy));
4256 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4257 RecordDecls.push_back(RD);
4258 while (RecordDecls.back()->getNumBases()) {
4259 CXXRecordDecl *D = RecordDecls.back();
4261 "HLSL doesn't support multiple inheritance");
4262 RecordDecls.push_back(
4265 while (!RecordDecls.empty()) {
4266 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4267 for (
auto *FD : RD->
fields())
4268 if (!FD->isUnnamedBitField())
4269 Inits.push_back(generateInitListsImpl(FD->
getType()));
4272 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4273 Inits, Inits.back()->getEndLoc());
4274 NewInit->setType(Ty);
4279 llvm::SmallVector<QualType, 16> DestTypes;
4280 llvm::SmallVector<Expr *, 16> ArgExprs;
4281 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4282 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4283 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4284 InitTy = Entity.
getType().getNonReferenceType();
4294 DstIt = DestTypes.begin();
4297 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4299 Expr *generateInitLists() {
4300 assert(!ArgExprs.empty() &&
4301 "Call buildInitializerList to generate argument expressions.");
4302 ArgIt = ArgExprs.begin();
4304 return generateInitListsImpl(InitTy);
4305 llvm::SmallVector<Expr *> Inits;
4306 while (ArgIt != ArgExprs.end())
4307 Inits.push_back(generateInitListsImpl(InitTy));
4309 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4310 Inits, Inits.back()->getEndLoc());
4311 llvm::APInt ArySize(64, Inits.size());
4313 ArraySizeModifier::Normal, 0));
4322 if (
Init->getType()->isScalarType())
4325 InitListTransformer ILT(
SemaRef, Entity);
4327 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4335 Init->setInit(I, E);
4337 if (!ILT.buildInitializerList(E))
4340 size_t ExpectedSize = ILT.DestTypes.size();
4341 size_t ActualSize = ILT.ArgExprs.size();
4342 if (ExpectedSize == 0 && ActualSize == 0)
4351 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4358 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4359 if (ExpectedSize != ActualSize) {
4360 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4361 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4362 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4369 Init->resizeInits(Ctx, NewInit->getNumInits());
4370 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4371 Init->updateInit(Ctx, I, NewInit->getInit(I));
4376 const HLSLVkConstantIdAttr *ConstIdAttr =
4377 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4384 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4394 int ConstantID = ConstIdAttr->getId();
4395 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4397 ConstIdAttr->getLocation());
4401 if (
C->getType()->getCanonicalTypeUnqualified() !=
4405 Context.getTrivialTypeSourceInfo(
4406 Init->getType(),
Init->getExprLoc()),
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static bool isResourceRecordTypeOrArrayOf(VarDecl *VD)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static const HLSLAttributedResourceType * getResourceArrayHandleType(VarDecl *VD)
static RegisterType getRegisterType(ResourceClass RC)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool hasCounterHandle(const CXXRecordDecl *RD)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool isValidWaveSizeValue(unsigned Value)
static bool IsDefaultBufferConstantDecl(VarDecl *VD)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
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_iterator field_end() const
field_range fields() const
field_iterator field_begin() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
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.
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const