14#include "clang/AST/Attrs.inc"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/SmallVector.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/ADT/StringRef.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/DXILABI.h"
37#include "llvm/Support/ErrorHandling.h"
38#include "llvm/TargetParser/Triple.h"
47 case ResourceClass::SRV:
48 return RegisterType::SRV;
49 case ResourceClass::UAV:
50 return RegisterType::UAV;
51 case ResourceClass::CBuffer:
52 return RegisterType::CBuffer;
53 case ResourceClass::Sampler:
54 return RegisterType::Sampler;
56 llvm_unreachable(
"unexpected ResourceClass value");
62 assert(RT !=
nullptr);
66 *RT = RegisterType::SRV;
70 *RT = RegisterType::UAV;
74 *RT = RegisterType::CBuffer;
78 *RT = RegisterType::Sampler;
82 *RT = RegisterType::C;
86 *RT = RegisterType::I;
95 case RegisterType::SRV:
96 return ResourceClass::SRV;
97 case RegisterType::UAV:
98 return ResourceClass::UAV;
99 case RegisterType::CBuffer:
100 return ResourceClass::CBuffer;
101 case RegisterType::Sampler:
102 return ResourceClass::Sampler;
103 case RegisterType::C:
104 case RegisterType::I:
108 llvm_unreachable(
"unexpected RegisterType value");
112 ResourceClass ResClass) {
114 "DeclBindingInfo already added");
120 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
121 return &BindingsList.emplace_back(VD, ResClass);
125 ResourceClass ResClass) {
126 auto Entry = DeclToBindingListIndex.find(VD);
127 if (Entry != DeclToBindingListIndex.end()) {
128 for (
unsigned Index = Entry->getSecond();
129 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
131 if (BindingsList[Index].ResClass == ResClass)
132 return &BindingsList[Index];
139 return DeclToBindingListIndex.contains(VD);
151 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
154 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
155 : llvm::hlsl::ResourceClass::SRV;
156 auto RK = CBuffer ? llvm::hlsl::ResourceKind::CBuffer
157 : llvm::hlsl::ResourceKind::TBuffer;
172 constexpr unsigned CBufferAlign = 16;
180 unsigned FieldAlign = 4;
182 FieldAlign = CBufferAlign;
183 Size = llvm::alignTo(Size, FieldAlign);
187 if (
unsigned ElementCount = AT->getSize().getZExtValue()) {
188 unsigned ElementSize =
190 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
191 Size = AlignedElementSize * (ElementCount - 1) + ElementSize;
194 unsigned ElementCount = VT->getNumElements();
195 unsigned ElementSize =
197 Size = ElementSize * ElementCount;
212 bool HasPackOffset =
false;
213 bool HasNonPackOffset =
false;
214 for (
auto *Field : BufDecl->
decls()) {
215 VarDecl *Var = dyn_cast<VarDecl>(Field);
218 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
219 PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());
220 HasPackOffset =
true;
222 HasNonPackOffset =
true;
229 if (HasNonPackOffset)
235 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
236 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
237 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
238 return LHS.second->getOffsetInBytes() <
239 RHS.second->getOffsetInBytes();
241 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
242 VarDecl *Var = PackOffsetVec[i].first;
243 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
245 unsigned Begin =
Attr->getOffsetInBytes();
246 unsigned End =
Begin + Size;
247 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
248 if (End > NextBegin) {
249 VarDecl *NextVar = PackOffsetVec[i + 1].first;
257 auto *BufDecl = cast<HLSLBufferDecl>(Dcl);
258 BufDecl->setRBraceLoc(RBrace);
267 int X,
int Y,
int Z) {
268 if (HLSLNumThreadsAttr *NT =
D->
getAttr<HLSLNumThreadsAttr>()) {
269 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
270 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
271 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
281 int Min,
int Max,
int Preferred,
282 int SpelledArgsCount) {
283 if (HLSLWaveSizeAttr *WS =
D->
getAttr<HLSLWaveSizeAttr>()) {
284 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
285 WS->getPreferred() != Preferred ||
286 WS->getSpelledArgsCount() != SpelledArgsCount) {
287 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
288 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
294 Result->setSpelledArgsCount(SpelledArgsCount);
300 llvm::Triple::EnvironmentType ShaderType) {
301 if (HLSLShaderAttr *NT =
D->
getAttr<HLSLShaderAttr>()) {
302 if (NT->getType() != ShaderType) {
303 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
304 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
308 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
311HLSLParamModifierAttr *
313 HLSLParamModifierAttr::Spelling Spelling) {
316 if (HLSLParamModifierAttr *PA =
D->
getAttr<HLSLParamModifierAttr>()) {
317 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
318 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
321 return HLSLParamModifierAttr::Create(
323 HLSLParamModifierAttr::Keyword_inout);
325 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
326 Diag(PA->getLocation(), diag::note_conflicting_attribute);
339 if (HLSLShaderAttr::isValidShaderType(
Env) &&
Env != llvm::Triple::Library) {
340 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
343 if (Shader->getType() !=
Env) {
344 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
356 case llvm::Triple::UnknownEnvironment:
357 case llvm::Triple::Library:
360 llvm_unreachable(
"Unhandled environment in triple");
366 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
367 assert(ShaderAttr &&
"Entry point has no shader attribute");
368 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
372 case llvm::Triple::Pixel:
373 case llvm::Triple::Vertex:
374 case llvm::Triple::Geometry:
375 case llvm::Triple::Hull:
376 case llvm::Triple::Domain:
377 case llvm::Triple::RayGeneration:
378 case llvm::Triple::Intersection:
379 case llvm::Triple::AnyHit:
380 case llvm::Triple::ClosestHit:
381 case llvm::Triple::Miss:
382 case llvm::Triple::Callable:
383 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
385 {llvm::Triple::Compute,
386 llvm::Triple::Amplification,
387 llvm::Triple::Mesh});
390 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
392 {llvm::Triple::Compute,
393 llvm::Triple::Amplification,
394 llvm::Triple::Mesh});
399 case llvm::Triple::Compute:
400 case llvm::Triple::Amplification:
401 case llvm::Triple::Mesh:
402 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
404 << llvm::Triple::getEnvironmentTypeName(ST);
407 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
408 if (Ver < VersionTuple(6, 6)) {
409 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
412 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
415 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
416 << WS << WS->getSpelledArgsCount() <<
"6.8";
422 llvm_unreachable(
"Unhandled environment in triple");
432 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
442 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
443 assert(ShaderAttr &&
"Entry point has no shader attribute");
444 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
446 switch (AnnotationAttr->
getKind()) {
447 case attr::HLSLSV_DispatchThreadID:
448 case attr::HLSLSV_GroupIndex:
449 case attr::HLSLSV_GroupThreadID:
450 case attr::HLSLSV_GroupID:
451 if (ST == llvm::Triple::Compute)
456 llvm_unreachable(
"Unknown HLSLAnnotationAttr");
461 const Attr *A, llvm::Triple::EnvironmentType Stage,
462 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
464 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
465 [](llvm::Triple::EnvironmentType ST) {
467 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
469 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
470 << A << llvm::Triple::getEnvironmentTypeName(Stage)
471 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
474template <CastKind Kind>
477 Ty = VTy->getElementType();
482template <CastKind Kind>
494 if (LHSFloat && RHSFloat) {
497 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
499 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
503 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
507 return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
509 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
522 if (LHSSigned == RHSSigned) {
523 if (IsCompAssign || IntOrder >= 0)
524 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
526 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
531 if (IntOrder != (LHSSigned ? 1 : -1)) {
532 if (IsCompAssign || RHSSigned)
533 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
534 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
540 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
541 if (IsCompAssign || LHSSigned)
542 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
543 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
554 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
557 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
558 QualType NewTy = Ctx.getExtVectorType(
560 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
562 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
568 return CK_FloatingCast;
570 return CK_IntegralCast;
572 return CK_IntegralToFloating;
574 return CK_FloatingToIntegral;
587 if (!LVecTy && IsCompAssign) {
591 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
598 unsigned EndSz = std::numeric_limits<unsigned>::max();
601 LSz = EndSz = LVecTy->getNumElements();
604 assert(EndSz != std::numeric_limits<unsigned>::max() &&
605 "one of the above should have had a value");
609 if (IsCompAssign && LSz != EndSz) {
611 diag::err_hlsl_vector_compound_assignment_truncation)
612 << LHSType << RHSType;
617 castVector<CK_HLSLVectorTruncation>(
SemaRef, RHS, RHSType, EndSz);
618 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
619 castVector<CK_HLSLVectorTruncation>(
SemaRef, LHS, LHSType, EndSz);
622 castVector<CK_VectorSplat>(
SemaRef, RHS, RHSType, EndSz);
623 if (!IsCompAssign && !LVecTy)
624 castVector<CK_VectorSplat>(
SemaRef, LHS, LHSType, EndSz);
627 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
628 return Ctx.getCommonSugaredType(LHSType, RHSType);
636 LElTy, RElTy, IsCompAssign);
639 "HLSL Vectors can only contain integer or floating point types");
641 LElTy, RElTy, IsCompAssign);
646 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
647 "Called with non-logical operator");
649 llvm::raw_svector_ostream OS(Buff);
651 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
652 OS << NewFnName <<
"(";
663 llvm::VersionTuple SMVersion =
665 uint32_t ZMax = 1024;
666 uint32_t ThreadMax = 1024;
667 if (SMVersion.getMajor() <= 4) {
670 }
else if (SMVersion.getMajor() == 5) {
680 diag::err_hlsl_numthreads_argument_oor)
689 diag::err_hlsl_numthreads_argument_oor)
698 diag::err_hlsl_numthreads_argument_oor)
703 if (
X * Y * Z > ThreadMax) {
704 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
721 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
729 if (SpelledArgsCount > 1 &&
733 uint32_t Preferred = 0;
734 if (SpelledArgsCount > 2 &&
738 if (SpelledArgsCount > 2) {
741 diag::err_attribute_power_of_two_in_range)
742 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
747 if (Preferred < Min || Preferred >
Max) {
749 diag::err_attribute_power_of_two_in_range)
750 << AL <<
Min <<
Max << Preferred;
753 }
else if (SpelledArgsCount > 1) {
756 diag::err_attribute_power_of_two_in_range)
757 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
761 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
764 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
769 diag::err_attribute_power_of_two_in_range)
770 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
775 HLSLWaveSizeAttr *NewAttr =
785 (VT && VT->getNumElements() > 3)) {
786 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
787 << AL <<
"uint/uint2/uint3";
795 auto *VD = cast<ValueDecl>(
D);
804 auto *VD = cast<ValueDecl>(
D);
813 auto *VD = cast<ValueDecl>(
D);
822 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
823 << AL <<
"shader constant in a constant buffer";
827 uint32_t SubComponent;
834 QualType T = cast<VarDecl>(
D)->getType().getCanonicalType();
842 if (IsAggregateTy || Size > 128) {
843 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
847 if ((Component * 32 + Size) > 128) {
848 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
853 EltTy = VT->getElementType();
855 if (Align > 32 && Component == 1) {
858 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
875 llvm::Triple::EnvironmentType ShaderType;
876 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
877 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
878 << AL << Str << ArgLoc;
892 assert(AttrList.size() &&
"expected list of resource attributes");
901 bool HasResourceClass =
false;
902 for (
const Attr *A : AttrList) {
905 LocEnd = A->getRange().getEnd();
906 switch (A->getKind()) {
907 case attr::HLSLResourceClass: {
908 ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();
909 if (HasResourceClass) {
911 ? diag::warn_duplicate_attribute_exact
912 : diag::warn_duplicate_attribute)
917 HasResourceClass =
true;
921 if (ResAttrs.
IsROV) {
922 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
925 ResAttrs.
IsROV =
true;
927 case attr::HLSLRawBuffer:
929 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
934 case attr::HLSLContainedType: {
935 const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
937 if (!ContainedTy.
isNull()) {
938 S.
Diag(A->getLocation(), ContainedTy == Ty
939 ? diag::warn_duplicate_attribute_exact
940 : diag::warn_duplicate_attribute)
949 llvm_unreachable(
"unhandled resource attribute type");
953 if (!HasResourceClass) {
954 S.
Diag(AttrList.back()->getRange().getEnd(),
955 diag::err_hlsl_missing_resource_class);
960 Wrapped, ContainedTy, ResAttrs);
962 if (LocInfo && ContainedTyInfo) {
975 if (!
T->isHLSLResourceType()) {
976 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
987 case ParsedAttr::AT_HLSLResourceClass: {
989 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1000 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(
Identifier, RC)) {
1001 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1009 case ParsedAttr::AT_HLSLROV:
1013 case ParsedAttr::AT_HLSLRawBuffer:
1017 case ParsedAttr::AT_HLSLContainedType: {
1019 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1025 assert(TSI &&
"no type source info for attribute argument");
1027 diag::err_incomplete_type))
1034 llvm_unreachable(
"unhandled HLSL attribute");
1037 HLSLResourcesTypeAttrs.emplace_back(A);
1043 if (!HLSLResourcesTypeAttrs.size())
1049 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1051 cast<HLSLAttributedResourceType>(QT.
getTypePtr());
1057 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1059 HLSLResourcesTypeAttrs.clear();
1067 auto I = LocsForHLSLAttributedResources.find(RT);
1068 if (I != LocsForHLSLAttributedResources.end()) {
1069 LocInfo = I->second;
1070 LocsForHLSLAttributedResources.erase(I);
1079void SemaHLSL::collectResourcesOnUserRecordDecl(
const VarDecl *VD,
1088 "incomplete arrays inside user defined types are not supported");
1100 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1103 Bindings.addDeclBindingInfo(VD, RC);
1104 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1110 collectResourcesOnUserRecordDecl(VD, RT);
1122 bool SpecifiedSpace) {
1123 int RegTypeNum =
static_cast<int>(RegType);
1126 if (
D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
1127 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1133 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
1134 : ResourceClass::SRV;
1144 assert(isa<VarDecl>(
D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
1151 if (RegType ==
getRegisterType(AttrResType->getAttrs().ResourceClass))
1166 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
1167 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1169 if (!DeclaredInCOrTBuffer &&
1172 if (RegType == RegisterType::CBuffer)
1173 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1174 else if (RegType != RegisterType::C)
1175 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1177 if (RegType == RegisterType::C)
1178 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
1180 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1190 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1198 bool RegisterTypesDetected[5] = {
false};
1199 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
1202 if (HLSLResourceBindingAttr *
attr =
1203 dyn_cast<HLSLResourceBindingAttr>(*it)) {
1206 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
1207 int otherRegTypeNum =
static_cast<int>(otherRegType);
1209 diag::err_hlsl_duplicate_register_annotation)
1213 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
1221 bool SpecifiedSpace) {
1224 assert(((isa<VarDecl>(
D) && !isa<HLSLBufferDecl>(
D)) ||
1225 (!isa<VarDecl>(
D) && isa<HLSLBufferDecl>(
D))) &&
1226 "expecting VarDecl or HLSLBufferDecl");
1237 if (isa<VarDecl>(TheDecl)) {
1239 cast<ValueDecl>(TheDecl)->getType(),
1240 diag::err_incomplete_type))
1243 StringRef Space =
"space0";
1244 StringRef Slot =
"";
1247 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1253 StringRef Str =
Loc->Ident->getName();
1257 bool SpecifiedSpace =
false;
1259 SpecifiedSpace =
true;
1262 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1268 Space =
Loc->Ident->getName();
1269 SpaceArgLoc =
Loc->Loc;
1275 unsigned SlotNum = 0;
1276 unsigned SpaceNum = 0;
1279 if (!Slot.empty()) {
1281 Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
1284 if (RegType == RegisterType::I) {
1285 Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);
1289 StringRef SlotNumStr = Slot.substr(1);
1290 if (SlotNumStr.getAsInteger(10, SlotNum)) {
1291 Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);
1296 if (!Space.starts_with(
"space")) {
1297 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1300 StringRef SpaceNumStr = Space.substr(5);
1301 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
1302 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1310 HLSLResourceBindingAttr *NewAttr =
1311 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
1313 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
1368 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
1372 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
1373 unsigned CurrentShaderStageBit;
1378 bool ReportOnlyShaderStageIssues;
1381 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
1382 static_assert(
sizeof(
unsigned) >= 4);
1383 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
1384 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
1385 "ShaderType is too big for this bitmap");
1388 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
1389 CurrentShaderEnvironment = ShaderType;
1390 CurrentShaderStageBit = (1 << bitmapIndex);
1393 void SetUnknownShaderStageContext() {
1394 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
1395 CurrentShaderStageBit = (1 << 31);
1398 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
1399 return CurrentShaderEnvironment;
1402 bool InUnknownShaderStageContext()
const {
1403 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
1408 unsigned &ScannedStages = ScannedDecls[FD];
1409 ScannedStages |= CurrentShaderStageBit;
1412 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
1414 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
1415 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
1418 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
1419 return ScannerStages & CurrentShaderStageBit;
1422 static bool NeverBeenScanned(
unsigned ScannedStages) {
1423 return ScannedStages == 0;
1428 void CheckDeclAvailability(
NamedDecl *
D,
const AvailabilityAttr *AA,
1430 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *
D);
1431 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
1434 DiagnoseHLSLAvailability(
Sema &SemaRef)
1436 CurrentShaderEnvironment(
llvm::Triple::UnknownEnvironment),
1437 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
1443 bool VisitDeclRefExpr(
DeclRefExpr *DRE)
override {
1446 HandleFunctionOrMethodRef(FD, DRE);
1450 bool VisitMemberExpr(
MemberExpr *ME)
override {
1453 HandleFunctionOrMethodRef(FD, ME);
1458void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
1460 assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
1461 "expected DeclRefExpr or MemberExpr");
1465 if (FD->
hasBody(FDWithBody)) {
1466 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
1467 DeclsToScan.push_back(FDWithBody);
1472 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
1474 CheckDeclAvailability(
1478void DiagnoseHLSLAvailability::RunOnTranslationUnit(
1487 DeclContextsToScan.push_back(TU);
1489 while (!DeclContextsToScan.empty()) {
1490 const DeclContext *DC = DeclContextsToScan.pop_back_val();
1491 for (
auto &
D : DC->
decls()) {
1498 if (llvm::dyn_cast<NamespaceDecl>(
D) || llvm::dyn_cast<ExportDecl>(
D)) {
1499 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(
D));
1509 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
1510 SetShaderStageContext(ShaderAttr->getType());
1519 for (
const auto *Redecl : FD->
redecls()) {
1520 if (Redecl->isInExportDeclContext()) {
1527 SetUnknownShaderStageContext();
1535void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
1536 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
1537 DeclsToScan.push_back(FD);
1539 while (!DeclsToScan.empty()) {
1547 const unsigned ScannedStages = GetScannedStages(FD);
1548 if (WasAlreadyScannedInCurrentStage(ScannedStages))
1551 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
1553 AddToScannedFunctions(FD);
1558bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
1559 const AvailabilityAttr *AA) {
1564 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
1565 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
1568 llvm::Triple::EnvironmentType AttrEnv =
1569 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
1571 return CurrentEnv == AttrEnv;
1574const AvailabilityAttr *
1575DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *
D) {
1576 AvailabilityAttr
const *PartialMatch =
nullptr;
1580 for (
const auto *A :
D->
attrs()) {
1581 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
1582 StringRef AttrPlatform = Avail->getPlatform()->getName();
1583 StringRef TargetPlatform =
1587 if (AttrPlatform == TargetPlatform) {
1589 if (HasMatchingEnvironmentOrNone(Avail))
1591 PartialMatch = Avail;
1595 return PartialMatch;
1600void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *
D,
1601 const AvailabilityAttr *AA,
1620 if (ReportOnlyShaderStageIssues)
1626 if (InUnknownShaderStageContext())
1631 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
1632 VersionTuple Introduced = AA->getIntroduced();
1641 llvm::StringRef PlatformName(
1644 llvm::StringRef CurrentEnvStr =
1645 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
1647 llvm::StringRef AttrEnvStr =
1648 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
1649 bool UseEnvironment = !AttrEnvStr.empty();
1651 if (EnvironmentMatches) {
1653 <<
Range <<
D << PlatformName << Introduced.getAsString()
1654 << UseEnvironment << CurrentEnvStr;
1660 SemaRef.
Diag(
D->
getLocation(), diag::note_partial_availability_specified_here)
1661 <<
D << PlatformName << Introduced.getAsString()
1663 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
1675 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
1678 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
1691 for (
unsigned i = 1; i < TheCall->
getNumArgs(); ++i) {
1695 if (VecTyA ==
nullptr && VecTyB ==
nullptr)
1698 if (VecTyA && VecTyB) {
1699 bool retValue =
false;
1700 if (VecTyA->getElementType() != VecTyB->getElementType()) {
1704 diag::err_vec_builtin_incompatible_vector)
1709 if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
1713 S->
Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
1725 S->
Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1746 if (Check(PassedType)) {
1749 ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
1760 for (
unsigned i = 0; i < TheCall->
getNumArgs(); ++i) {
1771 return !PassedType->hasFloatingRepresentation();
1774 checkAllFloatTypes);
1790 unsigned ArgIndex) {
1791 auto *Arg = TheCall->
getArg(ArgIndex);
1796 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
1802 if (
const auto *VecTy = PassedType->getAs<
VectorType>())
1803 return VecTy->getElementType()->isDoubleType();
1811 return !PassedType->hasIntegerRepresentation() &&
1812 !PassedType->hasFloatingRepresentation();
1815 checkAllSignedTypes);
1820 return !PassedType->hasUnsignedIntegerRepresentation();
1823 checkAllUnsignedTypes);
1836 unsigned ArgIndex) {
1845 diag::err_typecheck_expect_scalar_or_vector)
1846 << ArgType << Scalar;
1853 unsigned ArgIndex) {
1859 (VTy && VTy->getElementType()->isScalarType()))) {
1861 diag::err_typecheck_expect_any_scalar_or_vector)
1874 diag::err_typecheck_call_different_arg_types)
1904 diag::err_typecheck_call_different_arg_types)
1915 diag::err_typecheck_vector_lengths_not_equal)
1934 diag::err_typecheck_expect_hlsl_resource)
1938 if (Check && Check(ResTy)) {
1940 diag::err_invalid_hlsl_resource_type)
1950 switch (BuiltinID) {
1951 case Builtin::BI__builtin_hlsl_resource_getpointer: {
1960 QualType ContainedTy = ResourceTy->getContainedType();
1967 case Builtin::BI__builtin_hlsl_all:
1968 case Builtin::BI__builtin_hlsl_any: {
1973 case Builtin::BI__builtin_hlsl_asdouble: {
1982 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
1993 case Builtin::BI__builtin_hlsl_cross: {
2001 int NumElementsArg1 =
2003 int NumElementsArg2 =
2006 if (NumElementsArg1 != 3) {
2007 int LessOrMore = NumElementsArg1 > 3 ? 1 : 0;
2009 diag::err_vector_incorrect_num_elements)
2010 << LessOrMore << 3 << NumElementsArg1 << 1;
2013 if (NumElementsArg2 != 3) {
2014 int LessOrMore = NumElementsArg2 > 3 ? 1 : 0;
2017 diag::err_vector_incorrect_num_elements)
2018 << LessOrMore << 3 << NumElementsArg2 << 1;
2028 case Builtin::BI__builtin_hlsl_dot: {
2039 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
2050 EltTy = VecTy->getElementType();
2052 VecTy->getVectorKind());
2064 case Builtin::BI__builtin_hlsl_select: {
2073 if (VTy && VTy->getElementType()->isBooleanType() &&
2078 case Builtin::BI__builtin_hlsl_elementwise_saturate:
2079 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
2086 case Builtin::BI__builtin_hlsl_elementwise_degrees:
2087 case Builtin::BI__builtin_hlsl_elementwise_radians:
2088 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
2089 case Builtin::BI__builtin_hlsl_elementwise_frac: {
2096 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
2104 case Builtin::BI__builtin_hlsl_lerp: {
2115 case Builtin::BI__builtin_hlsl_length: {
2126 RetTy = VTy->getElementType();
2133 case Builtin::BI__builtin_hlsl_mad: {
2144 case Builtin::BI__builtin_hlsl_normalize: {
2156 case Builtin::BI__builtin_hlsl_elementwise_sign: {
2164 case Builtin::BI__builtin_hlsl_step: {
2178 case Builtin::BI__builtin_elementwise_bitreverse: {
2183 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
2189 QualType ArgTyIndex = Index.get()->getType();
2192 diag::err_typecheck_convert_incompatible)
2206 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
2211 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
2227 case Builtin::BI__builtin_hlsl_elementwise_clip: {
2235 case Builtin::BI__builtin_elementwise_acos:
2236 case Builtin::BI__builtin_elementwise_asin:
2237 case Builtin::BI__builtin_elementwise_atan:
2238 case Builtin::BI__builtin_elementwise_atan2:
2239 case Builtin::BI__builtin_elementwise_ceil:
2240 case Builtin::BI__builtin_elementwise_cos:
2241 case Builtin::BI__builtin_elementwise_cosh:
2242 case Builtin::BI__builtin_elementwise_exp:
2243 case Builtin::BI__builtin_elementwise_exp2:
2244 case Builtin::BI__builtin_elementwise_floor:
2245 case Builtin::BI__builtin_elementwise_fmod:
2246 case Builtin::BI__builtin_elementwise_log:
2247 case Builtin::BI__builtin_elementwise_log2:
2248 case Builtin::BI__builtin_elementwise_log10:
2249 case Builtin::BI__builtin_elementwise_pow:
2250 case Builtin::BI__builtin_elementwise_roundeven:
2251 case Builtin::BI__builtin_elementwise_sin:
2252 case Builtin::BI__builtin_elementwise_sinh:
2253 case Builtin::BI__builtin_elementwise_sqrt:
2254 case Builtin::BI__builtin_elementwise_tan:
2255 case Builtin::BI__builtin_elementwise_tanh:
2256 case Builtin::BI__builtin_elementwise_trunc: {
2261 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
2263 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
2264 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
2272 std::optional<llvm::APSInt> Offset =
2274 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
2276 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
2289 WorkList.push_back(BaseTy);
2290 while (!WorkList.empty()) {
2292 T =
T.getCanonicalType().getUnqualifiedType();
2293 assert(!isa<MatrixType>(
T) &&
"Matrix types not yet supported in HLSL");
2294 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
2302 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
2303 List.insert(List.end(), ElementFields.begin(), ElementFields.end());
2308 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
2309 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
2312 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2324 for (
const auto *FD : RD->
fields())
2325 FieldTypes.push_back(FD->
getType());
2327 std::reverse(FieldTypes.begin(), FieldTypes.end());
2328 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2335 FieldTypes.push_back(
Base.getType());
2336 std::reverse(FieldTypes.begin(), FieldTypes.end());
2337 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2365 int ArraySize = VT->getNumElements();
2370 QualType ElTy = VT->getElementType();
2399 return llvm::equal(T1Types, T2Types,
2410 bool HadError =
false;
2412 for (
unsigned i = 0, e = New->
getNumParams(); i != e; ++i) {
2420 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
2421 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
2422 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
2423 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
2425 if (NSpellingIdx != OSpellingIdx) {
2427 diag::err_hlsl_param_qualifier_mismatch)
2428 << NDAttr << NewParam;
2438 assert(Param->
hasAttr<HLSLParamModifierAttr>() &&
2439 "We should not get here without a parameter modifier expression");
2440 const auto *
Attr = Param->
getAttr<HLSLParamModifierAttr>();
2447 << Arg << (IsInOut ? 1 : 0);
2460 << Arg << (IsInOut ? 1 : 0);
2478 auto *OpV =
new (Ctx)
2484 tok::equal, ArgOpV, OpV);
2500 "Pointer and reference types cannot be inout or out parameters");
2512 diag::err_typecheck_decl_incomplete_type)) {
2519 collectResourcesOnVarDecl(VD);
2522 processExplicitBindingsOnDecl(VD);
2528void SemaHLSL::collectResourcesOnVarDecl(
VarDecl *VD) {
2530 "expected global variable that contains HLSL resource");
2533 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
2534 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
2535 ? ResourceClass::CBuffer
2536 : ResourceClass::SRV);
2551 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
2556 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
2557 collectResourcesOnUserRecordDecl(VD, RT);
2563void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
2567 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
2572 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
2573 "never have an attribute created");
2575 if (RT == RegisterType::C) {
2576 if (
Bindings.hasBindingInfoForDecl(VD))
2578 diag::warn_hlsl_user_defined_type_missing_member)
2579 <<
static_cast<int>(RT);
2592 diag::warn_hlsl_user_defined_type_missing_member)
2593 <<
static_cast<int>(RT);
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
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 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 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 bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
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 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 bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall)
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 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
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....
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 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)
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 C++ struct/union/class.
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
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.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
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
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
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 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.
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.
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
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 isStructureType() const
bool isBooleanType() const
bool isIncompleteArrayType() const
bool isConstantArrayType() const
bool isArithmeticType() 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
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
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.
@ 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.