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);
604 HLSLVkBindingAttr *VkBinding = Dcl->
getAttr<HLSLVkBindingAttr>();
605 HLSLResourceBindingAttr *RBA = Dcl->
getAttr<HLSLResourceBindingAttr>();
606 if (!VkBinding && (!RBA || !RBA->hasRegisterSlot())) {
610 uint32_t OrderID = getNextImplicitBindingOrderID();
612 RBA->setImplicitBindingOrderID(OrderID);
615 BufDecl->isCBuffer() ? RegisterType::CBuffer
625 int X,
int Y,
int Z) {
626 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
627 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
628 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
629 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
639 int Min,
int Max,
int Preferred,
640 int SpelledArgsCount) {
641 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
642 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
643 WS->getPreferred() != Preferred ||
644 WS->getSpelledArgsCount() != SpelledArgsCount) {
645 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
646 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
652 Result->setSpelledArgsCount(SpelledArgsCount);
656HLSLVkConstantIdAttr *
662 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
670 Diag(VD->getLocation(), diag::err_specialization_const);
674 if (!VD->getType().isConstQualified()) {
675 Diag(VD->getLocation(), diag::err_specialization_const);
679 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
680 if (CI->getId() != Id) {
681 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
682 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
687 HLSLVkConstantIdAttr *
Result =
694 llvm::Triple::EnvironmentType ShaderType) {
695 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
696 if (NT->getType() != ShaderType) {
697 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
698 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
702 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
705HLSLParamModifierAttr *
707 HLSLParamModifierAttr::Spelling Spelling) {
710 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
711 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
712 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
713 D->
dropAttr<HLSLParamModifierAttr>();
715 return HLSLParamModifierAttr::Create(
717 HLSLParamModifierAttr::Keyword_inout);
719 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
720 Diag(PA->getLocation(), diag::note_conflicting_attribute);
746 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
747 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
750 if (Shader->getType() != Env) {
751 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
763 case llvm::Triple::UnknownEnvironment:
764 case llvm::Triple::Library:
766 case llvm::Triple::RootSignature:
767 llvm_unreachable(
"rootsig environment has no functions");
769 llvm_unreachable(
"Unhandled environment in triple");
776 if (AnnotationAttr) {
782 const RecordType *RT = dyn_cast<RecordType>(
T);
795 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
796 assert(ShaderAttr &&
"Entry point has no shader attribute");
797 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
801 case llvm::Triple::Pixel:
802 case llvm::Triple::Vertex:
803 case llvm::Triple::Geometry:
804 case llvm::Triple::Hull:
805 case llvm::Triple::Domain:
806 case llvm::Triple::RayGeneration:
807 case llvm::Triple::Intersection:
808 case llvm::Triple::AnyHit:
809 case llvm::Triple::ClosestHit:
810 case llvm::Triple::Miss:
811 case llvm::Triple::Callable:
812 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
814 {llvm::Triple::Compute,
815 llvm::Triple::Amplification,
816 llvm::Triple::Mesh});
819 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
821 {llvm::Triple::Compute,
822 llvm::Triple::Amplification,
823 llvm::Triple::Mesh});
828 case llvm::Triple::Compute:
829 case llvm::Triple::Amplification:
830 case llvm::Triple::Mesh:
831 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
833 << llvm::Triple::getEnvironmentTypeName(ST);
836 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
837 if (Ver < VersionTuple(6, 6)) {
838 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
841 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
844 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
845 << WS << WS->getSpelledArgsCount() <<
"6.8";
850 case llvm::Triple::RootSignature:
851 llvm_unreachable(
"rootsig environment has no function entry point");
853 llvm_unreachable(
"Unhandled environment in triple");
859 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
869 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
870 assert(ShaderAttr &&
"Entry point has no shader attribute");
871 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
873 switch (AnnotationAttr->
getKind()) {
874 case attr::HLSLSV_DispatchThreadID:
875 case attr::HLSLSV_GroupIndex:
876 case attr::HLSLSV_GroupThreadID:
877 case attr::HLSLSV_GroupID:
878 if (ST == llvm::Triple::Compute)
882 case attr::HLSLSV_Position:
885 if (ST == llvm::Triple::Pixel)
890 llvm_unreachable(
"Unknown HLSLAnnotationAttr");
895 const Attr *A, llvm::Triple::EnvironmentType Stage,
896 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
898 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
899 [](llvm::Triple::EnvironmentType ST) {
901 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
903 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
904 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
905 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
908template <CastKind Kind>
911 Ty = VTy->getElementType();
916template <CastKind Kind>
928 if (LHSFloat && RHSFloat) {
956 if (LHSSigned == RHSSigned) {
957 if (IsCompAssign || IntOrder >= 0)
965 if (IntOrder != (LHSSigned ? 1 : -1)) {
966 if (IsCompAssign || RHSSigned)
974 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
975 if (IsCompAssign || LHSSigned)
991 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
992 QualType NewTy = Ctx.getExtVectorType(
1002 return CK_FloatingCast;
1004 return CK_IntegralCast;
1006 return CK_IntegralToFloating;
1008 return CK_FloatingToIntegral;
1014 bool IsCompAssign) {
1021 if (!LVecTy && IsCompAssign) {
1023 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1025 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1027 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1032 unsigned EndSz = std::numeric_limits<unsigned>::max();
1035 LSz = EndSz = LVecTy->getNumElements();
1038 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1039 "one of the above should have had a value");
1043 if (IsCompAssign && LSz != EndSz) {
1045 diag::err_hlsl_vector_compound_assignment_truncation)
1046 << LHSType << RHSType;
1052 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1057 if (!IsCompAssign && !LVecTy)
1061 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1062 return Ctx.getCommonSugaredType(LHSType, RHSType);
1070 LElTy, RElTy, IsCompAssign);
1073 "HLSL Vectors can only contain integer or floating point types");
1075 LElTy, RElTy, IsCompAssign);
1080 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1081 "Called with non-logical operator");
1083 llvm::raw_svector_ostream OS(Buff);
1085 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1086 OS << NewFnName <<
"(";
1096std::pair<IdentifierInfo *, bool>
1099 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1106 return {DeclIdent,
Found};
1117 for (
auto &RootSigElement : RootElements)
1118 Elements.push_back(RootSigElement.getElement());
1122 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1124 SignatureDecl->setImplicit();
1130 if (RootSigOverrideIdent) {
1133 if (
SemaRef.LookupQualifiedName(R, DC))
1134 return dyn_cast<HLSLRootSignatureDecl>(R.
getFoundDecl());
1142struct PerVisibilityBindingChecker {
1145 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1149 llvm::dxbc::ShaderVisibility Vis;
1154 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1156 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1157 llvm::dxil::ResourceClass RC, uint32_t Space,
1158 uint32_t LowerBound, uint32_t UpperBound,
1159 const hlsl::RootSignatureElement *Elem) {
1161 assert(BuilderIndex < Builders.size() &&
1162 "Not enough builders for visibility type");
1163 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1164 static_cast<const void *
>(Elem));
1166 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1167 "'All' visibility must come first");
1168 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1169 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1170 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1171 static_cast<const void *
>(Elem));
1173 ElemInfoMap.push_back({Elem,
Visibility,
false});
1176 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1177 auto It = llvm::lower_bound(
1179 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1180 assert(It->Elem == Elem &&
"Element not in map");
1184 bool checkOverlap() {
1185 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1186 return LHS.Elem < RHS.Elem;
1189 bool HadOverlap =
false;
1191 using llvm::hlsl::BindingInfoBuilder;
1192 auto ReportOverlap = [
this,
1193 &HadOverlap](
const BindingInfoBuilder &Builder,
1194 const llvm::hlsl::Binding &Reported) {
1198 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1199 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1200 const auto *PrevElem =
1201 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1203 ElemInfo &Info =
getInfo(Elem);
1208 Info.Diagnosed =
true;
1210 ElemInfo &PrevInfo =
getInfo(PrevElem);
1211 llvm::dxbc::ShaderVisibility CommonVis =
1212 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1215 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1216 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1217 << Reported.isUnbounded() << Reported.UpperBound
1222 this->S->
Diag(PrevElem->getLocation(),
1223 diag::note_hlsl_resource_range_here);
1226 for (BindingInfoBuilder &Builder : Builders)
1227 Builder.calculateBindingInfo(ReportOverlap);
1247 bool HadError =
false;
1248 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1249 uint32_t UpperBound) {
1251 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1252 << LowerBound << UpperBound;
1259 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1260 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1261 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1264 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1265 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1266 ReportError(Loc, 0, 0xfffffffe);
1269 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1270 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1271 ReportError(Loc, 0, 0xffffffef);
1274 const uint32_t Version =
1275 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1276 const uint32_t VersionEnum = Version - 1;
1277 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1279 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1286 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1287 if (
const auto *Descriptor =
1288 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1289 VerifyRegister(Loc, Descriptor->Reg.Number);
1290 VerifySpace(Loc, Descriptor->Space);
1292 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(
1293 Version, llvm::to_underlying(Descriptor->Flags)))
1294 ReportFlagError(Loc);
1295 }
else if (
const auto *Constants =
1296 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1297 VerifyRegister(Loc, Constants->Reg.Number);
1298 VerifySpace(Loc, Constants->Space);
1299 }
else if (
const auto *Sampler =
1300 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1301 VerifyRegister(Loc, Sampler->Reg.Number);
1302 VerifySpace(Loc, Sampler->Space);
1305 "By construction, parseFloatParam can't produce a NaN from a "
1306 "float_literal token");
1308 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1309 ReportError(Loc, 0, 16);
1310 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1311 ReportFloatError(Loc, -16.f, 15.99f);
1312 }
else if (
const auto *Clause =
1313 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1315 VerifyRegister(Loc, Clause->Reg.Number);
1316 VerifySpace(Loc, Clause->Space);
1318 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1322 ReportError(Loc, 1, 0xfffffffe);
1325 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1327 ReportFlagError(Loc);
1331 PerVisibilityBindingChecker BindingChecker(
this);
1332 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1337 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1338 if (
const auto *Descriptor =
1339 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1340 uint32_t LowerBound(Descriptor->Reg.Number);
1341 uint32_t UpperBound(LowerBound);
1343 BindingChecker.trackBinding(
1344 Descriptor->Visibility,
1345 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1346 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1347 }
else if (
const auto *Constants =
1348 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1349 uint32_t LowerBound(Constants->Reg.Number);
1350 uint32_t UpperBound(LowerBound);
1352 BindingChecker.trackBinding(
1353 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1354 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1355 }
else if (
const auto *Sampler =
1356 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1357 uint32_t LowerBound(Sampler->Reg.Number);
1358 uint32_t UpperBound(LowerBound);
1360 BindingChecker.trackBinding(
1361 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1362 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1363 }
else if (
const auto *Clause =
1364 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1367 UnboundClauses.emplace_back(Clause, &RootSigElem);
1368 }
else if (
const auto *Table =
1369 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1370 assert(UnboundClauses.size() == Table->NumClauses &&
1371 "Number of unbound elements must match the number of clauses");
1372 bool HasAnySampler =
false;
1373 bool HasAnyNonSampler =
false;
1374 uint64_t Offset = 0;
1375 bool IsPrevUnbound =
false;
1376 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1378 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1379 HasAnySampler =
true;
1381 HasAnyNonSampler =
true;
1383 if (HasAnySampler && HasAnyNonSampler)
1384 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1389 if (Clause->NumDescriptors == 0)
1393 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1395 Offset = Clause->Offset;
1397 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1398 Offset, Clause->NumDescriptors);
1400 if (IsPrevUnbound && IsAppending)
1401 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1402 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1403 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1406 Offset = RangeBound + 1;
1407 IsPrevUnbound = Clause->NumDescriptors ==
1408 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1411 uint32_t LowerBound(Clause->Reg.Number);
1412 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1413 LowerBound, Clause->NumDescriptors);
1415 BindingChecker.trackBinding(
1417 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1418 LowerBound, UpperBound, ClauseElem);
1420 UnboundClauses.clear();
1424 return BindingChecker.checkOverlap();
1429 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1434 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1435 if (RS->getSignatureIdent() != Ident) {
1436 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1440 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1446 if (
auto *SignatureDecl =
1454 llvm::VersionTuple SMVersion =
1459 uint32_t ZMax = 1024;
1460 uint32_t ThreadMax = 1024;
1461 if (IsDXIL && SMVersion.getMajor() <= 4) {
1464 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1474 diag::err_hlsl_numthreads_argument_oor)
1483 diag::err_hlsl_numthreads_argument_oor)
1492 diag::err_hlsl_numthreads_argument_oor)
1497 if (
X * Y * Z > ThreadMax) {
1498 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1515 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1523 if (SpelledArgsCount > 1 &&
1527 uint32_t Preferred = 0;
1528 if (SpelledArgsCount > 2 &&
1532 if (SpelledArgsCount > 2) {
1535 diag::err_attribute_power_of_two_in_range)
1536 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1541 if (Preferred < Min || Preferred >
Max) {
1543 diag::err_attribute_power_of_two_in_range)
1544 << AL <<
Min <<
Max << Preferred;
1547 }
else if (SpelledArgsCount > 1) {
1550 diag::err_attribute_power_of_two_in_range)
1551 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1555 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1558 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1563 diag::err_attribute_power_of_two_in_range)
1564 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1569 HLSLWaveSizeAttr *NewAttr =
1597 uint32_t Binding = 0;
1612 if (!
T->hasUnsignedIntegerRepresentation() ||
1613 (VT && VT->getNumElements() > 3)) {
1614 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1615 << AL <<
"uint/uint2/uint3";
1624 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1625 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1626 << AL <<
"float/float1/float2/float3/float4";
1634 std::optional<unsigned> Index) {
1638 QualType ValueType = VD->getType();
1639 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1640 ValueType = FD->getReturnType();
1642 bool IsOutput =
false;
1643 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1650 Attr *Attribute =
nullptr;
1651 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1654 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1656 }
else if (SemanticName ==
"SV_GROUPINDEX") {
1658 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1660 }
else if (SemanticName ==
"SV_GROUPTHREADID") {
1663 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1665 }
else if (SemanticName ==
"SV_GROUPID") {
1668 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1670 }
else if (SemanticName ==
"SV_POSITION") {
1671 const auto *VT = ValueType->getAs<
VectorType>();
1672 if (!ValueType->hasFloatingRepresentation() ||
1673 (VT && VT->getNumElements() > 4))
1674 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1675 << AL <<
"float/float1/float2/float3/float4";
1678 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1686 uint32_t IndexValue, ExplicitIndex;
1689 assert(IndexValue > 0 ? ExplicitIndex :
true);
1690 std::optional<unsigned> Index =
1691 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1696 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1701 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1702 << AL <<
"shader constant in a constant buffer";
1706 uint32_t SubComponent;
1716 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1721 if (IsAggregateTy || Size > 128) {
1722 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1726 if ((Component * 32 + Size) > 128) {
1727 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1732 EltTy = VT->getElementType();
1734 if (Align > 32 && Component == 1) {
1737 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1751 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1754 llvm::Triple::EnvironmentType ShaderType;
1755 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1756 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1757 << AL << Str << ArgLoc;
1771 assert(AttrList.size() &&
"expected list of resource attributes");
1778 HLSLAttributedResourceType::Attributes ResAttrs;
1780 bool HasResourceClass =
false;
1781 for (
const Attr *A : AttrList) {
1784 LocEnd = A->getRange().getEnd();
1785 switch (A->getKind()) {
1786 case attr::HLSLResourceClass: {
1788 if (HasResourceClass) {
1789 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1790 ? diag::warn_duplicate_attribute_exact
1791 : diag::warn_duplicate_attribute)
1795 ResAttrs.ResourceClass = RC;
1796 HasResourceClass =
true;
1800 if (ResAttrs.IsROV) {
1801 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1804 ResAttrs.IsROV =
true;
1806 case attr::HLSLRawBuffer:
1807 if (ResAttrs.RawBuffer) {
1808 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1811 ResAttrs.RawBuffer =
true;
1813 case attr::HLSLContainedType: {
1816 if (!ContainedTy.
isNull()) {
1817 S.
Diag(A->getLocation(), ContainedTy == Ty
1818 ? diag::warn_duplicate_attribute_exact
1819 : diag::warn_duplicate_attribute)
1828 llvm_unreachable(
"unhandled resource attribute type");
1832 if (!HasResourceClass) {
1833 S.
Diag(AttrList.back()->getRange().getEnd(),
1834 diag::err_hlsl_missing_resource_class);
1839 Wrapped, ContainedTy, ResAttrs);
1841 if (LocInfo && ContainedTyInfo) {
1854 if (!
T->isHLSLResourceType()) {
1855 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1870 AttributeCommonInfo::AS_CXX11, 0, false ,
1875 case ParsedAttr::AT_HLSLResourceClass: {
1877 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1888 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1889 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1890 <<
"ResourceClass" << Identifier;
1893 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
1897 case ParsedAttr::AT_HLSLROV:
1901 case ParsedAttr::AT_HLSLRawBuffer:
1905 case ParsedAttr::AT_HLSLContainedType: {
1907 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1913 assert(TSI &&
"no type source info for attribute argument");
1915 diag::err_incomplete_type))
1917 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
1922 llvm_unreachable(
"unhandled HLSL attribute");
1925 HLSLResourcesTypeAttrs.emplace_back(A);
1931 if (!HLSLResourcesTypeAttrs.size())
1937 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1938 const HLSLAttributedResourceType *RT =
1945 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1947 HLSLResourcesTypeAttrs.clear();
1955 auto I = LocsForHLSLAttributedResources.find(RT);
1956 if (I != LocsForHLSLAttributedResources.end()) {
1957 LocInfo = I->second;
1958 LocsForHLSLAttributedResources.erase(I);
1967void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
1968 const RecordType *RT) {
1969 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
1976 "incomplete arrays inside user defined types are not supported");
1985 if (
const HLSLAttributedResourceType *AttrResType =
1986 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
1991 Bindings.addDeclBindingInfo(VD, RC);
1992 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1998 collectResourceBindingsOnUserRecordDecl(VD, RT);
2010 bool SpecifiedSpace) {
2011 int RegTypeNum =
static_cast<int>(RegType);
2014 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2015 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2020 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2021 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2022 : ResourceClass::SRV;
2032 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2036 if (
const HLSLAttributedResourceType *AttrResType =
2037 HLSLAttributedResourceType::findHandleTypeOnResource(
2054 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2055 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2060 if (RegType == RegisterType::CBuffer)
2061 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2062 else if (RegType != RegisterType::C)
2063 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2067 if (RegType == RegisterType::C)
2068 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2070 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2080 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2088 bool RegisterTypesDetected[5] = {
false};
2089 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2092 if (HLSLResourceBindingAttr *
attr =
2093 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2096 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2097 int otherRegTypeNum =
static_cast<int>(otherRegType);
2099 diag::err_hlsl_duplicate_register_annotation)
2103 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2111 bool SpecifiedSpace) {
2116 "expecting VarDecl or HLSLBufferDecl");
2127 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2129 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2130 Ty = IAT->getElementType();
2132 diag::err_incomplete_type))
2136 StringRef Slot =
"";
2137 StringRef Space =
"";
2141 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2151 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2157 SpaceLoc = Loc->
getLoc();
2160 if (Str.starts_with(
"space")) {
2162 SpaceLoc = Loc->
getLoc();
2171 std::optional<unsigned> SlotNum;
2172 unsigned SpaceNum = 0;
2175 if (!Slot.empty()) {
2177 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2180 if (RegType == RegisterType::I) {
2181 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2184 StringRef SlotNumStr = Slot.substr(1);
2186 if (SlotNumStr.getAsInteger(10, N)) {
2187 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2194 if (!Space.starts_with(
"space")) {
2195 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2198 StringRef SpaceNumStr = Space.substr(5);
2199 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2200 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2205 if (SlotNum.has_value())
2210 HLSLResourceBindingAttr *NewAttr =
2211 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2213 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2268 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2272 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2273 unsigned CurrentShaderStageBit;
2278 bool ReportOnlyShaderStageIssues;
2281 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2282 static_assert(
sizeof(
unsigned) >= 4);
2283 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2284 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2285 "ShaderType is too big for this bitmap");
2288 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2289 CurrentShaderEnvironment = ShaderType;
2290 CurrentShaderStageBit = (1 << bitmapIndex);
2293 void SetUnknownShaderStageContext() {
2294 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2295 CurrentShaderStageBit = (1 << 31);
2298 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2299 return CurrentShaderEnvironment;
2302 bool InUnknownShaderStageContext()
const {
2303 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2307 void AddToScannedFunctions(
const FunctionDecl *FD) {
2308 unsigned &ScannedStages = ScannedDecls[FD];
2309 ScannedStages |= CurrentShaderStageBit;
2312 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2314 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2315 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2318 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2319 return ScannerStages & CurrentShaderStageBit;
2322 static bool NeverBeenScanned(
unsigned ScannedStages) {
2323 return ScannedStages == 0;
2327 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2328 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2330 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2331 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2334 DiagnoseHLSLAvailability(Sema &SemaRef)
2336 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2337 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2340 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2341 void RunOnFunction(
const FunctionDecl *FD);
2343 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2344 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2346 HandleFunctionOrMethodRef(FD, DRE);
2350 bool VisitMemberExpr(MemberExpr *ME)
override {
2351 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2353 HandleFunctionOrMethodRef(FD, ME);
2358void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2361 "expected DeclRefExpr or MemberExpr");
2365 if (FD->
hasBody(FDWithBody)) {
2366 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2367 DeclsToScan.push_back(FDWithBody);
2372 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2374 CheckDeclAvailability(
2378void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2387 DeclContextsToScan.push_back(TU);
2389 while (!DeclContextsToScan.empty()) {
2390 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2391 for (
auto &D : DC->
decls()) {
2393 if (D->isImplicit())
2398 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2399 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2404 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2409 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2410 SetShaderStageContext(ShaderAttr->getType());
2419 for (
const auto *Redecl : FD->
redecls()) {
2420 if (Redecl->isInExportDeclContext()) {
2427 SetUnknownShaderStageContext();
2435void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2436 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2437 DeclsToScan.push_back(FD);
2439 while (!DeclsToScan.empty()) {
2447 const unsigned ScannedStages = GetScannedStages(FD);
2448 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2451 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2453 AddToScannedFunctions(FD);
2458bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2459 const AvailabilityAttr *AA) {
2464 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2465 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2468 llvm::Triple::EnvironmentType AttrEnv =
2469 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2471 return CurrentEnv == AttrEnv;
2474const AvailabilityAttr *
2475DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2476 AvailabilityAttr
const *PartialMatch =
nullptr;
2480 for (
const auto *A : D->
attrs()) {
2481 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2482 StringRef AttrPlatform = Avail->getPlatform()->getName();
2483 StringRef TargetPlatform =
2487 if (AttrPlatform == TargetPlatform) {
2489 if (HasMatchingEnvironmentOrNone(Avail))
2491 PartialMatch = Avail;
2495 return PartialMatch;
2500void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2501 const AvailabilityAttr *AA,
2520 if (ReportOnlyShaderStageIssues)
2526 if (InUnknownShaderStageContext())
2531 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2532 VersionTuple Introduced = AA->getIntroduced();
2541 llvm::StringRef PlatformName(
2544 llvm::StringRef CurrentEnvStr =
2545 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2547 llvm::StringRef AttrEnvStr =
2548 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2549 bool UseEnvironment = !AttrEnvStr.empty();
2551 if (EnvironmentMatches) {
2552 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2553 <<
Range << D << PlatformName << Introduced.getAsString()
2554 << UseEnvironment << CurrentEnvStr;
2556 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2560 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2561 << D << PlatformName << Introduced.getAsString()
2563 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2570 if (!DefaultCBufferDecls.empty()) {
2573 DefaultCBufferDecls);
2575 getNextImplicitBindingOrderID());
2576 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2580 for (
const Decl *VD : DefaultCBufferDecls) {
2581 const HLSLResourceBindingAttr *RBA =
2582 VD->
getAttr<HLSLResourceBindingAttr>();
2583 if (RBA && RBA->hasRegisterSlot() &&
2584 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2591 SemaRef.Consumer.HandleTopLevelDecl(DG);
2593 diagnoseAvailabilityViolations(TU);
2603 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2606 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2613 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2616 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2641 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2656 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2657 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2658 << ArgOrdinal << 5 << 0
2664 unsigned ArgIndex) {
2665 auto *Arg = TheCall->
getArg(ArgIndex);
2667 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2670 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2680 if (VecTy->getElementType()->isDoubleType())
2681 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2682 << ArgOrdinal << 1 << 0 << 1
2692 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2693 << ArgOrdinal << 5 << 1
2702 if (VecTy->getElementType()->isUnsignedIntegerType())
2705 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2706 << ArgOrdinal << 4 << 3 << 0
2715 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2716 << ArgOrdinal << 5 << 3
2732 unsigned ArgIndex) {
2741 diag::err_typecheck_expect_scalar_or_vector)
2742 << ArgType << Scalar;
2749 unsigned ArgIndex) {
2754 if (!(ArgType->isScalarType() ||
2755 (VTy && VTy->getElementType()->isScalarType()))) {
2757 diag::err_typecheck_expect_any_scalar_or_vector)
2774 diag::err_typecheck_expect_any_scalar_or_vector)
2787 diag::err_typecheck_call_different_arg_types)
2806 Arg1ScalarTy = VTy->getElementType();
2810 Arg2ScalarTy = VTy->getElementType();
2813 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2814 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2824 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2826 diag::err_typecheck_vector_lengths_not_equal)
2832 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2834 diag::err_typecheck_vector_lengths_not_equal)
2847 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2851 const HLSLAttributedResourceType *ResTy =
2855 diag::err_typecheck_expect_hlsl_resource)
2859 if (Check && Check(ResTy)) {
2861 diag::err_invalid_hlsl_resource_type)
2871 switch (BuiltinID) {
2872 case Builtin::BI__builtin_hlsl_adduint64: {
2873 if (
SemaRef.checkArgCount(TheCall, 2))
2886 if (ElementBitCount != 32) {
2888 diag::err_integer_incorrect_bit_count)
2889 << 32 << ElementBitCount;
2894 int NumElementsArg = VTy->getNumElements();
2895 if (NumElementsArg != 2 && NumElementsArg != 4) {
2897 << 1 << 64 << NumElementsArg * ElementBitCount;
2911 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2912 if (
SemaRef.checkArgCount(TheCall, 2) ||
2915 SemaRef.getASTContext().UnsignedIntTy))
2920 QualType ContainedTy = ResourceTy->getContainedType();
2923 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
2929 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
2930 if (
SemaRef.checkArgCount(TheCall, 1) ||
2938 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
2940 if (
SemaRef.checkArgCount(TheCall, 6) ||
2954 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
2956 if (
SemaRef.checkArgCount(TheCall, 6) ||
2970 case Builtin::BI__builtin_hlsl_and:
2971 case Builtin::BI__builtin_hlsl_or: {
2972 if (
SemaRef.checkArgCount(TheCall, 2))
2985 case Builtin::BI__builtin_hlsl_all:
2986 case Builtin::BI__builtin_hlsl_any: {
2987 if (
SemaRef.checkArgCount(TheCall, 1))
2993 case Builtin::BI__builtin_hlsl_asdouble: {
2994 if (
SemaRef.checkArgCount(TheCall, 2))
2998 SemaRef.Context.UnsignedIntTy,
3003 SemaRef.Context.UnsignedIntTy,
3012 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3013 if (
SemaRef.BuiltinElementwiseTernaryMath(
3019 case Builtin::BI__builtin_hlsl_dot: {
3021 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3027 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3028 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3029 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3039 EltTy = VecTy->getElementType();
3040 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3053 case Builtin::BI__builtin_hlsl_select: {
3054 if (
SemaRef.checkArgCount(TheCall, 3))
3062 if (VTy && VTy->getElementType()->isBooleanType() &&
3067 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3068 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3069 if (
SemaRef.checkArgCount(TheCall, 1))
3075 diag::err_builtin_invalid_arg_type)
3078 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3082 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3083 case Builtin::BI__builtin_hlsl_elementwise_radians:
3084 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3085 case Builtin::BI__builtin_hlsl_elementwise_frac: {
3086 if (
SemaRef.checkArgCount(TheCall, 1))
3091 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3095 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3096 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3097 if (
SemaRef.checkArgCount(TheCall, 1))
3102 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3107 case Builtin::BI__builtin_hlsl_lerp: {
3108 if (
SemaRef.checkArgCount(TheCall, 3))
3115 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3119 case Builtin::BI__builtin_hlsl_mad: {
3120 if (
SemaRef.BuiltinElementwiseTernaryMath(
3126 case Builtin::BI__builtin_hlsl_normalize: {
3127 if (
SemaRef.checkArgCount(TheCall, 1))
3138 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3139 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3147 case Builtin::BI__builtin_hlsl_step: {
3148 if (
SemaRef.checkArgCount(TheCall, 2))
3160 case Builtin::BI__builtin_hlsl_wave_active_max:
3161 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3162 if (
SemaRef.checkArgCount(TheCall, 1))
3177 case Builtin::BI__builtin_elementwise_bitreverse: {
3185 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3186 if (
SemaRef.checkArgCount(TheCall, 2))
3194 diag::err_typecheck_convert_incompatible)
3195 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3208 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3209 if (
SemaRef.checkArgCount(TheCall, 0))
3213 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3214 if (
SemaRef.checkArgCount(TheCall, 3))
3229 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3230 if (
SemaRef.checkArgCount(TheCall, 1))
3237 case Builtin::BI__builtin_elementwise_acos:
3238 case Builtin::BI__builtin_elementwise_asin:
3239 case Builtin::BI__builtin_elementwise_atan:
3240 case Builtin::BI__builtin_elementwise_atan2:
3241 case Builtin::BI__builtin_elementwise_ceil:
3242 case Builtin::BI__builtin_elementwise_cos:
3243 case Builtin::BI__builtin_elementwise_cosh:
3244 case Builtin::BI__builtin_elementwise_exp:
3245 case Builtin::BI__builtin_elementwise_exp2:
3246 case Builtin::BI__builtin_elementwise_exp10:
3247 case Builtin::BI__builtin_elementwise_floor:
3248 case Builtin::BI__builtin_elementwise_fmod:
3249 case Builtin::BI__builtin_elementwise_log:
3250 case Builtin::BI__builtin_elementwise_log2:
3251 case Builtin::BI__builtin_elementwise_log10:
3252 case Builtin::BI__builtin_elementwise_pow:
3253 case Builtin::BI__builtin_elementwise_roundeven:
3254 case Builtin::BI__builtin_elementwise_sin:
3255 case Builtin::BI__builtin_elementwise_sinh:
3256 case Builtin::BI__builtin_elementwise_sqrt:
3257 case Builtin::BI__builtin_elementwise_tan:
3258 case Builtin::BI__builtin_elementwise_tanh:
3259 case Builtin::BI__builtin_elementwise_trunc: {
3265 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3266 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3267 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3268 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3270 if (
SemaRef.checkArgCount(TheCall, 2) ||
3273 SemaRef.getASTContext().IntTy))
3276 std::optional<llvm::APSInt> Offset =
3278 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3280 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3293 WorkList.push_back(BaseTy);
3294 while (!WorkList.empty()) {
3296 T =
T.getCanonicalType().getUnqualifiedType();
3297 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3305 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3306 llvm::append_range(List, ElementFields);
3311 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3312 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3315 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3316 if (RD->isStandardLayout())
3317 RD = RD->getStandardLayoutBaseWithFields();
3321 if (RD->
isUnion() || !RD->isAggregate()) {
3327 for (
const auto *FD : RD->
fields())
3328 if (!FD->isUnnamedBitField())
3329 FieldTypes.push_back(FD->
getType());
3331 std::reverse(FieldTypes.begin(), FieldTypes.end());
3332 llvm::append_range(WorkList, FieldTypes);
3336 if (!RD->isStandardLayout()) {
3338 for (
const auto &
Base : RD->bases())
3339 FieldTypes.push_back(
Base.getType());
3340 std::reverse(FieldTypes.begin(), FieldTypes.end());
3341 llvm::append_range(WorkList, FieldTypes);
3363 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3369 int ArraySize = VT->getNumElements();
3374 QualType ElTy = VT->getElementType();
3378 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3394 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3403 return llvm::equal(T1Types, T2Types,
3405 return SemaRef.IsLayoutCompatible(LHS, RHS);
3414 bool HadError =
false;
3416 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3424 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3425 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3426 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3427 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3429 if (NSpellingIdx != OSpellingIdx) {
3431 diag::err_hlsl_param_qualifier_mismatch)
3432 << NDAttr << NewParam;
3448 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3463 llvm_unreachable(
"HLSL doesn't support pointers.");
3466 llvm_unreachable(
"HLSL doesn't support complex types.");
3468 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3470 llvm_unreachable(
"Should have returned before this");
3480 llvm_unreachable(
"HLSL doesn't support complex types.");
3482 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3487 llvm_unreachable(
"HLSL doesn't support pointers.");
3489 llvm_unreachable(
"Should have returned before this");
3495 llvm_unreachable(
"HLSL doesn't support pointers.");
3498 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3502 llvm_unreachable(
"HLSL doesn't support complex types.");
3505 llvm_unreachable(
"Unhandled scalar cast");
3512 WorkList.push_back(BaseTy);
3513 while (!WorkList.empty()) {
3515 T =
T.getCanonicalType().getUnqualifiedType();
3517 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3518 WorkList.push_back(AT->getElementType());
3521 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
3522 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
3531 for (
const auto *FD : RD->
fields()) {
3532 if (FD->isBitField())
3534 WorkList.push_back(FD->
getType());
3569 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3570 if (DestTypes[I]->isUnionType())
3602 if (SrcTypes.size() < DestTypes.size())
3605 unsigned SrcSize = SrcTypes.size();
3606 unsigned DstSize = DestTypes.size();
3608 for (I = 0; I < DstSize && I < SrcSize; I++) {
3609 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3617 for (; I < SrcSize; I++) {
3618 if (SrcTypes[I]->isUnionType())
3625 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3626 "We should not get here without a parameter modifier expression");
3627 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3634 << Arg << (IsInOut ? 1 : 0);
3640 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3647 << Arg << (IsInOut ? 1 : 0);
3659 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3665 auto *OpV =
new (Ctx)
3670 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3671 tok::equal, ArgOpV, OpV);
3687 "Pointer and reference types cannot be inout or out parameters");
3688 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3698 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3704 if (
Decl->getType().hasAddressSpace())
3707 if (
Decl->getType()->isDependentType())
3739 if (
SemaRef.RequireCompleteType(
3742 diag::err_typecheck_decl_incomplete_type)) {
3756 DefaultCBufferDecls.push_back(VD);
3761 collectResourceBindingsOnVarDecl(VD);
3764 VD->
hasAttr<HLSLVkConstantIdAttr>()) {
3772 processExplicitBindingsOnDecl(VD);
3778 if (!VD->
hasAttr<HLSLVkBindingAttr>()) {
3779 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3780 if (!RBA || !RBA->hasRegisterSlot()) {
3781 uint32_t OrderID = getNextImplicitBindingOrderID();
3783 RBA->setImplicitBindingOrderID(OrderID);
3796bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3798 "expected resource record type");
3813 if (Binding.isExplicit()) {
3815 CreateMethod = lookupMethod(
SemaRef, ResourceDecl,
"__createFromBinding",
3820 Args.push_back(RegSlot);
3824 lookupMethod(
SemaRef, ResourceDecl,
"__createFromImplicitBinding",
3826 uint32_t OrderID = (Binding.hasImplicitOrderID())
3827 ? Binding.getImplicitOrderID()
3828 : getNextImplicitBindingOrderID();
3832 Args.push_back(OrderId);
3841 IntegerLiteral *Space =
3844 Args.push_back(Space);
3847 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
3848 Args.push_back(RangeSize);
3851 AST, llvm::APInt(UIntTySize, 0), AST.
UnsignedIntTy, SourceLocation());
3852 Args.push_back(Index);
3854 StringRef VarName = VD->
getName();
3861 Name,
nullptr,
VK_PRValue, FPOptionsOverride());
3862 Args.push_back(NameCast);
3872 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod,
false,
3877 CK_FunctionToPointerDecay, DRE,
nullptr,
VK_PRValue, FPOptionsOverride());
3879 CallExpr *InitExpr =
3881 SourceLocation(), FPOptionsOverride());
3884 SemaRef.CheckCompleteVariableDeclaration(VD);
3888bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
3890 "expected array of resource records");
3901 ASTContext &AST =
SemaRef.getASTContext();
3905 HLSLResourceBindingAttr *RBA = VD->
getAttr<HLSLResourceBindingAttr>();
3906 HLSLVkBindingAttr *VkBinding = VD->
getAttr<HLSLVkBindingAttr>();
3907 CXXMethodDecl *CreateMethod =
nullptr;
3909 if (VkBinding || (RBA && RBA->hasRegisterSlot()))
3911 CreateMethod = lookupMethod(
SemaRef, ResourceDecl,
"__createFromBinding",
3916 lookupMethod(
SemaRef, ResourceDecl,
"__createFromImplicitBinding",
3923 if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3941 return initGlobalResourceDecl(VD);
3943 return initGlobalResourceArrayDecl(VD);
3953 "expected LHS to be a resource record or array of resource records");
3954 if (Opc != BO_Assign)
3959 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
3967 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
3978void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
3980 "expected global variable that contains HLSL resource");
3983 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
3984 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
3985 ? ResourceClass::CBuffer
3986 : ResourceClass::SRV);
3999 if (
const HLSLAttributedResourceType *AttrResType =
4000 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4001 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4006 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
4007 collectResourceBindingsOnUserRecordDecl(VD, RT);
4013void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
4016 bool HasBinding =
false;
4017 for (Attr *A : VD->
attrs()) {
4021 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4022 if (!RBA || !RBA->hasRegisterSlot())
4027 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
4028 "never have an attribute created");
4030 if (RT == RegisterType::C) {
4031 if (Bindings.hasBindingInfoForDecl(VD))
4033 diag::warn_hlsl_user_defined_type_missing_member)
4034 <<
static_cast<int>(RT);
4042 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4047 diag::warn_hlsl_user_defined_type_missing_member)
4048 <<
static_cast<int>(RT);
4056class InitListTransformer {
4060 QualType *DstIt =
nullptr;
4061 Expr **ArgIt =
nullptr;
4067 bool castInitializer(Expr *E) {
4068 assert(DstIt &&
"This should always be something!");
4069 if (DstIt == DestTypes.end()) {
4071 ArgExprs.push_back(E);
4076 DstIt = DestTypes.begin();
4079 Ctx, *DstIt,
false);
4084 ArgExprs.push_back(
Init);
4089 bool buildInitializerListImpl(Expr *E) {
4091 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4092 for (
auto *SubInit :
Init->inits())
4093 if (!buildInitializerListImpl(SubInit))
4102 return castInitializer(E);
4104 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4109 for (uint64_t I = 0; I <
Size; ++I) {
4111 SizeTy, SourceLocation());
4117 if (!castInitializer(ElExpr.
get()))
4123 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4127 for (uint64_t I = 0; I <
Size; ++I) {
4129 SizeTy, SourceLocation());
4134 if (!buildInitializerListImpl(ElExpr.
get()))
4141 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4142 RecordDecls.push_back(RD);
4143 while (RecordDecls.back()->getNumBases()) {
4144 CXXRecordDecl *D = RecordDecls.back();
4146 "HLSL doesn't support multiple inheritance");
4147 RecordDecls.push_back(
4150 while (!RecordDecls.empty()) {
4151 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4152 for (
auto *FD : RD->
fields()) {
4153 if (FD->isUnnamedBitField())
4161 if (!buildInitializerListImpl(Res.
get()))
4169 Expr *generateInitListsImpl(QualType Ty) {
4170 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
4174 llvm::SmallVector<Expr *> Inits;
4175 assert(!
isa<MatrixType>(Ty) &&
"Matrix types not yet supported in HLSL");
4180 if (
auto *ATy = Ty->
getAs<VectorType>()) {
4181 ElTy = ATy->getElementType();
4182 Size = ATy->getNumElements();
4185 ElTy = VTy->getElementType();
4186 Size = VTy->getZExtSize();
4188 for (uint64_t I = 0; I <
Size; ++I)
4189 Inits.push_back(generateInitListsImpl(ElTy));
4192 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4193 RecordDecls.push_back(RD);
4194 while (RecordDecls.back()->getNumBases()) {
4195 CXXRecordDecl *D = RecordDecls.back();
4197 "HLSL doesn't support multiple inheritance");
4198 RecordDecls.push_back(
4201 while (!RecordDecls.empty()) {
4202 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4203 for (
auto *FD : RD->
fields())
4204 if (!FD->isUnnamedBitField())
4205 Inits.push_back(generateInitListsImpl(FD->
getType()));
4208 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4209 Inits, Inits.back()->getEndLoc());
4210 NewInit->setType(Ty);
4215 llvm::SmallVector<QualType, 16> DestTypes;
4216 llvm::SmallVector<Expr *, 16> ArgExprs;
4217 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4218 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4219 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4220 InitTy = Entity.
getType().getNonReferenceType();
4230 DstIt = DestTypes.begin();
4233 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4235 Expr *generateInitLists() {
4236 assert(!ArgExprs.empty() &&
4237 "Call buildInitializerList to generate argument expressions.");
4238 ArgIt = ArgExprs.begin();
4240 return generateInitListsImpl(InitTy);
4241 llvm::SmallVector<Expr *> Inits;
4242 while (ArgIt != ArgExprs.end())
4243 Inits.push_back(generateInitListsImpl(InitTy));
4245 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4246 Inits, Inits.back()->getEndLoc());
4247 llvm::APInt ArySize(64, Inits.size());
4249 ArraySizeModifier::Normal, 0));
4258 if (
Init->getType()->isScalarType())
4261 InitListTransformer ILT(
SemaRef, Entity);
4263 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4271 Init->setInit(I, E);
4273 if (!ILT.buildInitializerList(E))
4276 size_t ExpectedSize = ILT.DestTypes.size();
4277 size_t ActualSize = ILT.ArgExprs.size();
4278 if (ExpectedSize == 0 && ActualSize == 0)
4287 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4294 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4295 if (ExpectedSize != ActualSize) {
4296 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4297 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4298 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4305 Init->resizeInits(Ctx, NewInit->getNumInits());
4306 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4307 Init->updateInit(Ctx, I, NewInit->getInit(I));
4312 const HLSLVkConstantIdAttr *ConstIdAttr =
4313 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4320 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4330 int ConstantID = ConstIdAttr->getId();
4331 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4333 ConstIdAttr->getLocation());
4337 if (
C->getType()->getCanonicalTypeUnqualified() !=
4341 Context.getTrivialTypeSourceInfo(
4342 Init->getType(),
Init->getExprLoc()),
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static bool isResourceRecordTypeOrArrayOf(VarDecl *VD)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static const HLSLAttributedResourceType * getResourceArrayHandleType(VarDecl *VD)
static RegisterType getRegisterType(ResourceClass RC)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool isValidWaveSizeValue(unsigned Value)
static bool IsDefaultBufferConstantDecl(VarDecl *VD)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
void completeDefinition() override
Indicates that the definition of this class is now complete.
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
const CXXRecordDecl * getStandardLayoutBaseWithFields() const
If this is a standard-layout class or union, any and all data members will be declared in the same ty...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Decl - This represents one declaration (or definition), e.g.
attr_iterator attr_end() const
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
attr_iterator attr_begin() const
SourceLocation getLocation() const
void setImplicit(bool I=true)
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
Represents a ValueDecl that came out of a declarator.
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
ArrayRef< ParmVarDecl * > parameters() const
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
DeclarationNameInfo getNameInfo() const
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
void addLayoutStruct(CXXRecordDecl *LS)
void setHasValidPackoffset(bool PO)
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
buffer_decl_range buffer_decls() const
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Represents the results of name lookup.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
bool hasParsedType() const
const ParsedType & getTypeArg() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
AttributeCommonInfo::Kind getKind() const
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_range fields() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
void handleSemanticAttr(Decl *D, const ParsedAttr &AL)
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
bool isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
void CheckEntryPoint(FunctionDecl *FD)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
bool ContainsBitField(QualType BaseTy)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
T * createSemanticAttr(const ParsedAttr &AL, std::optional< unsigned > Location)
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, std::optional< unsigned > Index)
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
bool ActOnUninitializedVarDecl(VarDecl *D)
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
QualType getInoutParameterType(QualType Ty)
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isHLSLBuiltinIntangibleType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const