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);
1236 bool HadError =
false;
1237 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1238 uint32_t UpperBound) {
1240 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1241 << LowerBound << UpperBound;
1248 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1249 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1250 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1253 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1254 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1255 ReportError(Loc, 0, 0xfffffffe);
1258 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1259 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1260 ReportError(Loc, 0, 0xffffffef);
1263 const uint32_t Version =
1264 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1265 const uint32_t VersionEnum = Version - 1;
1266 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1268 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1275 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1276 if (
const auto *Descriptor =
1277 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1278 VerifyRegister(Loc, Descriptor->Reg.Number);
1279 VerifySpace(Loc, Descriptor->Space);
1281 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(
1282 Version, llvm::to_underlying(Descriptor->Flags)))
1283 ReportFlagError(Loc);
1284 }
else if (
const auto *Constants =
1285 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1286 VerifyRegister(Loc, Constants->Reg.Number);
1287 VerifySpace(Loc, Constants->Space);
1288 }
else if (
const auto *Sampler =
1289 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1290 VerifyRegister(Loc, Sampler->Reg.Number);
1291 VerifySpace(Loc, Sampler->Space);
1294 "By construction, parseFloatParam can't produce a NaN from a "
1295 "float_literal token");
1297 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1298 ReportError(Loc, 0, 16);
1299 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1300 ReportFloatError(Loc, -16.f, 15.99f);
1301 }
else if (
const auto *Clause =
1302 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1304 VerifyRegister(Loc, Clause->Reg.Number);
1305 VerifySpace(Loc, Clause->Space);
1307 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1311 ReportError(Loc, 1, 0xfffffffe);
1314 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1316 ReportFlagError(Loc);
1320 PerVisibilityBindingChecker BindingChecker(
this);
1321 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1326 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1327 if (
const auto *Descriptor =
1328 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1329 uint32_t LowerBound(Descriptor->Reg.Number);
1330 uint32_t UpperBound(LowerBound);
1332 BindingChecker.trackBinding(
1333 Descriptor->Visibility,
1334 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1335 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1336 }
else if (
const auto *Constants =
1337 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1338 uint32_t LowerBound(Constants->Reg.Number);
1339 uint32_t UpperBound(LowerBound);
1341 BindingChecker.trackBinding(
1342 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1343 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1344 }
else if (
const auto *Sampler =
1345 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1346 uint32_t LowerBound(Sampler->Reg.Number);
1347 uint32_t UpperBound(LowerBound);
1349 BindingChecker.trackBinding(
1350 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1351 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1352 }
else if (
const auto *Clause =
1353 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1356 UnboundClauses.emplace_back(Clause, &RootSigElem);
1357 }
else if (
const auto *Table =
1358 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1359 assert(UnboundClauses.size() == Table->NumClauses &&
1360 "Number of unbound elements must match the number of clauses");
1361 bool HasAnySampler =
false;
1362 bool HasAnyNonSampler =
false;
1363 uint32_t Offset = 0;
1364 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1366 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1367 HasAnySampler =
true;
1369 HasAnyNonSampler =
true;
1371 if (HasAnySampler && HasAnyNonSampler)
1372 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1377 if (Clause->NumDescriptors == 0)
1380 if (Clause->Offset !=
1381 llvm::hlsl::rootsig::DescriptorTableOffsetAppend) {
1383 Offset = Clause->Offset;
1386 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1387 Offset, Clause->NumDescriptors);
1389 if (!llvm::hlsl::rootsig::verifyBoundOffset(Offset)) {
1391 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1392 }
else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound)) {
1394 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1397 Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded
1398 ? uint32_t(RangeBound)
1399 : uint32_t(RangeBound + 1);
1402 uint32_t LowerBound(Clause->Reg.Number);
1403 uint32_t UpperBound = Clause->NumDescriptors == ~0u
1405 : LowerBound + Clause->NumDescriptors - 1;
1407 BindingChecker.trackBinding(
1409 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1410 LowerBound, UpperBound, ClauseElem);
1412 UnboundClauses.clear();
1416 return BindingChecker.checkOverlap();
1421 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1426 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1427 if (RS->getSignatureIdent() != Ident) {
1428 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1432 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1438 if (
auto *SignatureDecl =
1446 llvm::VersionTuple SMVersion =
1451 uint32_t ZMax = 1024;
1452 uint32_t ThreadMax = 1024;
1453 if (IsDXIL && SMVersion.getMajor() <= 4) {
1456 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1466 diag::err_hlsl_numthreads_argument_oor)
1475 diag::err_hlsl_numthreads_argument_oor)
1484 diag::err_hlsl_numthreads_argument_oor)
1489 if (
X * Y * Z > ThreadMax) {
1490 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1507 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1515 if (SpelledArgsCount > 1 &&
1519 uint32_t Preferred = 0;
1520 if (SpelledArgsCount > 2 &&
1524 if (SpelledArgsCount > 2) {
1527 diag::err_attribute_power_of_two_in_range)
1528 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1533 if (Preferred < Min || Preferred >
Max) {
1535 diag::err_attribute_power_of_two_in_range)
1536 << AL <<
Min <<
Max << Preferred;
1539 }
else if (SpelledArgsCount > 1) {
1542 diag::err_attribute_power_of_two_in_range)
1543 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1547 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1550 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1555 diag::err_attribute_power_of_two_in_range)
1556 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1561 HLSLWaveSizeAttr *NewAttr =
1589 uint32_t Binding = 0;
1604 if (!
T->hasUnsignedIntegerRepresentation() ||
1605 (VT && VT->getNumElements() > 3)) {
1606 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1607 << AL <<
"uint/uint2/uint3";
1616 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1617 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1618 << AL <<
"float/float1/float2/float3/float4";
1626 std::optional<unsigned> Index) {
1630 QualType ValueType = VD->getType();
1631 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1632 ValueType = FD->getReturnType();
1634 bool IsOutput =
false;
1635 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1642 Attr *Attribute =
nullptr;
1643 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1646 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1648 }
else if (SemanticName ==
"SV_GROUPINDEX") {
1650 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1652 }
else if (SemanticName ==
"SV_GROUPTHREADID") {
1655 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1657 }
else if (SemanticName ==
"SV_GROUPID") {
1660 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1662 }
else if (SemanticName ==
"SV_POSITION") {
1663 const auto *VT = ValueType->getAs<
VectorType>();
1664 if (!ValueType->hasFloatingRepresentation() ||
1665 (VT && VT->getNumElements() > 4))
1666 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1667 << AL <<
"float/float1/float2/float3/float4";
1670 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1678 uint32_t IndexValue, ExplicitIndex;
1681 assert(IndexValue > 0 ? ExplicitIndex :
true);
1682 std::optional<unsigned> Index =
1683 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1688 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1693 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1694 << AL <<
"shader constant in a constant buffer";
1698 uint32_t SubComponent;
1708 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1713 if (IsAggregateTy || Size > 128) {
1714 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1718 if ((Component * 32 + Size) > 128) {
1719 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1724 EltTy = VT->getElementType();
1726 if (Align > 32 && Component == 1) {
1729 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1743 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1746 llvm::Triple::EnvironmentType ShaderType;
1747 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1748 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1749 << AL << Str << ArgLoc;
1763 assert(AttrList.size() &&
"expected list of resource attributes");
1770 HLSLAttributedResourceType::Attributes ResAttrs;
1772 bool HasResourceClass =
false;
1773 for (
const Attr *A : AttrList) {
1776 LocEnd = A->getRange().getEnd();
1777 switch (A->getKind()) {
1778 case attr::HLSLResourceClass: {
1780 if (HasResourceClass) {
1781 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1782 ? diag::warn_duplicate_attribute_exact
1783 : diag::warn_duplicate_attribute)
1787 ResAttrs.ResourceClass = RC;
1788 HasResourceClass =
true;
1792 if (ResAttrs.IsROV) {
1793 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1796 ResAttrs.IsROV =
true;
1798 case attr::HLSLRawBuffer:
1799 if (ResAttrs.RawBuffer) {
1800 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1803 ResAttrs.RawBuffer =
true;
1805 case attr::HLSLContainedType: {
1808 if (!ContainedTy.
isNull()) {
1809 S.
Diag(A->getLocation(), ContainedTy == Ty
1810 ? diag::warn_duplicate_attribute_exact
1811 : diag::warn_duplicate_attribute)
1820 llvm_unreachable(
"unhandled resource attribute type");
1824 if (!HasResourceClass) {
1825 S.
Diag(AttrList.back()->getRange().getEnd(),
1826 diag::err_hlsl_missing_resource_class);
1831 Wrapped, ContainedTy, ResAttrs);
1833 if (LocInfo && ContainedTyInfo) {
1846 if (!
T->isHLSLResourceType()) {
1847 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1862 AttributeCommonInfo::AS_CXX11, 0, false ,
1867 case ParsedAttr::AT_HLSLResourceClass: {
1869 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1880 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1881 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1882 <<
"ResourceClass" << Identifier;
1885 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
1889 case ParsedAttr::AT_HLSLROV:
1893 case ParsedAttr::AT_HLSLRawBuffer:
1897 case ParsedAttr::AT_HLSLContainedType: {
1899 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1905 assert(TSI &&
"no type source info for attribute argument");
1907 diag::err_incomplete_type))
1909 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
1914 llvm_unreachable(
"unhandled HLSL attribute");
1917 HLSLResourcesTypeAttrs.emplace_back(A);
1923 if (!HLSLResourcesTypeAttrs.size())
1929 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1930 const HLSLAttributedResourceType *RT =
1937 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1939 HLSLResourcesTypeAttrs.clear();
1947 auto I = LocsForHLSLAttributedResources.find(RT);
1948 if (I != LocsForHLSLAttributedResources.end()) {
1949 LocInfo = I->second;
1950 LocsForHLSLAttributedResources.erase(I);
1959void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
1960 const RecordType *RT) {
1961 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1968 "incomplete arrays inside user defined types are not supported");
1977 if (
const HLSLAttributedResourceType *AttrResType =
1978 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
1983 Bindings.addDeclBindingInfo(VD, RC);
1984 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1990 collectResourceBindingsOnUserRecordDecl(VD, RT);
2002 bool SpecifiedSpace) {
2003 int RegTypeNum =
static_cast<int>(RegType);
2006 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2007 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2012 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2013 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2014 : ResourceClass::SRV;
2024 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2028 if (
const HLSLAttributedResourceType *AttrResType =
2029 HLSLAttributedResourceType::findHandleTypeOnResource(
2046 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2047 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2052 if (RegType == RegisterType::CBuffer)
2053 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2054 else if (RegType != RegisterType::C)
2055 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2059 if (RegType == RegisterType::C)
2060 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2062 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2072 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2080 bool RegisterTypesDetected[5] = {
false};
2081 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2084 if (HLSLResourceBindingAttr *
attr =
2085 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2088 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2089 int otherRegTypeNum =
static_cast<int>(otherRegType);
2091 diag::err_hlsl_duplicate_register_annotation)
2095 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2103 bool SpecifiedSpace) {
2108 "expecting VarDecl or HLSLBufferDecl");
2119 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2121 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2122 Ty = IAT->getElementType();
2124 diag::err_incomplete_type))
2128 StringRef Slot =
"";
2129 StringRef Space =
"";
2133 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2143 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2149 SpaceLoc = Loc->
getLoc();
2152 if (Str.starts_with(
"space")) {
2154 SpaceLoc = Loc->
getLoc();
2163 std::optional<unsigned> SlotNum;
2164 unsigned SpaceNum = 0;
2167 if (!Slot.empty()) {
2169 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2172 if (RegType == RegisterType::I) {
2173 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2176 StringRef SlotNumStr = Slot.substr(1);
2178 if (SlotNumStr.getAsInteger(10, N)) {
2179 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2186 if (!Space.starts_with(
"space")) {
2187 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2190 StringRef SpaceNumStr = Space.substr(5);
2191 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2192 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2197 if (SlotNum.has_value())
2202 HLSLResourceBindingAttr *NewAttr =
2203 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2205 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2260 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2264 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2265 unsigned CurrentShaderStageBit;
2270 bool ReportOnlyShaderStageIssues;
2273 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2274 static_assert(
sizeof(
unsigned) >= 4);
2275 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2276 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2277 "ShaderType is too big for this bitmap");
2280 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2281 CurrentShaderEnvironment = ShaderType;
2282 CurrentShaderStageBit = (1 << bitmapIndex);
2285 void SetUnknownShaderStageContext() {
2286 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2287 CurrentShaderStageBit = (1 << 31);
2290 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2291 return CurrentShaderEnvironment;
2294 bool InUnknownShaderStageContext()
const {
2295 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2299 void AddToScannedFunctions(
const FunctionDecl *FD) {
2300 unsigned &ScannedStages = ScannedDecls[FD];
2301 ScannedStages |= CurrentShaderStageBit;
2304 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2306 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2307 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2310 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2311 return ScannerStages & CurrentShaderStageBit;
2314 static bool NeverBeenScanned(
unsigned ScannedStages) {
2315 return ScannedStages == 0;
2319 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2320 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2322 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2323 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2326 DiagnoseHLSLAvailability(Sema &SemaRef)
2328 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2329 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2332 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2333 void RunOnFunction(
const FunctionDecl *FD);
2335 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2336 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2338 HandleFunctionOrMethodRef(FD, DRE);
2342 bool VisitMemberExpr(MemberExpr *ME)
override {
2343 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2345 HandleFunctionOrMethodRef(FD, ME);
2350void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2353 "expected DeclRefExpr or MemberExpr");
2357 if (FD->
hasBody(FDWithBody)) {
2358 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2359 DeclsToScan.push_back(FDWithBody);
2364 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2366 CheckDeclAvailability(
2370void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2379 DeclContextsToScan.push_back(TU);
2381 while (!DeclContextsToScan.empty()) {
2382 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2383 for (
auto &D : DC->
decls()) {
2385 if (D->isImplicit())
2390 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2391 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2396 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2401 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2402 SetShaderStageContext(ShaderAttr->getType());
2411 for (
const auto *Redecl : FD->
redecls()) {
2412 if (Redecl->isInExportDeclContext()) {
2419 SetUnknownShaderStageContext();
2427void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2428 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2429 DeclsToScan.push_back(FD);
2431 while (!DeclsToScan.empty()) {
2439 const unsigned ScannedStages = GetScannedStages(FD);
2440 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2443 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2445 AddToScannedFunctions(FD);
2450bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2451 const AvailabilityAttr *AA) {
2456 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2457 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2460 llvm::Triple::EnvironmentType AttrEnv =
2461 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2463 return CurrentEnv == AttrEnv;
2466const AvailabilityAttr *
2467DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2468 AvailabilityAttr
const *PartialMatch =
nullptr;
2472 for (
const auto *A : D->
attrs()) {
2473 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2474 StringRef AttrPlatform = Avail->getPlatform()->getName();
2475 StringRef TargetPlatform =
2479 if (AttrPlatform == TargetPlatform) {
2481 if (HasMatchingEnvironmentOrNone(Avail))
2483 PartialMatch = Avail;
2487 return PartialMatch;
2492void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2493 const AvailabilityAttr *AA,
2512 if (ReportOnlyShaderStageIssues)
2518 if (InUnknownShaderStageContext())
2523 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2524 VersionTuple Introduced = AA->getIntroduced();
2533 llvm::StringRef PlatformName(
2536 llvm::StringRef CurrentEnvStr =
2537 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2539 llvm::StringRef AttrEnvStr =
2540 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2541 bool UseEnvironment = !AttrEnvStr.empty();
2543 if (EnvironmentMatches) {
2544 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2545 <<
Range << D << PlatformName << Introduced.getAsString()
2546 << UseEnvironment << CurrentEnvStr;
2548 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2552 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2553 << D << PlatformName << Introduced.getAsString()
2555 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2562 if (!DefaultCBufferDecls.empty()) {
2565 DefaultCBufferDecls);
2567 getNextImplicitBindingOrderID());
2568 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2572 for (
const Decl *VD : DefaultCBufferDecls) {
2573 const HLSLResourceBindingAttr *RBA =
2574 VD->
getAttr<HLSLResourceBindingAttr>();
2575 if (RBA && RBA->hasRegisterSlot() &&
2576 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2583 SemaRef.Consumer.HandleTopLevelDecl(DG);
2585 diagnoseAvailabilityViolations(TU);
2595 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2598 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2605 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2608 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2633 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2648 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2649 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2650 << ArgOrdinal << 5 << 0
2656 unsigned ArgIndex) {
2657 auto *Arg = TheCall->
getArg(ArgIndex);
2659 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2662 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2672 if (VecTy->getElementType()->isDoubleType())
2673 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2674 << ArgOrdinal << 1 << 0 << 1
2684 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2685 << ArgOrdinal << 5 << 1
2694 if (VecTy->getElementType()->isUnsignedIntegerType())
2697 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2698 << ArgOrdinal << 4 << 3 << 0
2707 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2708 << ArgOrdinal << 5 << 3
2724 unsigned ArgIndex) {
2733 diag::err_typecheck_expect_scalar_or_vector)
2734 << ArgType << Scalar;
2741 unsigned ArgIndex) {
2746 if (!(ArgType->isScalarType() ||
2747 (VTy && VTy->getElementType()->isScalarType()))) {
2749 diag::err_typecheck_expect_any_scalar_or_vector)
2766 diag::err_typecheck_expect_any_scalar_or_vector)
2779 diag::err_typecheck_call_different_arg_types)
2798 Arg1ScalarTy = VTy->getElementType();
2802 Arg2ScalarTy = VTy->getElementType();
2805 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2806 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2816 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2818 diag::err_typecheck_vector_lengths_not_equal)
2824 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2826 diag::err_typecheck_vector_lengths_not_equal)
2839 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2843 const HLSLAttributedResourceType *ResTy =
2847 diag::err_typecheck_expect_hlsl_resource)
2851 if (Check && Check(ResTy)) {
2853 diag::err_invalid_hlsl_resource_type)
2863 switch (BuiltinID) {
2864 case Builtin::BI__builtin_hlsl_adduint64: {
2865 if (
SemaRef.checkArgCount(TheCall, 2))
2878 if (ElementBitCount != 32) {
2880 diag::err_integer_incorrect_bit_count)
2881 << 32 << ElementBitCount;
2886 int NumElementsArg = VTy->getNumElements();
2887 if (NumElementsArg != 2 && NumElementsArg != 4) {
2889 << 1 << 64 << NumElementsArg * ElementBitCount;
2903 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2904 if (
SemaRef.checkArgCount(TheCall, 2) ||
2907 SemaRef.getASTContext().UnsignedIntTy))
2912 QualType ContainedTy = ResourceTy->getContainedType();
2915 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
2921 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2922 if (
SemaRef.checkArgCount(TheCall, 1) ||
2930 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2932 if (
SemaRef.checkArgCount(TheCall, 6) ||
2946 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2948 if (
SemaRef.checkArgCount(TheCall, 6) ||
2962 case Builtin::BI__builtin_hlsl_and:
2963 case Builtin::BI__builtin_hlsl_or: {
2964 if (
SemaRef.checkArgCount(TheCall, 2))
2977 case Builtin::BI__builtin_hlsl_all:
2978 case Builtin::BI__builtin_hlsl_any: {
2979 if (
SemaRef.checkArgCount(TheCall, 1))
2985 case Builtin::BI__builtin_hlsl_asdouble: {
2986 if (
SemaRef.checkArgCount(TheCall, 2))
2990 SemaRef.Context.UnsignedIntTy,
2995 SemaRef.Context.UnsignedIntTy,
3004 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3005 if (
SemaRef.BuiltinElementwiseTernaryMath(
3011 case Builtin::BI__builtin_hlsl_dot: {
3013 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3019 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3020 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3021 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3031 EltTy = VecTy->getElementType();
3032 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3045 case Builtin::BI__builtin_hlsl_select: {
3046 if (
SemaRef.checkArgCount(TheCall, 3))
3054 if (VTy && VTy->getElementType()->isBooleanType() &&
3059 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3060 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3061 if (
SemaRef.checkArgCount(TheCall, 1))
3067 diag::err_builtin_invalid_arg_type)
3070 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3074 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3075 case Builtin::BI__builtin_hlsl_elementwise_radians:
3076 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3077 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3078 if (
SemaRef.checkArgCount(TheCall, 1))
3083 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3087 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
3088 if (
SemaRef.checkArgCount(TheCall, 1))
3093 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3098 case Builtin::BI__builtin_hlsl_lerp: {
3099 if (
SemaRef.checkArgCount(TheCall, 3))
3106 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3110 case Builtin::BI__builtin_hlsl_mad: {
3111 if (
SemaRef.BuiltinElementwiseTernaryMath(
3117 case Builtin::BI__builtin_hlsl_normalize: {
3118 if (
SemaRef.checkArgCount(TheCall, 1))
3129 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3130 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3138 case Builtin::BI__builtin_hlsl_step: {
3139 if (
SemaRef.checkArgCount(TheCall, 2))
3151 case Builtin::BI__builtin_hlsl_wave_active_max:
3152 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3153 if (
SemaRef.checkArgCount(TheCall, 1))
3168 case Builtin::BI__builtin_elementwise_bitreverse: {
3176 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3177 if (
SemaRef.checkArgCount(TheCall, 2))
3185 diag::err_typecheck_convert_incompatible)
3186 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3199 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3200 if (
SemaRef.checkArgCount(TheCall, 0))
3204 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3205 if (
SemaRef.checkArgCount(TheCall, 3))
3220 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3221 if (
SemaRef.checkArgCount(TheCall, 1))
3228 case Builtin::BI__builtin_elementwise_acos:
3229 case Builtin::BI__builtin_elementwise_asin:
3230 case Builtin::BI__builtin_elementwise_atan:
3231 case Builtin::BI__builtin_elementwise_atan2:
3232 case Builtin::BI__builtin_elementwise_ceil:
3233 case Builtin::BI__builtin_elementwise_cos:
3234 case Builtin::BI__builtin_elementwise_cosh:
3235 case Builtin::BI__builtin_elementwise_exp:
3236 case Builtin::BI__builtin_elementwise_exp2:
3237 case Builtin::BI__builtin_elementwise_exp10:
3238 case Builtin::BI__builtin_elementwise_floor:
3239 case Builtin::BI__builtin_elementwise_fmod:
3240 case Builtin::BI__builtin_elementwise_log:
3241 case Builtin::BI__builtin_elementwise_log2:
3242 case Builtin::BI__builtin_elementwise_log10:
3243 case Builtin::BI__builtin_elementwise_pow:
3244 case Builtin::BI__builtin_elementwise_roundeven:
3245 case Builtin::BI__builtin_elementwise_sin:
3246 case Builtin::BI__builtin_elementwise_sinh:
3247 case Builtin::BI__builtin_elementwise_sqrt:
3248 case Builtin::BI__builtin_elementwise_tan:
3249 case Builtin::BI__builtin_elementwise_tanh:
3250 case Builtin::BI__builtin_elementwise_trunc: {
3256 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3257 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3258 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3259 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3261 if (
SemaRef.checkArgCount(TheCall, 2) ||
3264 SemaRef.getASTContext().IntTy))
3267 std::optional<llvm::APSInt> Offset =
3269 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3271 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3284 WorkList.push_back(BaseTy);
3285 while (!WorkList.empty()) {
3287 T =
T.getCanonicalType().getUnqualifiedType();
3289 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3297 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3298 llvm::append_range(List, ElementFields);
3303 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3304 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3307 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3308 if (RD->isStandardLayout())
3309 RD = RD->getStandardLayoutBaseWithFields();
3313 if (RD->
isUnion() || !RD->isAggregate()) {
3319 for (
const auto *FD : RD->
fields())
3320 FieldTypes.push_back(FD->
getType());
3322 std::reverse(FieldTypes.begin(), FieldTypes.end());
3323 llvm::append_range(WorkList, FieldTypes);
3327 if (!RD->isStandardLayout()) {
3329 for (
const auto &
Base : RD->bases())
3330 FieldTypes.push_back(
Base.getType());
3331 std::reverse(FieldTypes.begin(), FieldTypes.end());
3332 llvm::append_range(WorkList, FieldTypes);
3354 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3360 int ArraySize = VT->getNumElements();
3365 QualType ElTy = VT->getElementType();
3369 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3385 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3394 return llvm::equal(T1Types, T2Types,
3396 return SemaRef.IsLayoutCompatible(LHS, RHS);
3405 bool HadError =
false;
3407 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3415 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3416 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3417 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3418 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3420 if (NSpellingIdx != OSpellingIdx) {
3422 diag::err_hlsl_param_qualifier_mismatch)
3423 << NDAttr << NewParam;
3439 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3454 llvm_unreachable(
"HLSL doesn't support pointers.");
3457 llvm_unreachable(
"HLSL doesn't support complex types.");
3459 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3461 llvm_unreachable(
"Should have returned before this");
3471 llvm_unreachable(
"HLSL doesn't support complex types.");
3473 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3478 llvm_unreachable(
"HLSL doesn't support pointers.");
3480 llvm_unreachable(
"Should have returned before this");
3486 llvm_unreachable(
"HLSL doesn't support pointers.");
3489 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3493 llvm_unreachable(
"HLSL doesn't support complex types.");
3496 llvm_unreachable(
"Unhandled scalar cast");
3503 WorkList.push_back(BaseTy);
3504 while (!WorkList.empty()) {
3506 T =
T.getCanonicalType().getUnqualifiedType();
3508 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3509 WorkList.push_back(AT->getElementType());
3512 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
3513 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3522 for (
const auto *FD : RD->
fields()) {
3523 if (FD->isBitField())
3525 WorkList.push_back(FD->
getType());
3560 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3561 if (DestTypes[I]->isUnionType())
3593 if (SrcTypes.size() < DestTypes.size())
3596 unsigned SrcSize = SrcTypes.size();
3597 unsigned DstSize = DestTypes.size();
3599 for (I = 0; I < DstSize && I < SrcSize; I++) {
3600 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3608 for (; I < SrcSize; I++) {
3609 if (SrcTypes[I]->isUnionType())
3616 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3617 "We should not get here without a parameter modifier expression");
3618 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3625 << Arg << (IsInOut ? 1 : 0);
3631 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3638 << Arg << (IsInOut ? 1 : 0);
3650 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3656 auto *OpV =
new (Ctx)
3661 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3662 tok::equal, ArgOpV, OpV);
3678 "Pointer and reference types cannot be inout or out parameters");
3679 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3689 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3695 if (
Decl->getType().hasAddressSpace())
3698 if (
Decl->getType()->isDependentType())
3730 if (
SemaRef.RequireCompleteType(
3733 diag::err_typecheck_decl_incomplete_type)) {
3747 DefaultCBufferDecls.push_back(VD);
3752 collectResourceBindingsOnVarDecl(VD);
3755 VD->
hasAttr<HLSLVkConstantIdAttr>()) {
3763 processExplicitBindingsOnDecl(VD);
3769 if (!VD->
hasAttr<HLSLVkBindingAttr>()) {
3770 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3771 if (!RBA || !RBA->hasRegisterSlot()) {
3772 uint32_t OrderID = getNextImplicitBindingOrderID();
3774 RBA->setImplicitBindingOrderID(OrderID);
3807void SemaHLSL::createResourceRecordCtorArgs(
3808 const Type *ResourceTy, StringRef VarName, HLSLResourceBindingAttr *RBA,
3809 HLSLVkBindingAttr *VkBinding, uint32_t ArrayIndex,
3811 std::optional<uint32_t> RegisterSlot;
3814 RegisterSlot = VkBinding->getBinding();
3815 SpaceNo = VkBinding->getSet();
3817 if (RBA->hasRegisterSlot())
3818 RegisterSlot = RBA->getSlotNumber();
3819 SpaceNo = RBA->getSpaceNumber();
3822 ASTContext &AST =
SemaRef.getASTContext();
3826 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
3827 IntegerLiteral *Index =
3830 IntegerLiteral *Space =
3839 if (RegisterSlot.has_value()) {
3841 AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.
UnsignedIntTy,
3843 Args.append({RegSlot, Space, RangeSize, Index, Name});
3846 uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
3847 ? RBA->getImplicitBindingOrderID()
3848 : getNextImplicitBindingOrderID();
3849 IntegerLiteral *OrderId =
3852 Args.append({Space, RangeSize, Index, OrderId, Name});
3856bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3857 SmallVector<Expr *> Args;
3859 VD->
getAttr<HLSLResourceBindingAttr>(),
3860 VD->
getAttr<HLSLVkBindingAttr>(), 0, Args);
3864bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
3866 "expected array of resource records");
3874 SmallVector<Expr *> Args;
3877 VD->
getAttr<HLSLResourceBindingAttr>(),
3878 VD->
getAttr<HLSLVkBindingAttr>(), 0, Args);
3881 InitializedEntity Entity =
3884 InitializationSequence InitSeq(
SemaRef, Entity, Kind, Args);
3885 if (InitSeq.Failed())
3906 return initGlobalResourceDecl(VD);
3908 return initGlobalResourceArrayDecl(VD);
3915void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
3917 "expected global variable that contains HLSL resource");
3920 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
3921 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
3922 ? ResourceClass::CBuffer
3923 : ResourceClass::SRV);
3936 if (
const HLSLAttributedResourceType *AttrResType =
3937 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
3938 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
3943 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
3944 collectResourceBindingsOnUserRecordDecl(VD, RT);
3950void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
3953 bool HasBinding =
false;
3954 for (Attr *A : VD->
attrs()) {
3958 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
3959 if (!RBA || !RBA->hasRegisterSlot())
3964 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
3965 "never have an attribute created");
3967 if (RT == RegisterType::C) {
3968 if (Bindings.hasBindingInfoForDecl(VD))
3970 diag::warn_hlsl_user_defined_type_missing_member)
3971 <<
static_cast<int>(RT);
3979 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
3984 diag::warn_hlsl_user_defined_type_missing_member)
3985 <<
static_cast<int>(RT);
3993class InitListTransformer {
3997 QualType *DstIt =
nullptr;
3998 Expr **ArgIt =
nullptr;
4004 bool castInitializer(Expr *E) {
4005 assert(DstIt &&
"This should always be something!");
4006 if (DstIt == DestTypes.end()) {
4008 ArgExprs.push_back(E);
4013 DstIt = DestTypes.begin();
4016 Ctx, *DstIt,
false);
4021 ArgExprs.push_back(
Init);
4026 bool buildInitializerListImpl(Expr *E) {
4028 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4029 for (
auto *SubInit :
Init->inits())
4030 if (!buildInitializerListImpl(SubInit))
4039 return castInitializer(E);
4041 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4046 for (uint64_t I = 0; I <
Size; ++I) {
4048 SizeTy, SourceLocation());
4054 if (!castInitializer(ElExpr.
get()))
4060 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4064 for (uint64_t I = 0; I <
Size; ++I) {
4066 SizeTy, SourceLocation());
4071 if (!buildInitializerListImpl(ElExpr.
get()))
4078 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4079 RecordDecls.push_back(RD);
4080 while (RecordDecls.back()->getNumBases()) {
4081 CXXRecordDecl *D = RecordDecls.back();
4083 "HLSL doesn't support multiple inheritance");
4084 RecordDecls.push_back(
4087 while (!RecordDecls.empty()) {
4088 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4089 for (
auto *FD : RD->
fields()) {
4096 if (!buildInitializerListImpl(Res.
get()))
4104 Expr *generateInitListsImpl(QualType Ty) {
4105 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
4109 llvm::SmallVector<Expr *> Inits;
4110 assert(!
isa<MatrixType>(Ty) &&
"Matrix types not yet supported in HLSL");
4115 if (
auto *ATy = Ty->
getAs<VectorType>()) {
4116 ElTy = ATy->getElementType();
4117 Size = ATy->getNumElements();
4120 ElTy = VTy->getElementType();
4121 Size = VTy->getZExtSize();
4123 for (uint64_t I = 0; I <
Size; ++I)
4124 Inits.push_back(generateInitListsImpl(ElTy));
4127 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4128 RecordDecls.push_back(RD);
4129 while (RecordDecls.back()->getNumBases()) {
4130 CXXRecordDecl *D = RecordDecls.back();
4132 "HLSL doesn't support multiple inheritance");
4133 RecordDecls.push_back(
4136 while (!RecordDecls.empty()) {
4137 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4138 for (
auto *FD : RD->
fields())
4139 Inits.push_back(generateInitListsImpl(FD->
getType()));
4142 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4143 Inits, Inits.back()->getEndLoc());
4144 NewInit->setType(Ty);
4149 llvm::SmallVector<QualType, 16> DestTypes;
4150 llvm::SmallVector<Expr *, 16> ArgExprs;
4151 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4152 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4153 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4154 InitTy = Entity.
getType().getNonReferenceType();
4164 DstIt = DestTypes.begin();
4167 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4169 Expr *generateInitLists() {
4170 assert(!ArgExprs.empty() &&
4171 "Call buildInitializerList to generate argument expressions.");
4172 ArgIt = ArgExprs.begin();
4174 return generateInitListsImpl(InitTy);
4175 llvm::SmallVector<Expr *> Inits;
4176 while (ArgIt != ArgExprs.end())
4177 Inits.push_back(generateInitListsImpl(InitTy));
4179 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4180 Inits, Inits.back()->getEndLoc());
4181 llvm::APInt ArySize(64, Inits.size());
4183 ArraySizeModifier::Normal, 0));
4192 if (
Init->getType()->isScalarType())
4195 InitListTransformer ILT(
SemaRef, Entity);
4197 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4205 Init->setInit(I, E);
4207 if (!ILT.buildInitializerList(E))
4210 size_t ExpectedSize = ILT.DestTypes.size();
4211 size_t ActualSize = ILT.ArgExprs.size();
4218 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4225 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4226 if (ExpectedSize != ActualSize) {
4227 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4228 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4229 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4236 Init->resizeInits(Ctx, NewInit->getNumInits());
4237 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4238 Init->updateInit(Ctx, I, NewInit->getInit(I));
4243 const HLSLVkConstantIdAttr *ConstIdAttr =
4244 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4251 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4261 int ConstantID = ConstIdAttr->getId();
4262 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4264 ConstIdAttr->getLocation());
4268 if (
C->getType()->getCanonicalTypeUnqualified() !=
4272 Context.getTrivialTypeSourceInfo(
4273 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 bool initVarDeclWithCtor(Sema &S, VarDecl *VD, MutableArrayRef< Expr * > Args)
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 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
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()
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
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.
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
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.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
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.
Describes an C or C++ initializer list.
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc)
Create a direct initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
bool Failed() const
Determine whether the initialization sequence is invalid.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeTemporary(QualType Type)
Create the initialization entity for a temporary.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
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 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....
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)
void CheckCompleteVariableDeclaration(VarDecl *VD)
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
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_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