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 = 128;
178 unsigned FieldAlign = 32;
180 FieldAlign = CBufferAlign;
181 Size = llvm::alignTo(Size, FieldAlign);
185 if (
unsigned ElementCount = AT->getSize().getZExtValue()) {
186 unsigned ElementSize =
188 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
189 Size = AlignedElementSize * (ElementCount - 1) + ElementSize;
192 unsigned ElementCount = VT->getNumElements();
193 unsigned ElementSize =
195 Size = ElementSize * ElementCount;
203 auto *BufDecl = cast<HLSLBufferDecl>(Dcl);
204 BufDecl->setRBraceLoc(RBrace);
208 bool HasPackOffset =
false;
209 bool HasNonPackOffset =
false;
210 for (
auto *Field : BufDecl->decls()) {
211 VarDecl *Var = dyn_cast<VarDecl>(Field);
214 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
215 PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());
216 HasPackOffset =
true;
218 HasNonPackOffset =
true;
222 if (HasPackOffset && HasNonPackOffset)
223 Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);
229 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
230 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
231 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
232 return LHS.second->getOffset() < RHS.second->getOffset();
235 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
236 VarDecl *Var = PackOffsetVec[i].first;
237 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
240 unsigned End =
Begin + Size;
241 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffset() * 32;
242 if (End > NextBegin) {
243 VarDecl *NextVar = PackOffsetVec[i + 1].first;
255 int X,
int Y,
int Z) {
256 if (HLSLNumThreadsAttr *NT =
D->
getAttr<HLSLNumThreadsAttr>()) {
257 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
258 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
259 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
269 int Min,
int Max,
int Preferred,
270 int SpelledArgsCount) {
271 if (HLSLWaveSizeAttr *WS =
D->
getAttr<HLSLWaveSizeAttr>()) {
272 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
273 WS->getPreferred() != Preferred ||
274 WS->getSpelledArgsCount() != SpelledArgsCount) {
275 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
276 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
282 Result->setSpelledArgsCount(SpelledArgsCount);
288 llvm::Triple::EnvironmentType ShaderType) {
289 if (HLSLShaderAttr *NT =
D->
getAttr<HLSLShaderAttr>()) {
290 if (NT->getType() != ShaderType) {
291 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
292 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
296 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
299HLSLParamModifierAttr *
301 HLSLParamModifierAttr::Spelling Spelling) {
304 if (HLSLParamModifierAttr *PA =
D->
getAttr<HLSLParamModifierAttr>()) {
305 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
306 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
309 return HLSLParamModifierAttr::Create(
311 HLSLParamModifierAttr::Keyword_inout);
313 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
314 Diag(PA->getLocation(), diag::note_conflicting_attribute);
327 if (HLSLShaderAttr::isValidShaderType(
Env) &&
Env != llvm::Triple::Library) {
328 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
331 if (Shader->getType() !=
Env) {
332 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
344 case llvm::Triple::UnknownEnvironment:
345 case llvm::Triple::Library:
348 llvm_unreachable(
"Unhandled environment in triple");
354 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
355 assert(ShaderAttr &&
"Entry point has no shader attribute");
356 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
360 case llvm::Triple::Pixel:
361 case llvm::Triple::Vertex:
362 case llvm::Triple::Geometry:
363 case llvm::Triple::Hull:
364 case llvm::Triple::Domain:
365 case llvm::Triple::RayGeneration:
366 case llvm::Triple::Intersection:
367 case llvm::Triple::AnyHit:
368 case llvm::Triple::ClosestHit:
369 case llvm::Triple::Miss:
370 case llvm::Triple::Callable:
371 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
373 {llvm::Triple::Compute,
374 llvm::Triple::Amplification,
375 llvm::Triple::Mesh});
378 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
380 {llvm::Triple::Compute,
381 llvm::Triple::Amplification,
382 llvm::Triple::Mesh});
387 case llvm::Triple::Compute:
388 case llvm::Triple::Amplification:
389 case llvm::Triple::Mesh:
390 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
392 << llvm::Triple::getEnvironmentTypeName(ST);
395 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
396 if (Ver < VersionTuple(6, 6)) {
397 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
400 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
403 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
404 << WS << WS->getSpelledArgsCount() <<
"6.8";
410 llvm_unreachable(
"Unhandled environment in triple");
420 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
430 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
431 assert(ShaderAttr &&
"Entry point has no shader attribute");
432 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
434 switch (AnnotationAttr->
getKind()) {
435 case attr::HLSLSV_DispatchThreadID:
436 case attr::HLSLSV_GroupIndex:
437 case attr::HLSLSV_GroupThreadID:
438 case attr::HLSLSV_GroupID:
439 if (ST == llvm::Triple::Compute)
444 llvm_unreachable(
"Unknown HLSLAnnotationAttr");
449 const Attr *A, llvm::Triple::EnvironmentType Stage,
450 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
452 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
453 [](llvm::Triple::EnvironmentType ST) {
455 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
457 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
458 << A << llvm::Triple::getEnvironmentTypeName(Stage)
459 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
462template <CastKind Kind>
465 Ty = VTy->getElementType();
470template <CastKind Kind>
482 if (LHSFloat && RHSFloat) {
485 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
487 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
491 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
495 return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
497 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
510 if (LHSSigned == RHSSigned) {
511 if (IsCompAssign || IntOrder >= 0)
512 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
514 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
519 if (IntOrder != (LHSSigned ? 1 : -1)) {
520 if (IsCompAssign || RHSSigned)
521 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
522 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
528 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
529 if (IsCompAssign || LHSSigned)
530 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
531 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
542 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
545 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
546 QualType NewTy = Ctx.getExtVectorType(
548 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
550 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
556 return CK_FloatingCast;
558 return CK_IntegralCast;
560 return CK_IntegralToFloating;
562 return CK_FloatingToIntegral;
575 if (!LVecTy && IsCompAssign) {
579 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
586 unsigned EndSz = std::numeric_limits<unsigned>::max();
589 LSz = EndSz = LVecTy->getNumElements();
592 assert(EndSz != std::numeric_limits<unsigned>::max() &&
593 "one of the above should have had a value");
597 if (IsCompAssign && LSz != EndSz) {
599 diag::err_hlsl_vector_compound_assignment_truncation)
600 << LHSType << RHSType;
605 castVector<CK_HLSLVectorTruncation>(
SemaRef, RHS, RHSType, EndSz);
606 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
607 castVector<CK_HLSLVectorTruncation>(
SemaRef, LHS, LHSType, EndSz);
610 castVector<CK_VectorSplat>(
SemaRef, RHS, RHSType, EndSz);
611 if (!IsCompAssign && !LVecTy)
612 castVector<CK_VectorSplat>(
SemaRef, LHS, LHSType, EndSz);
615 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
616 return Ctx.getCommonSugaredType(LHSType, RHSType);
624 LElTy, RElTy, IsCompAssign);
627 "HLSL Vectors can only contain integer or floating point types");
629 LElTy, RElTy, IsCompAssign);
634 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
635 "Called with non-logical operator");
637 llvm::raw_svector_ostream OS(Buff);
639 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
640 OS << NewFnName <<
"(";
651 llvm::VersionTuple SMVersion =
653 uint32_t ZMax = 1024;
654 uint32_t ThreadMax = 1024;
655 if (SMVersion.getMajor() <= 4) {
658 }
else if (SMVersion.getMajor() == 5) {
668 diag::err_hlsl_numthreads_argument_oor)
677 diag::err_hlsl_numthreads_argument_oor)
686 diag::err_hlsl_numthreads_argument_oor)
691 if (
X * Y * Z > ThreadMax) {
692 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
709 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
717 if (SpelledArgsCount > 1 &&
721 uint32_t Preferred = 0;
722 if (SpelledArgsCount > 2 &&
726 if (SpelledArgsCount > 2) {
729 diag::err_attribute_power_of_two_in_range)
730 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
735 if (Preferred < Min || Preferred >
Max) {
737 diag::err_attribute_power_of_two_in_range)
738 << AL <<
Min <<
Max << Preferred;
741 }
else if (SpelledArgsCount > 1) {
744 diag::err_attribute_power_of_two_in_range)
745 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
749 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
752 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
757 diag::err_attribute_power_of_two_in_range)
758 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
763 HLSLWaveSizeAttr *NewAttr =
773 (VT && VT->getNumElements() > 3)) {
774 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
775 << AL <<
"uint/uint2/uint3";
783 auto *VD = cast<ValueDecl>(
D);
792 auto *VD = cast<ValueDecl>(
D);
801 auto *VD = cast<ValueDecl>(
D);
810 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
811 << AL <<
"shader constant in a constant buffer";
815 uint32_t SubComponent;
822 QualType T = cast<VarDecl>(
D)->getType().getCanonicalType();
830 if (IsAggregateTy || Size > 128) {
831 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
835 if ((Component * 32 + Size) > 128) {
836 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
841 EltTy = VT->getElementType();
843 if (Align > 32 && Component == 1) {
846 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
863 llvm::Triple::EnvironmentType ShaderType;
864 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
865 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
866 << AL << Str << ArgLoc;
880 assert(AttrList.size() &&
"expected list of resource attributes");
889 bool HasResourceClass =
false;
890 for (
const Attr *A : AttrList) {
893 LocEnd = A->getRange().getEnd();
894 switch (A->getKind()) {
895 case attr::HLSLResourceClass: {
896 ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();
897 if (HasResourceClass) {
899 ? diag::warn_duplicate_attribute_exact
900 : diag::warn_duplicate_attribute)
905 HasResourceClass =
true;
909 if (ResAttrs.
IsROV) {
910 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
913 ResAttrs.
IsROV =
true;
915 case attr::HLSLRawBuffer:
917 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
922 case attr::HLSLContainedType: {
923 const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
925 if (!ContainedTy.
isNull()) {
926 S.
Diag(A->getLocation(), ContainedTy == Ty
927 ? diag::warn_duplicate_attribute_exact
928 : diag::warn_duplicate_attribute)
937 llvm_unreachable(
"unhandled resource attribute type");
941 if (!HasResourceClass) {
942 S.
Diag(AttrList.back()->getRange().getEnd(),
943 diag::err_hlsl_missing_resource_class);
948 Wrapped, ContainedTy, ResAttrs);
950 if (LocInfo && ContainedTyInfo) {
963 if (!
T->isHLSLResourceType()) {
964 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
975 case ParsedAttr::AT_HLSLResourceClass: {
977 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
988 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(
Identifier, RC)) {
989 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
997 case ParsedAttr::AT_HLSLROV:
1001 case ParsedAttr::AT_HLSLRawBuffer:
1005 case ParsedAttr::AT_HLSLContainedType: {
1007 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1013 assert(TSI &&
"no type source info for attribute argument");
1015 diag::err_incomplete_type))
1022 llvm_unreachable(
"unhandled HLSL attribute");
1025 HLSLResourcesTypeAttrs.emplace_back(A);
1031 if (!HLSLResourcesTypeAttrs.size())
1037 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1039 cast<HLSLAttributedResourceType>(QT.
getTypePtr());
1045 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1047 HLSLResourcesTypeAttrs.clear();
1055 auto I = LocsForHLSLAttributedResources.find(RT);
1056 if (I != LocsForHLSLAttributedResources.end()) {
1057 LocInfo = I->second;
1058 LocsForHLSLAttributedResources.erase(I);
1067void SemaHLSL::collectResourcesOnUserRecordDecl(
const VarDecl *VD,
1076 "incomplete arrays inside user defined types are not supported");
1088 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1091 Bindings.addDeclBindingInfo(VD, RC);
1092 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
1098 collectResourcesOnUserRecordDecl(VD, RT);
1110 bool SpecifiedSpace) {
1111 int RegTypeNum =
static_cast<int>(RegType);
1114 if (
D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
1115 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1121 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
1122 : ResourceClass::SRV;
1132 assert(isa<VarDecl>(
D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
1139 if (RegType ==
getRegisterType(AttrResType->getAttrs().ResourceClass))
1154 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
1155 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1157 if (!DeclaredInCOrTBuffer &&
1160 if (RegType == RegisterType::CBuffer)
1161 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1162 else if (RegType != RegisterType::C)
1163 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1165 if (RegType == RegisterType::C)
1166 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
1168 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1178 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1186 bool RegisterTypesDetected[5] = {
false};
1187 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
1190 if (HLSLResourceBindingAttr *
attr =
1191 dyn_cast<HLSLResourceBindingAttr>(*it)) {
1194 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
1195 int otherRegTypeNum =
static_cast<int>(otherRegType);
1197 diag::err_hlsl_duplicate_register_annotation)
1201 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
1209 bool SpecifiedSpace) {
1212 assert(((isa<VarDecl>(
D) && !isa<HLSLBufferDecl>(
D)) ||
1213 (!isa<VarDecl>(
D) && isa<HLSLBufferDecl>(
D))) &&
1214 "expecting VarDecl or HLSLBufferDecl");
1225 if (isa<VarDecl>(TheDecl)) {
1227 cast<ValueDecl>(TheDecl)->getType(),
1228 diag::err_incomplete_type))
1231 StringRef Space =
"space0";
1232 StringRef Slot =
"";
1235 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1241 StringRef Str =
Loc->Ident->getName();
1245 bool SpecifiedSpace =
false;
1247 SpecifiedSpace =
true;
1250 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
1256 Space =
Loc->Ident->getName();
1257 SpaceArgLoc =
Loc->Loc;
1263 unsigned SlotNum = 0;
1264 unsigned SpaceNum = 0;
1267 if (!Slot.empty()) {
1269 Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
1272 if (RegType == RegisterType::I) {
1273 Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);
1277 StringRef SlotNumStr = Slot.substr(1);
1278 if (SlotNumStr.getAsInteger(10, SlotNum)) {
1279 Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);
1284 if (!Space.starts_with(
"space")) {
1285 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1288 StringRef SpaceNumStr = Space.substr(5);
1289 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
1290 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1298 HLSLResourceBindingAttr *NewAttr =
1299 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
1301 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
1356 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
1360 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
1361 unsigned CurrentShaderStageBit;
1366 bool ReportOnlyShaderStageIssues;
1369 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
1370 static_assert(
sizeof(
unsigned) >= 4);
1371 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
1372 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
1373 "ShaderType is too big for this bitmap");
1376 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
1377 CurrentShaderEnvironment = ShaderType;
1378 CurrentShaderStageBit = (1 << bitmapIndex);
1381 void SetUnknownShaderStageContext() {
1382 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
1383 CurrentShaderStageBit = (1 << 31);
1386 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
1387 return CurrentShaderEnvironment;
1390 bool InUnknownShaderStageContext()
const {
1391 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
1396 unsigned &ScannedStages = ScannedDecls[FD];
1397 ScannedStages |= CurrentShaderStageBit;
1400 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
1402 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
1403 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
1406 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
1407 return ScannerStages & CurrentShaderStageBit;
1410 static bool NeverBeenScanned(
unsigned ScannedStages) {
1411 return ScannedStages == 0;
1416 void CheckDeclAvailability(
NamedDecl *
D,
const AvailabilityAttr *AA,
1418 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *
D);
1419 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
1422 DiagnoseHLSLAvailability(
Sema &SemaRef)
1424 CurrentShaderEnvironment(
llvm::Triple::UnknownEnvironment),
1425 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
1431 bool VisitDeclRefExpr(
DeclRefExpr *DRE)
override {
1434 HandleFunctionOrMethodRef(FD, DRE);
1438 bool VisitMemberExpr(
MemberExpr *ME)
override {
1441 HandleFunctionOrMethodRef(FD, ME);
1446void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
1448 assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
1449 "expected DeclRefExpr or MemberExpr");
1453 if (FD->
hasBody(FDWithBody)) {
1454 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
1455 DeclsToScan.push_back(FDWithBody);
1460 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
1462 CheckDeclAvailability(
1466void DiagnoseHLSLAvailability::RunOnTranslationUnit(
1475 DeclContextsToScan.push_back(TU);
1477 while (!DeclContextsToScan.empty()) {
1478 const DeclContext *DC = DeclContextsToScan.pop_back_val();
1479 for (
auto &
D : DC->
decls()) {
1486 if (llvm::dyn_cast<NamespaceDecl>(
D) || llvm::dyn_cast<ExportDecl>(
D)) {
1487 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(
D));
1497 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
1498 SetShaderStageContext(ShaderAttr->getType());
1507 for (
const auto *Redecl : FD->
redecls()) {
1508 if (Redecl->isInExportDeclContext()) {
1515 SetUnknownShaderStageContext();
1523void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
1524 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
1525 DeclsToScan.push_back(FD);
1527 while (!DeclsToScan.empty()) {
1535 const unsigned ScannedStages = GetScannedStages(FD);
1536 if (WasAlreadyScannedInCurrentStage(ScannedStages))
1539 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
1541 AddToScannedFunctions(FD);
1546bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
1547 const AvailabilityAttr *AA) {
1552 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
1553 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
1556 llvm::Triple::EnvironmentType AttrEnv =
1557 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
1559 return CurrentEnv == AttrEnv;
1562const AvailabilityAttr *
1563DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *
D) {
1564 AvailabilityAttr
const *PartialMatch =
nullptr;
1568 for (
const auto *A :
D->
attrs()) {
1569 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
1570 StringRef AttrPlatform = Avail->getPlatform()->getName();
1571 StringRef TargetPlatform =
1575 if (AttrPlatform == TargetPlatform) {
1577 if (HasMatchingEnvironmentOrNone(Avail))
1579 PartialMatch = Avail;
1583 return PartialMatch;
1588void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *
D,
1589 const AvailabilityAttr *AA,
1608 if (ReportOnlyShaderStageIssues)
1614 if (InUnknownShaderStageContext())
1619 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
1620 VersionTuple Introduced = AA->getIntroduced();
1629 llvm::StringRef PlatformName(
1632 llvm::StringRef CurrentEnvStr =
1633 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
1635 llvm::StringRef AttrEnvStr =
1636 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
1637 bool UseEnvironment = !AttrEnvStr.empty();
1639 if (EnvironmentMatches) {
1641 <<
Range <<
D << PlatformName << Introduced.getAsString()
1642 << UseEnvironment << CurrentEnvStr;
1648 SemaRef.
Diag(
D->
getLocation(), diag::note_partial_availability_specified_here)
1649 <<
D << PlatformName << Introduced.getAsString()
1651 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
1663 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
1666 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
1679 for (
unsigned i = 1; i < TheCall->
getNumArgs(); ++i) {
1683 if (VecTyA ==
nullptr && VecTyB ==
nullptr)
1686 if (VecTyA && VecTyB) {
1687 bool retValue =
false;
1688 if (VecTyA->getElementType() != VecTyB->getElementType()) {
1692 diag::err_vec_builtin_incompatible_vector)
1697 if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
1701 S->
Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
1713 S->
Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1734 if (Check(PassedType)) {
1737 ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
1748 for (
unsigned i = 0; i < TheCall->
getNumArgs(); ++i) {
1759 return !PassedType->hasFloatingRepresentation();
1762 checkAllFloatTypes);
1778 unsigned ArgIndex) {
1779 auto *Arg = TheCall->
getArg(ArgIndex);
1784 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
1790 if (
const auto *VecTy = PassedType->getAs<
VectorType>())
1791 return VecTy->getElementType()->isDoubleType();
1799 return !PassedType->hasIntegerRepresentation() &&
1800 !PassedType->hasFloatingRepresentation();
1803 checkAllSignedTypes);
1808 return !PassedType->hasUnsignedIntegerRepresentation();
1811 checkAllUnsignedTypes);
1824 unsigned ArgIndex) {
1833 diag::err_typecheck_expect_scalar_or_vector)
1834 << ArgType << Scalar;
1841 unsigned ArgIndex) {
1847 (VTy && VTy->getElementType()->isScalarType()))) {
1849 diag::err_typecheck_expect_any_scalar_or_vector)
1862 diag::err_typecheck_call_different_arg_types)
1892 diag::err_typecheck_call_different_arg_types)
1903 diag::err_typecheck_vector_lengths_not_equal)
1922 diag::err_typecheck_expect_hlsl_resource)
1926 if (Check && Check(ResTy)) {
1928 diag::err_invalid_hlsl_resource_type)
1938 switch (BuiltinID) {
1939 case Builtin::BI__builtin_hlsl_resource_getpointer: {
1948 QualType ContainedTy = ResourceTy->getContainedType();
1955 case Builtin::BI__builtin_hlsl_all:
1956 case Builtin::BI__builtin_hlsl_any: {
1961 case Builtin::BI__builtin_hlsl_asdouble: {
1970 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
1981 case Builtin::BI__builtin_hlsl_cross: {
1989 int NumElementsArg1 =
1991 int NumElementsArg2 =
1994 if (NumElementsArg1 != 3) {
1995 int LessOrMore = NumElementsArg1 > 3 ? 1 : 0;
1997 diag::err_vector_incorrect_num_elements)
1998 << LessOrMore << 3 << NumElementsArg1 << 1;
2001 if (NumElementsArg2 != 3) {
2002 int LessOrMore = NumElementsArg2 > 3 ? 1 : 0;
2005 diag::err_vector_incorrect_num_elements)
2006 << LessOrMore << 3 << NumElementsArg2 << 1;
2016 case Builtin::BI__builtin_hlsl_dot: {
2027 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
2038 EltTy = VecTy->getElementType();
2040 VecTy->getVectorKind());
2052 case Builtin::BI__builtin_hlsl_select: {
2061 if (VTy && VTy->getElementType()->isBooleanType() &&
2066 case Builtin::BI__builtin_hlsl_elementwise_saturate:
2067 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
2074 case Builtin::BI__builtin_hlsl_elementwise_degrees:
2075 case Builtin::BI__builtin_hlsl_elementwise_radians:
2076 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
2077 case Builtin::BI__builtin_hlsl_elementwise_frac: {
2084 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
2092 case Builtin::BI__builtin_hlsl_lerp: {
2103 case Builtin::BI__builtin_hlsl_length: {
2114 RetTy = VTy->getElementType();
2121 case Builtin::BI__builtin_hlsl_mad: {
2132 case Builtin::BI__builtin_hlsl_normalize: {
2144 case Builtin::BI__builtin_hlsl_elementwise_sign: {
2152 case Builtin::BI__builtin_hlsl_step: {
2166 case Builtin::BI__builtin_elementwise_bitreverse: {
2171 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
2177 QualType ArgTyIndex = Index.get()->getType();
2180 diag::err_typecheck_convert_incompatible)
2194 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
2199 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
2215 case Builtin::BI__builtin_hlsl_elementwise_clip: {
2223 case Builtin::BI__builtin_elementwise_acos:
2224 case Builtin::BI__builtin_elementwise_asin:
2225 case Builtin::BI__builtin_elementwise_atan:
2226 case Builtin::BI__builtin_elementwise_atan2:
2227 case Builtin::BI__builtin_elementwise_ceil:
2228 case Builtin::BI__builtin_elementwise_cos:
2229 case Builtin::BI__builtin_elementwise_cosh:
2230 case Builtin::BI__builtin_elementwise_exp:
2231 case Builtin::BI__builtin_elementwise_exp2:
2232 case Builtin::BI__builtin_elementwise_floor:
2233 case Builtin::BI__builtin_elementwise_fmod:
2234 case Builtin::BI__builtin_elementwise_log:
2235 case Builtin::BI__builtin_elementwise_log2:
2236 case Builtin::BI__builtin_elementwise_log10:
2237 case Builtin::BI__builtin_elementwise_pow:
2238 case Builtin::BI__builtin_elementwise_roundeven:
2239 case Builtin::BI__builtin_elementwise_sin:
2240 case Builtin::BI__builtin_elementwise_sinh:
2241 case Builtin::BI__builtin_elementwise_sqrt:
2242 case Builtin::BI__builtin_elementwise_tan:
2243 case Builtin::BI__builtin_elementwise_tanh:
2244 case Builtin::BI__builtin_elementwise_trunc: {
2249 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
2251 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
2252 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
2260 std::optional<llvm::APSInt> Offset =
2262 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
2264 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
2277 WorkList.push_back(BaseTy);
2278 while (!WorkList.empty()) {
2280 T =
T.getCanonicalType().getUnqualifiedType();
2281 assert(!isa<MatrixType>(
T) &&
"Matrix types not yet supported in HLSL");
2282 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
2290 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
2291 List.insert(List.end(), ElementFields.begin(), ElementFields.end());
2296 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
2297 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
2300 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2312 for (
const auto *FD : RD->
fields())
2313 FieldTypes.push_back(FD->
getType());
2315 std::reverse(FieldTypes.begin(), FieldTypes.end());
2316 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2323 FieldTypes.push_back(
Base.getType());
2324 std::reverse(FieldTypes.begin(), FieldTypes.end());
2325 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2353 int ArraySize = VT->getNumElements();
2358 QualType ElTy = VT->getElementType();
2387 return llvm::equal(T1Types, T2Types,
2398 bool HadError =
false;
2400 for (
unsigned i = 0, e = New->
getNumParams(); i != e; ++i) {
2408 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
2409 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
2410 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
2411 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
2413 if (NSpellingIdx != OSpellingIdx) {
2415 diag::err_hlsl_param_qualifier_mismatch)
2416 << NDAttr << NewParam;
2426 assert(Param->
hasAttr<HLSLParamModifierAttr>() &&
2427 "We should not get here without a parameter modifier expression");
2428 const auto *
Attr = Param->
getAttr<HLSLParamModifierAttr>();
2435 << Arg << (IsInOut ? 1 : 0);
2448 << Arg << (IsInOut ? 1 : 0);
2466 auto *OpV =
new (Ctx)
2472 tok::equal, ArgOpV, OpV);
2488 "Pointer and reference types cannot be inout or out parameters");
2500 diag::err_typecheck_decl_incomplete_type)) {
2507 collectResourcesOnVarDecl(VD);
2510 processExplicitBindingsOnDecl(VD);
2516void SemaHLSL::collectResourcesOnVarDecl(
VarDecl *VD) {
2518 "expected global variable that contains HLSL resource");
2521 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
2522 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
2523 ? ResourceClass::CBuffer
2524 : ResourceClass::SRV);
2539 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
2544 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
2545 collectResourcesOnUserRecordDecl(VD, RT);
2551void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
2555 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
2560 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
2561 "never have an attribute created");
2563 if (RT == RegisterType::C) {
2564 if (
Bindings.hasBindingInfoForDecl(VD))
2566 diag::warn_hlsl_user_defined_type_missing_member)
2567 <<
static_cast<int>(RT);
2580 diag::warn_hlsl_user_defined_type_missing_member)
2581 <<
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)
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.