14#include "clang/AST/Attrs.inc"
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/ADT/SmallVector.h"
36#include "llvm/ADT/StringExtras.h"
37#include "llvm/ADT/StringRef.h"
38#include "llvm/ADT/Twine.h"
39#include "llvm/Support/Casting.h"
40#include "llvm/Support/DXILABI.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/TargetParser/Triple.h"
55 case ResourceClass::SRV:
56 return RegisterType::SRV;
57 case ResourceClass::UAV:
58 return RegisterType::UAV;
59 case ResourceClass::CBuffer:
60 return RegisterType::CBuffer;
61 case ResourceClass::Sampler:
62 return RegisterType::Sampler;
64 llvm_unreachable(
"unexpected ResourceClass value");
70 assert(RT !=
nullptr);
74 *RT = RegisterType::SRV;
78 *RT = RegisterType::UAV;
82 *RT = RegisterType::CBuffer;
86 *RT = RegisterType::Sampler;
90 *RT = RegisterType::C;
94 *RT = RegisterType::I;
103 case RegisterType::SRV:
104 return ResourceClass::SRV;
105 case RegisterType::UAV:
106 return ResourceClass::UAV;
107 case RegisterType::CBuffer:
108 return ResourceClass::CBuffer;
109 case RegisterType::Sampler:
110 return ResourceClass::Sampler;
111 case RegisterType::C:
112 case RegisterType::I:
116 llvm_unreachable(
"unexpected RegisterType value");
120 ResourceClass ResClass) {
122 "DeclBindingInfo already added");
128 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
129 return &BindingsList.emplace_back(VD, ResClass);
133 ResourceClass ResClass) {
134 auto Entry = DeclToBindingListIndex.find(VD);
135 if (Entry != DeclToBindingListIndex.end()) {
136 for (
unsigned Index = Entry->getSecond();
137 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
139 if (BindingsList[Index].ResClass == ResClass)
140 return &BindingsList[Index];
147 return DeclToBindingListIndex.contains(VD);
159 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
162 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
163 : llvm::hlsl::ResourceClass::SRV;
164 auto RK = CBuffer ? llvm::hlsl::ResourceKind::CBuffer
165 : llvm::hlsl::ResourceKind::TBuffer;
180 constexpr unsigned CBufferAlign = 16;
188 unsigned FieldAlign = 4;
190 FieldAlign = CBufferAlign;
191 Size = llvm::alignTo(Size, FieldAlign);
195 if (
unsigned ElementCount = AT->getSize().getZExtValue()) {
196 unsigned ElementSize =
198 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
199 Size = AlignedElementSize * (ElementCount - 1) + ElementSize;
202 unsigned ElementCount = VT->getNumElements();
203 unsigned ElementSize =
205 Size = ElementSize * ElementCount;
220 bool HasPackOffset =
false;
221 bool HasNonPackOffset =
false;
222 for (
auto *Field : BufDecl->
decls()) {
223 VarDecl *Var = dyn_cast<VarDecl>(Field);
226 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
227 PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());
228 HasPackOffset =
true;
230 HasNonPackOffset =
true;
237 if (HasNonPackOffset)
243 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
244 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
245 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
246 return LHS.second->getOffsetInBytes() <
247 RHS.second->getOffsetInBytes();
249 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
250 VarDecl *Var = PackOffsetVec[i].first;
251 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
253 unsigned Begin =
Attr->getOffsetInBytes();
254 unsigned End =
Begin + Size;
255 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
256 if (End > NextBegin) {
257 VarDecl *NextVar = PackOffsetVec[i + 1].first;
267 CAT = dyn_cast<ConstantArrayType>(
269 return CAT !=
nullptr;
315 Base.getType()->getAsCXXRecordDecl()))
326 assert(RD ==
nullptr &&
327 "there should be at most 1 record by a given name in a scope");
344 Name.append(NameBaseII->
getName());
351 size_t NameLength = Name.size();
360 Name.append(llvm::Twine(suffix).str());
361 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
368 Name.truncate(NameLength);
410 "struct is already HLSL buffer compatible");
426 if (
unsigned NumBases = StructDecl->
getNumBases()) {
427 assert(NumBases == 1 &&
"HLSL supports only one base type");
501 auto *BufDecl = cast<HLSLBufferDecl>(Dcl);
502 BufDecl->setRBraceLoc(RBrace);
514 int X,
int Y,
int Z) {
515 if (HLSLNumThreadsAttr *NT =
D->
getAttr<HLSLNumThreadsAttr>()) {
516 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
517 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
518 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
528 int Min,
int Max,
int Preferred,
529 int SpelledArgsCount) {
530 if (HLSLWaveSizeAttr *WS =
D->
getAttr<HLSLWaveSizeAttr>()) {
531 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
532 WS->getPreferred() != Preferred ||
533 WS->getSpelledArgsCount() != SpelledArgsCount) {
534 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
535 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
541 Result->setSpelledArgsCount(SpelledArgsCount);
547 llvm::Triple::EnvironmentType ShaderType) {
548 if (HLSLShaderAttr *NT =
D->
getAttr<HLSLShaderAttr>()) {
549 if (NT->getType() != ShaderType) {
550 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
551 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
555 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
558HLSLParamModifierAttr *
560 HLSLParamModifierAttr::Spelling Spelling) {
563 if (HLSLParamModifierAttr *PA =
D->
getAttr<HLSLParamModifierAttr>()) {
564 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
565 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
568 return HLSLParamModifierAttr::Create(
570 HLSLParamModifierAttr::Keyword_inout);
572 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
573 Diag(PA->getLocation(), diag::note_conflicting_attribute);
586 if (HLSLShaderAttr::isValidShaderType(
Env) &&
Env != llvm::Triple::Library) {
587 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
590 if (Shader->getType() !=
Env) {
591 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
603 case llvm::Triple::UnknownEnvironment:
604 case llvm::Triple::Library:
607 llvm_unreachable(
"Unhandled environment in triple");
613 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
614 assert(ShaderAttr &&
"Entry point has no shader attribute");
615 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
619 case llvm::Triple::Pixel:
620 case llvm::Triple::Vertex:
621 case llvm::Triple::Geometry:
622 case llvm::Triple::Hull:
623 case llvm::Triple::Domain:
624 case llvm::Triple::RayGeneration:
625 case llvm::Triple::Intersection:
626 case llvm::Triple::AnyHit:
627 case llvm::Triple::ClosestHit:
628 case llvm::Triple::Miss:
629 case llvm::Triple::Callable:
630 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
632 {llvm::Triple::Compute,
633 llvm::Triple::Amplification,
634 llvm::Triple::Mesh});
637 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
639 {llvm::Triple::Compute,
640 llvm::Triple::Amplification,
641 llvm::Triple::Mesh});
646 case llvm::Triple::Compute:
647 case llvm::Triple::Amplification:
648 case llvm::Triple::Mesh:
649 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
651 << llvm::Triple::getEnvironmentTypeName(ST);
654 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
655 if (Ver < VersionTuple(6, 6)) {
656 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
659 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
662 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
663 << WS << WS->getSpelledArgsCount() <<
"6.8";
669 llvm_unreachable(
"Unhandled environment in triple");
679 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
689 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
690 assert(ShaderAttr &&
"Entry point has no shader attribute");
691 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
693 switch (AnnotationAttr->
getKind()) {
694 case attr::HLSLSV_DispatchThreadID:
695 case attr::HLSLSV_GroupIndex:
696 case attr::HLSLSV_GroupThreadID:
697 case attr::HLSLSV_GroupID:
698 if (ST == llvm::Triple::Compute)
703 llvm_unreachable(
"Unknown HLSLAnnotationAttr");
708 const Attr *A, llvm::Triple::EnvironmentType Stage,
709 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
711 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
712 [](llvm::Triple::EnvironmentType ST) {
714 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
716 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
717 << A << llvm::Triple::getEnvironmentTypeName(Stage)
718 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
721template <CastKind Kind>
724 Ty = VTy->getElementType();
729template <CastKind Kind>
741 if (LHSFloat && RHSFloat) {
744 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
746 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
750 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
754 return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
756 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
769 if (LHSSigned == RHSSigned) {
770 if (IsCompAssign || IntOrder >= 0)
771 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
773 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
778 if (IntOrder != (LHSSigned ? 1 : -1)) {
779 if (IsCompAssign || RHSSigned)
780 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
781 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
788 if (IsCompAssign || LHSSigned)
789 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
790 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
801 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
807 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
809 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
815 return CK_FloatingCast;
817 return CK_IntegralCast;
819 return CK_IntegralToFloating;
821 return CK_FloatingToIntegral;
834 if (!LVecTy && IsCompAssign) {
845 unsigned EndSz = std::numeric_limits<unsigned>::max();
848 LSz = EndSz = LVecTy->getNumElements();
851 assert(EndSz != std::numeric_limits<unsigned>::max() &&
852 "one of the above should have had a value");
856 if (IsCompAssign && LSz != EndSz) {
858 diag::err_hlsl_vector_compound_assignment_truncation)
859 << LHSType << RHSType;
864 castVector<CK_HLSLVectorTruncation>(
SemaRef, RHS, RHSType, EndSz);
865 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
866 castVector<CK_HLSLVectorTruncation>(
SemaRef, LHS, LHSType, EndSz);
869 castVector<CK_VectorSplat>(
SemaRef, RHS, RHSType, EndSz);
870 if (!IsCompAssign && !LVecTy)
871 castVector<CK_VectorSplat>(
SemaRef, LHS, LHSType, EndSz);
883 LElTy, RElTy, IsCompAssign);
886 "HLSL Vectors can only contain integer or floating point types");
888 LElTy, RElTy, IsCompAssign);
893 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
894 "Called with non-logical operator");
896 llvm::raw_svector_ostream OS(Buff);
898 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
899 OS << NewFnName <<
"(";
910 llvm::VersionTuple SMVersion =
912 uint32_t ZMax = 1024;
913 uint32_t ThreadMax = 1024;
914 if (SMVersion.getMajor() <= 4) {
917 }
else if (SMVersion.getMajor() == 5) {
927 diag::err_hlsl_numthreads_argument_oor)
936 diag::err_hlsl_numthreads_argument_oor)
945 diag::err_hlsl_numthreads_argument_oor)
950 if (
X * Y * Z > ThreadMax) {
951 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
968 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
976 if (SpelledArgsCount > 1 &&
980 uint32_t Preferred = 0;
981 if (SpelledArgsCount > 2 &&
985 if (SpelledArgsCount > 2) {
988 diag::err_attribute_power_of_two_in_range)
989 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
994 if (Preferred < Min || Preferred >
Max) {
996 diag::err_attribute_power_of_two_in_range)
997 << AL <<
Min <<
Max << Preferred;
1000 }
else if (SpelledArgsCount > 1) {
1003 diag::err_attribute_power_of_two_in_range)
1004 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1008 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1011 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1016 diag::err_attribute_power_of_two_in_range)
1017 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1022 HLSLWaveSizeAttr *NewAttr =
1032 (VT && VT->getNumElements() > 3)) {
1033 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1034 << AL <<
"uint/uint2/uint3";
1042 auto *VD = cast<ValueDecl>(
D);
1051 auto *VD = cast<ValueDecl>(
D);
1060 auto *VD = cast<ValueDecl>(
D);
1069 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1070 << AL <<
"shader constant in a constant buffer";
1074 uint32_t SubComponent;
1081 QualType T = cast<VarDecl>(
D)->getType().getCanonicalType();
1089 if (IsAggregateTy || Size > 128) {
1090 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1094 if ((Component * 32 + Size) > 128) {
1095 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1100 EltTy = VT->getElementType();
1102 if (Align > 32 && Component == 1) {
1105 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1122 llvm::Triple::EnvironmentType ShaderType;
1123 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1124 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1125 << AL << Str << ArgLoc;
1139 assert(AttrList.size() &&
"expected list of resource attributes");
1148 bool HasResourceClass =
false;
1149 for (
const Attr *A : AttrList) {
1152 LocEnd = A->getRange().getEnd();
1153 switch (A->getKind()) {
1154 case attr::HLSLResourceClass: {
1155 ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();
1156 if (HasResourceClass) {
1158 ? diag::warn_duplicate_attribute_exact
1159 : diag::warn_duplicate_attribute)
1164 HasResourceClass =
true;
1168 if (ResAttrs.
IsROV) {
1169 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1172 ResAttrs.
IsROV =
true;
1174 case attr::HLSLRawBuffer:
1176 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1181 case attr::HLSLContainedType: {
1182 const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
1184 if (!ContainedTy.
isNull()) {
1185 S.
Diag(A->getLocation(), ContainedTy == Ty
1186 ? diag::warn_duplicate_attribute_exact
1187 : diag::warn_duplicate_attribute)
1196 llvm_unreachable(
"unhandled resource attribute type");
1200 if (!HasResourceClass) {
1201 S.
Diag(AttrList.back()->getRange().getEnd(),
1202 diag::err_hlsl_missing_resource_class);
1207 Wrapped, ContainedTy, ResAttrs);
1209 if (LocInfo && ContainedTyInfo) {
1222 if (!
T->isHLSLResourceType()) {
1223 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1234 case ParsedAttr::AT_HLSLResourceClass: {
1236 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1247 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(
Identifier, RC)) {
1248 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1256 case ParsedAttr::AT_HLSLROV:
1260 case ParsedAttr::AT_HLSLRawBuffer:
1264 case ParsedAttr::AT_HLSLContainedType: {
1266 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1272 assert(TSI &&
"no type source info for attribute argument");
1274 diag::err_incomplete_type))
1281 llvm_unreachable(
"unhandled HLSL attribute");
1284 HLSLResourcesTypeAttrs.emplace_back(A);
1290 if (!HLSLResourcesTypeAttrs.size())
1296 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1298 cast<HLSLAttributedResourceType>(QT.
getTypePtr());
1304 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1306 HLSLResourcesTypeAttrs.clear();
1314 auto I = LocsForHLSLAttributedResources.find(RT);
1315 if (I != LocsForHLSLAttributedResources.end()) {
1316 LocInfo = I->second;
1317 LocsForHLSLAttributedResources.erase(I);
1326void SemaHLSL::collectResourcesOnUserRecordDecl(
const VarDecl *VD,
1335 "incomplete arrays inside user defined types are not supported");
1347 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1350 Bindings.addDeclBindingInfo(VD, RC);
1351 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1357 collectResourcesOnUserRecordDecl(VD, RT);
1369 bool SpecifiedSpace) {
1370 int RegTypeNum =
static_cast<int>(RegType);
1373 if (
D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
1374 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1380 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
1381 : ResourceClass::SRV;
1391 assert(isa<VarDecl>(
D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
1398 if (RegType ==
getRegisterType(AttrResType->getAttrs().ResourceClass))
1413 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
1414 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1416 if (!DeclaredInCOrTBuffer &&
1419 if (RegType == RegisterType::CBuffer)
1420 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1421 else if (RegType != RegisterType::C)
1422 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1424 if (RegType == RegisterType::C)
1425 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
1427 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1437 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1445 bool RegisterTypesDetected[5] = {
false};
1446 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
1449 if (HLSLResourceBindingAttr *
attr =
1450 dyn_cast<HLSLResourceBindingAttr>(*it)) {
1453 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
1454 int otherRegTypeNum =
static_cast<int>(otherRegType);
1456 diag::err_hlsl_duplicate_register_annotation)
1460 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
1468 bool SpecifiedSpace) {
1471 assert(((isa<VarDecl>(
D) && !isa<HLSLBufferDecl>(
D)) ||
1472 (!isa<VarDecl>(
D) && isa<HLSLBufferDecl>(
D))) &&
1473 "expecting VarDecl or HLSLBufferDecl");
1484 if (isa<VarDecl>(TheDecl)) {
1486 cast<ValueDecl>(TheDecl)->getType(),
1487 diag::err_incomplete_type))
1490 StringRef Space =
"space0";
1491 StringRef Slot =
"";
1494 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1500 StringRef Str =
Loc->Ident->getName();
1504 bool SpecifiedSpace =
false;
1506 SpecifiedSpace =
true;
1509 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1515 Space =
Loc->Ident->getName();
1516 SpaceArgLoc =
Loc->Loc;
1522 unsigned SlotNum = 0;
1523 unsigned SpaceNum = 0;
1526 if (!Slot.empty()) {
1528 Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
1531 if (RegType == RegisterType::I) {
1532 Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);
1536 StringRef SlotNumStr = Slot.substr(1);
1537 if (SlotNumStr.getAsInteger(10, SlotNum)) {
1538 Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);
1543 if (!Space.starts_with(
"space")) {
1544 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1547 StringRef SpaceNumStr = Space.substr(5);
1548 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
1549 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1557 HLSLResourceBindingAttr *NewAttr =
1558 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
1560 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
1615 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
1619 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
1620 unsigned CurrentShaderStageBit;
1625 bool ReportOnlyShaderStageIssues;
1628 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
1629 static_assert(
sizeof(
unsigned) >= 4);
1630 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
1631 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
1632 "ShaderType is too big for this bitmap");
1635 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
1636 CurrentShaderEnvironment = ShaderType;
1637 CurrentShaderStageBit = (1 << bitmapIndex);
1640 void SetUnknownShaderStageContext() {
1641 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
1642 CurrentShaderStageBit = (1 << 31);
1645 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
1646 return CurrentShaderEnvironment;
1649 bool InUnknownShaderStageContext()
const {
1650 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
1655 unsigned &ScannedStages = ScannedDecls[FD];
1656 ScannedStages |= CurrentShaderStageBit;
1659 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
1661 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
1662 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
1665 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
1666 return ScannerStages & CurrentShaderStageBit;
1669 static bool NeverBeenScanned(
unsigned ScannedStages) {
1670 return ScannedStages == 0;
1675 void CheckDeclAvailability(
NamedDecl *
D,
const AvailabilityAttr *AA,
1677 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *
D);
1678 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
1681 DiagnoseHLSLAvailability(
Sema &SemaRef)
1683 CurrentShaderEnvironment(
llvm::Triple::UnknownEnvironment),
1684 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
1690 bool VisitDeclRefExpr(
DeclRefExpr *DRE)
override {
1693 HandleFunctionOrMethodRef(FD, DRE);
1697 bool VisitMemberExpr(
MemberExpr *ME)
override {
1700 HandleFunctionOrMethodRef(FD, ME);
1705void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
1707 assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
1708 "expected DeclRefExpr or MemberExpr");
1712 if (FD->
hasBody(FDWithBody)) {
1713 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
1714 DeclsToScan.push_back(FDWithBody);
1719 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
1721 CheckDeclAvailability(
1725void DiagnoseHLSLAvailability::RunOnTranslationUnit(
1734 DeclContextsToScan.push_back(TU);
1736 while (!DeclContextsToScan.empty()) {
1737 const DeclContext *DC = DeclContextsToScan.pop_back_val();
1738 for (
auto &
D : DC->
decls()) {
1745 if (llvm::dyn_cast<NamespaceDecl>(
D) || llvm::dyn_cast<ExportDecl>(
D)) {
1746 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(
D));
1756 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
1757 SetShaderStageContext(ShaderAttr->getType());
1766 for (
const auto *Redecl : FD->
redecls()) {
1767 if (Redecl->isInExportDeclContext()) {
1774 SetUnknownShaderStageContext();
1782void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
1783 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
1784 DeclsToScan.push_back(FD);
1786 while (!DeclsToScan.empty()) {
1794 const unsigned ScannedStages = GetScannedStages(FD);
1795 if (WasAlreadyScannedInCurrentStage(ScannedStages))
1798 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
1800 AddToScannedFunctions(FD);
1805bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
1806 const AvailabilityAttr *AA) {
1811 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
1812 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
1815 llvm::Triple::EnvironmentType AttrEnv =
1816 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
1818 return CurrentEnv == AttrEnv;
1821const AvailabilityAttr *
1822DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *
D) {
1823 AvailabilityAttr
const *PartialMatch =
nullptr;
1827 for (
const auto *A :
D->
attrs()) {
1828 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
1829 StringRef AttrPlatform = Avail->getPlatform()->getName();
1830 StringRef TargetPlatform =
1834 if (AttrPlatform == TargetPlatform) {
1836 if (HasMatchingEnvironmentOrNone(Avail))
1838 PartialMatch = Avail;
1842 return PartialMatch;
1847void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *
D,
1848 const AvailabilityAttr *AA,
1867 if (ReportOnlyShaderStageIssues)
1873 if (InUnknownShaderStageContext())
1878 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
1879 VersionTuple Introduced = AA->getIntroduced();
1888 llvm::StringRef PlatformName(
1891 llvm::StringRef CurrentEnvStr =
1892 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
1894 llvm::StringRef AttrEnvStr =
1895 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
1896 bool UseEnvironment = !AttrEnvStr.empty();
1898 if (EnvironmentMatches) {
1900 <<
Range <<
D << PlatformName << Introduced.getAsString()
1901 << UseEnvironment << CurrentEnvStr;
1907 SemaRef.
Diag(
D->
getLocation(), diag::note_partial_availability_specified_here)
1908 <<
D << PlatformName << Introduced.getAsString()
1910 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
1922 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
1925 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
1938 bool AllBArgAreVectors =
true;
1939 for (
unsigned i = 1; i < TheCall->
getNumArgs(); ++i) {
1943 if (VecTyB ==
nullptr)
1944 AllBArgAreVectors &=
false;
1945 if (VecTyA && VecTyB ==
nullptr) {
1948 S->
Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1953 if (VecTyA && VecTyB) {
1954 bool retValue =
false;
1955 if (VecTyA->getElementType() != VecTyB->getElementType()) {
1959 diag::err_vec_builtin_incompatible_vector)
1964 if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
1968 S->
Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
1978 if (VecTyA ==
nullptr && AllBArgAreVectors) {
1981 S->
Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
2003 if (Check(PassedType)) {
2006 ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
2017 for (
unsigned i = 0; i < TheCall->
getNumArgs(); ++i) {
2028 return !PassedType->hasFloatingRepresentation();
2031 checkAllFloatTypes);
2047 unsigned ArgIndex) {
2048 auto *Arg = TheCall->
getArg(ArgIndex);
2053 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2059 if (
const auto *VecTy = PassedType->getAs<
VectorType>())
2060 return VecTy->getElementType()->isDoubleType();
2068 return !PassedType->hasIntegerRepresentation() &&
2069 !PassedType->hasFloatingRepresentation();
2072 checkAllSignedTypes);
2077 return !PassedType->hasUnsignedIntegerRepresentation();
2080 checkAllUnsignedTypes);
2093 unsigned ArgIndex) {
2102 diag::err_typecheck_expect_scalar_or_vector)
2103 << ArgType << Scalar;
2110 unsigned ArgIndex) {
2116 (VTy && VTy->getElementType()->isScalarType()))) {
2118 diag::err_typecheck_expect_any_scalar_or_vector)
2135 diag::err_typecheck_expect_any_scalar_or_vector)
2148 diag::err_typecheck_call_different_arg_types)
2178 diag::err_typecheck_call_different_arg_types)
2189 diag::err_typecheck_vector_lengths_not_equal)
2208 diag::err_typecheck_expect_hlsl_resource)
2212 if (Check && Check(ResTy)) {
2214 diag::err_invalid_hlsl_resource_type)
2224 switch (BuiltinID) {
2225 case Builtin::BI__builtin_hlsl_resource_getpointer: {
2234 QualType ContainedTy = ResourceTy->getContainedType();
2241 case Builtin::BI__builtin_hlsl_all:
2242 case Builtin::BI__builtin_hlsl_any: {
2247 case Builtin::BI__builtin_hlsl_asdouble: {
2256 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
2267 case Builtin::BI__builtin_hlsl_cross: {
2275 int NumElementsArg1 =
2277 int NumElementsArg2 =
2280 if (NumElementsArg1 != 3) {
2281 int LessOrMore = NumElementsArg1 > 3 ? 1 : 0;
2283 diag::err_vector_incorrect_num_elements)
2284 << LessOrMore << 3 << NumElementsArg1 << 1;
2287 if (NumElementsArg2 != 3) {
2288 int LessOrMore = NumElementsArg2 > 3 ? 1 : 0;
2291 diag::err_vector_incorrect_num_elements)
2292 << LessOrMore << 3 << NumElementsArg2 << 1;
2302 case Builtin::BI__builtin_hlsl_dot: {
2313 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
2314 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
2325 EltTy = VecTy->getElementType();
2327 VecTy->getVectorKind());
2339 case Builtin::BI__builtin_hlsl_select: {
2348 if (VTy && VTy->getElementType()->isBooleanType() &&
2353 case Builtin::BI__builtin_hlsl_elementwise_saturate:
2354 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
2361 case Builtin::BI__builtin_hlsl_elementwise_degrees:
2362 case Builtin::BI__builtin_hlsl_elementwise_radians:
2363 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
2364 case Builtin::BI__builtin_hlsl_elementwise_frac: {
2371 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
2379 case Builtin::BI__builtin_hlsl_lerp: {
2390 case Builtin::BI__builtin_hlsl_mad: {
2401 case Builtin::BI__builtin_hlsl_normalize: {
2413 case Builtin::BI__builtin_hlsl_elementwise_sign: {
2421 case Builtin::BI__builtin_hlsl_step: {
2433 case Builtin::BI__builtin_hlsl_wave_active_max:
2434 case Builtin::BI__builtin_hlsl_wave_active_sum: {
2450 case Builtin::BI__builtin_elementwise_bitreverse: {
2455 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
2461 QualType ArgTyIndex = Index.get()->getType();
2464 diag::err_typecheck_convert_incompatible)
2478 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
2483 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
2499 case Builtin::BI__builtin_hlsl_elementwise_clip: {
2507 case Builtin::BI__builtin_elementwise_acos:
2508 case Builtin::BI__builtin_elementwise_asin:
2509 case Builtin::BI__builtin_elementwise_atan:
2510 case Builtin::BI__builtin_elementwise_atan2:
2511 case Builtin::BI__builtin_elementwise_ceil:
2512 case Builtin::BI__builtin_elementwise_cos:
2513 case Builtin::BI__builtin_elementwise_cosh:
2514 case Builtin::BI__builtin_elementwise_exp:
2515 case Builtin::BI__builtin_elementwise_exp2:
2516 case Builtin::BI__builtin_elementwise_floor:
2517 case Builtin::BI__builtin_elementwise_fmod:
2518 case Builtin::BI__builtin_elementwise_log:
2519 case Builtin::BI__builtin_elementwise_log2:
2520 case Builtin::BI__builtin_elementwise_log10:
2521 case Builtin::BI__builtin_elementwise_pow:
2522 case Builtin::BI__builtin_elementwise_roundeven:
2523 case Builtin::BI__builtin_elementwise_sin:
2524 case Builtin::BI__builtin_elementwise_sinh:
2525 case Builtin::BI__builtin_elementwise_sqrt:
2526 case Builtin::BI__builtin_elementwise_tan:
2527 case Builtin::BI__builtin_elementwise_tanh:
2528 case Builtin::BI__builtin_elementwise_trunc: {
2533 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
2535 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
2536 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
2544 std::optional<llvm::APSInt> Offset =
2546 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
2548 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
2561 WorkList.push_back(BaseTy);
2562 while (!WorkList.empty()) {
2564 T =
T.getCanonicalType().getUnqualifiedType();
2565 assert(!isa<MatrixType>(
T) &&
"Matrix types not yet supported in HLSL");
2566 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
2574 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
2575 List.insert(List.end(), ElementFields.begin(), ElementFields.end());
2580 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
2581 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
2584 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2596 for (
const auto *FD : RD->
fields())
2597 FieldTypes.push_back(FD->
getType());
2599 std::reverse(FieldTypes.begin(), FieldTypes.end());
2600 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2607 FieldTypes.push_back(
Base.getType());
2608 std::reverse(FieldTypes.begin(), FieldTypes.end());
2609 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2637 int ArraySize = VT->getNumElements();
2642 QualType ElTy = VT->getElementType();
2671 return llvm::equal(T1Types, T2Types,
2682 bool HadError =
false;
2684 for (
unsigned i = 0, e = New->
getNumParams(); i != e; ++i) {
2692 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
2693 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
2694 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
2695 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
2697 if (NSpellingIdx != OSpellingIdx) {
2699 diag::err_hlsl_param_qualifier_mismatch)
2700 << NDAttr << NewParam;
2710 assert(Param->
hasAttr<HLSLParamModifierAttr>() &&
2711 "We should not get here without a parameter modifier expression");
2712 const auto *
Attr = Param->
getAttr<HLSLParamModifierAttr>();
2719 << Arg << (IsInOut ? 1 : 0);
2732 << Arg << (IsInOut ? 1 : 0);
2750 auto *OpV =
new (Ctx)
2756 tok::equal, ArgOpV, OpV);
2772 "Pointer and reference types cannot be inout or out parameters");
2784 diag::err_typecheck_decl_incomplete_type)) {
2791 collectResourcesOnVarDecl(VD);
2794 processExplicitBindingsOnDecl(VD);
2800void SemaHLSL::collectResourcesOnVarDecl(
VarDecl *VD) {
2802 "expected global variable that contains HLSL resource");
2805 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
2806 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
2807 ? ResourceClass::CBuffer
2808 : ResourceClass::SRV);
2823 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
2828 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
2829 collectResourcesOnUserRecordDecl(VD, RT);
2835void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
2839 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
2844 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
2845 "never have an attribute created");
2847 if (RT == RegisterType::C) {
2848 if (
Bindings.hasBindingInfoForDecl(VD))
2850 diag::warn_hlsl_user_defined_type_missing_member)
2851 <<
static_cast<int>(RT);
2864 diag::warn_hlsl_user_defined_type_missing_member)
2865 <<
static_cast<int>(RT);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static bool isResourceRecordType(const clang::Type *Ty)
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.
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
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 bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall)
static bool CheckFloatingOrIntRepresentation(Sema *S, CallExpr *TheCall)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
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 CheckArgTypeIsCorrect(Sema *S, Expr *Arg, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)
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 CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall)
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 CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)
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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
unsigned getIntWidth(QualType T) const
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified 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,...
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.
CanQualType UnsignedIntTy
QualType getCommonSugaredType(QualType X, QualType Y, bool Unqualified=false)
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 getCorrespondingUnsignedType(QualType T) 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 ...
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceRange getRange() const
SourceLocation getLoc() const
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
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.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr, bool DelayTypeCreation=false)
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 LLVM_READONLY
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.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
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.
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.
Decl - This represents one declaration (or definition), e.g.
attr_iterator attr_end() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
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()
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
Recursive AST visitor that supports extension via dynamic dispatch.
This represents one expression.
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, does not have an incomplet...
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
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
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.
static const HLSLAttributedResourceType * findHandleTypeOnResource(const Type *RT)
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
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.
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.
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.
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
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)
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)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL)
void CheckEntryPoint(FunctionDecl *FD)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
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)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU)
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)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
QualType getInoutParameterType(QualType Ty)
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)
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL)
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
Scope * getCurScope() const
Retrieve the parser's current scope.
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
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.
bool BuiltinVectorToScalarMath(CallExpr *TheCall)
bool IsLayoutCompatible(QualType T1, QualType T2) const
const LangOptions & getLangOpts() const
bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall)
DeclContext * getCurLexicalContext() const
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
bool BuiltinElementwiseTernaryMath(CallExpr *TheCall, bool CheckForFloatArgs=true)
ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr)
Binary Operators. 'Tok' is the token for the operator.
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() 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
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.
const Type * getTypeForDecl() const
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 isStructureType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isBooleanType() const
bool isIncompleteArrayType() const
bool isConstantArrayType() const
bool isArithmeticType() const
bool isHLSLBuiltinIntangibleType() 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.
bool isFloat32Type() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
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 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
void setType(QualType newType)
Represents a variable declaration or definition.
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
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
The JSON file list parser is used to communicate input to InstallAPI.
@ ICIS_NoInit
No in-class initializer.
@ OK_Ordinary
An ordinary object is located at an address in memory.
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
ActionResult< Expr * > ExprResult
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.
const FunctionProtoType * T
@ Generic
not a target-specific vector type
Diagnostic wrappers for TextAPI types for error reporting.
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
TypeSourceInfo * ContainedTyInfo
llvm::dxil::ResourceClass ResourceClass
Wraps an identifier and optional source location for the identifier.
Describes how types, statements, expressions, and declarations should be printed.