15#include "clang/AST/Attrs.inc"
38#include "llvm/ADT/ArrayRef.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/SmallVector.h"
41#include "llvm/ADT/StringExtras.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ADT/Twine.h"
44#include "llvm/Frontend/HLSL/HLSLBinding.h"
45#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
46#include "llvm/Support/Casting.h"
47#include "llvm/Support/DXILABI.h"
48#include "llvm/Support/ErrorHandling.h"
49#include "llvm/Support/FormatVariadic.h"
50#include "llvm/TargetParser/Triple.h"
65 case ResourceClass::SRV:
66 return RegisterType::SRV;
67 case ResourceClass::UAV:
68 return RegisterType::UAV;
69 case ResourceClass::CBuffer:
70 return RegisterType::CBuffer;
71 case ResourceClass::Sampler:
72 return RegisterType::Sampler;
74 llvm_unreachable(
"unexpected ResourceClass value");
84 assert(RT !=
nullptr);
88 *RT = RegisterType::SRV;
92 *RT = RegisterType::UAV;
96 *RT = RegisterType::CBuffer;
100 *RT = RegisterType::Sampler;
104 *RT = RegisterType::C;
108 *RT = RegisterType::I;
117 case RegisterType::SRV:
118 return ResourceClass::SRV;
119 case RegisterType::UAV:
120 return ResourceClass::UAV;
121 case RegisterType::CBuffer:
122 return ResourceClass::CBuffer;
123 case RegisterType::Sampler:
124 return ResourceClass::Sampler;
125 case RegisterType::C:
126 case RegisterType::I:
130 llvm_unreachable(
"unexpected RegisterType value");
134 const auto *BT = dyn_cast<BuiltinType>(
Type);
138 return Builtin::BI__builtin_get_spirv_spec_constant_int;
141 switch (BT->getKind()) {
142 case BuiltinType::Bool:
143 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
144 case BuiltinType::Short:
145 return Builtin::BI__builtin_get_spirv_spec_constant_short;
146 case BuiltinType::Int:
147 return Builtin::BI__builtin_get_spirv_spec_constant_int;
148 case BuiltinType::LongLong:
149 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
150 case BuiltinType::UShort:
151 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
152 case BuiltinType::UInt:
153 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
154 case BuiltinType::ULongLong:
155 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
156 case BuiltinType::Half:
157 return Builtin::BI__builtin_get_spirv_spec_constant_half;
158 case BuiltinType::Float:
159 return Builtin::BI__builtin_get_spirv_spec_constant_float;
160 case BuiltinType::Double:
161 return Builtin::BI__builtin_get_spirv_spec_constant_double;
168 ResourceClass ResClass) {
170 "DeclBindingInfo already added");
176 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
177 return &BindingsList.emplace_back(VD, ResClass);
181 ResourceClass ResClass) {
182 auto Entry = DeclToBindingListIndex.find(VD);
183 if (Entry != DeclToBindingListIndex.end()) {
184 for (
unsigned Index = Entry->getSecond();
185 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
187 if (BindingsList[Index].ResClass == ResClass)
188 return &BindingsList[Index];
195 return DeclToBindingListIndex.contains(VD);
207 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
210 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
211 : llvm::hlsl::ResourceClass::SRV;
223 if (
T->isArrayType() ||
T->isStructureType())
230 assert(Context.getTypeSize(
T) <= 64 &&
231 "Scalar bit widths larger than 64 not supported");
234 return Context.getTypeSize(
T) / 8;
241 constexpr unsigned CBufferAlign = 16;
242 if (
const auto *RD =
T->getAsRecordDecl()) {
244 for (
const FieldDecl *Field : RD->fields()) {
251 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
252 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
253 FieldAlign = CBufferAlign;
256 Size = llvm::alignTo(Size, FieldAlign);
263 unsigned ElementCount = AT->getSize().getZExtValue();
264 if (ElementCount == 0)
267 unsigned ElementSize =
269 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
270 return AlignedElementSize * (ElementCount - 1) + ElementSize;
274 unsigned ElementCount = VT->getNumElements();
275 unsigned ElementSize =
277 return ElementSize * ElementCount;
280 return Context.getTypeSize(
T) / 8;
291 bool HasPackOffset =
false;
292 bool HasNonPackOffset =
false;
294 VarDecl *Var = dyn_cast<VarDecl>(Field);
297 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
298 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
299 HasPackOffset =
true;
301 HasNonPackOffset =
true;
308 if (HasNonPackOffset)
315 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
316 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
317 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
318 return LHS.second->getOffsetInBytes() <
319 RHS.second->getOffsetInBytes();
321 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
322 VarDecl *Var = PackOffsetVec[i].first;
323 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
325 unsigned Begin =
Attr->getOffsetInBytes();
326 unsigned End = Begin + Size;
327 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
328 if (End > NextBegin) {
329 VarDecl *NextVar = PackOffsetVec[i + 1].first;
341 CAT = dyn_cast<ConstantArrayType>(
343 return CAT !=
nullptr;
351static const HLSLAttributedResourceType *
354 "expected array of resource records");
356 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
358 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
370 return RD->isEmpty();
399 Base.getType()->castAsCXXRecordDecl()))
410 assert(RD ==
nullptr &&
411 "there should be at most 1 record by a given name in a scope");
428 Name.append(NameBaseII->
getName());
435 size_t NameLength = Name.size();
444 Name.append(llvm::Twine(suffix).str());
445 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
452 Name.truncate(NameLength);
493 "struct is already HLSL buffer compatible");
507 LS->
addAttr(PackedAttr::CreateImplicit(AST));
511 if (
unsigned NumBases = StructDecl->
getNumBases()) {
512 assert(NumBases == 1 &&
"HLSL supports only one base type");
562 LS->
addAttr(PackedAttr::CreateImplicit(AST));
567 VarDecl *VD = dyn_cast<VarDecl>(D);
587 uint32_t ImplicitBindingOrderID) {
589 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
590 Attr->setBinding(RT, std::nullopt, 0);
591 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
598 BufDecl->setRBraceLoc(RBrace);
610 uint32_t OrderID = getNextImplicitBindingOrderID();
615 BufDecl->isCBuffer() ? RegisterType::CBuffer
625 int X,
int Y,
int Z) {
626 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
627 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
628 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
629 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
639 int Min,
int Max,
int Preferred,
640 int SpelledArgsCount) {
641 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
642 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
643 WS->getPreferred() != Preferred ||
644 WS->getSpelledArgsCount() != SpelledArgsCount) {
645 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
646 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
652 Result->setSpelledArgsCount(SpelledArgsCount);
656HLSLVkConstantIdAttr *
662 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
670 Diag(VD->getLocation(), diag::err_specialization_const);
674 if (!VD->getType().isConstQualified()) {
675 Diag(VD->getLocation(), diag::err_specialization_const);
679 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
680 if (CI->getId() != Id) {
681 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
682 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
687 HLSLVkConstantIdAttr *
Result =
694 llvm::Triple::EnvironmentType ShaderType) {
695 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
696 if (NT->getType() != ShaderType) {
697 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
698 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
702 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
705HLSLParamModifierAttr *
707 HLSLParamModifierAttr::Spelling Spelling) {
710 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
711 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
712 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
713 D->
dropAttr<HLSLParamModifierAttr>();
715 return HLSLParamModifierAttr::Create(
717 HLSLParamModifierAttr::Keyword_inout);
719 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
720 Diag(PA->getLocation(), diag::note_conflicting_attribute);
746 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
747 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
750 if (Shader->getType() != Env) {
751 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
763 case llvm::Triple::UnknownEnvironment:
764 case llvm::Triple::Library:
766 case llvm::Triple::RootSignature:
767 llvm_unreachable(
"rootsig environment has no functions");
769 llvm_unreachable(
"Unhandled environment in triple");
774bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
777 SemanticInfo &ActiveSemantic,
778 llvm::StringSet<> &UsedSemantics,
780 if (ActiveSemantic.Semantic ==
nullptr) {
781 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
782 if (ActiveSemantic.Semantic)
783 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
786 if (!ActiveSemantic.Semantic) {
792 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
793 ActiveSemantic.Semantic->getAttrName()->getName(),
794 ActiveSemantic.Index.value_or(0));
798 checkSemanticAnnotation(FD, D, A, IsInput);
799 OutputDecl->addAttr(A);
801 unsigned Location = ActiveSemantic.Index.value_or(0);
803 const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->
getType());
804 unsigned ElementCount = AT ? AT->getZExtSize() : 1;
805 ActiveSemantic.Index = Location + ElementCount;
807 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
808 for (
unsigned I = 0; I < ElementCount; ++I) {
809 Twine VariableName = BaseName.concat(Twine(Location + I));
811 auto [_, Inserted] = UsedSemantics.insert(VariableName.str());
813 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
814 << VariableName.str();
825 SemanticInfo &ActiveSemantic,
826 llvm::StringSet<> &UsedSemantics,
828 if (ActiveSemantic.Semantic ==
nullptr) {
829 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
830 if (ActiveSemantic.Semantic)
831 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
837 const RecordType *RT = dyn_cast<RecordType>(
T);
839 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
840 UsedSemantics, IsInput);
842 const RecordDecl *RD = RT->getDecl();
843 for (FieldDecl *Field : RD->
fields()) {
844 SemanticInfo Info = ActiveSemantic;
845 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, UsedSemantics,
847 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
850 if (ActiveSemantic.Semantic)
851 ActiveSemantic = Info;
858 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
859 assert(ShaderAttr &&
"Entry point has no shader attribute");
860 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
864 case llvm::Triple::Pixel:
865 case llvm::Triple::Vertex:
866 case llvm::Triple::Geometry:
867 case llvm::Triple::Hull:
868 case llvm::Triple::Domain:
869 case llvm::Triple::RayGeneration:
870 case llvm::Triple::Intersection:
871 case llvm::Triple::AnyHit:
872 case llvm::Triple::ClosestHit:
873 case llvm::Triple::Miss:
874 case llvm::Triple::Callable:
875 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
877 {llvm::Triple::Compute,
878 llvm::Triple::Amplification,
879 llvm::Triple::Mesh});
882 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
884 {llvm::Triple::Compute,
885 llvm::Triple::Amplification,
886 llvm::Triple::Mesh});
891 case llvm::Triple::Compute:
892 case llvm::Triple::Amplification:
893 case llvm::Triple::Mesh:
894 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
896 << llvm::Triple::getEnvironmentTypeName(ST);
899 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
900 if (Ver < VersionTuple(6, 6)) {
901 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
904 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
907 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
908 << WS << WS->getSpelledArgsCount() <<
"6.8";
913 case llvm::Triple::RootSignature:
914 llvm_unreachable(
"rootsig environment has no function entry point");
916 llvm_unreachable(
"Unhandled environment in triple");
919 llvm::StringSet<> ActiveInputSemantics;
921 SemanticInfo ActiveSemantic;
922 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
923 if (ActiveSemantic.Semantic)
924 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
927 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic,
928 ActiveInputSemantics,
true)) {
929 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
934 SemanticInfo ActiveSemantic;
935 llvm::StringSet<> ActiveOutputSemantics;
936 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
937 if (ActiveSemantic.Semantic)
938 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
940 determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics,
944void SemaHLSL::checkSemanticAnnotation(
946 const HLSLAppliedSemanticAttr *SemanticAttr,
bool IsInput) {
947 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
948 assert(ShaderAttr &&
"Entry point has no shader attribute");
949 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
951 auto SemanticName = SemanticAttr->getSemanticName().upper();
952 if (SemanticName ==
"SV_DISPATCHTHREADID" ||
953 SemanticName ==
"SV_GROUPINDEX" || SemanticName ==
"SV_GROUPTHREADID" ||
954 SemanticName ==
"SV_GROUPID") {
956 if (ST != llvm::Triple::Compute)
959 if (SemanticAttr->getSemanticIndex() != 0) {
960 std::string PrettyName =
961 "'" + SemanticAttr->getSemanticName().str() +
"'";
962 Diag(SemanticAttr->getLoc(),
963 diag::err_hlsl_semantic_indexing_not_supported)
969 if (SemanticName ==
"SV_POSITION") {
972 if (ST == llvm::Triple::Vertex || (ST == llvm::Triple::Pixel && IsInput))
975 {llvm::Triple::Pixel, llvm::Triple::Vertex});
981 if (SemanticAttr->getAttrName()->getName().starts_with_insensitive(
"SV_"))
982 llvm_unreachable(
"Unknown SemanticAttr");
986 const Attr *A, llvm::Triple::EnvironmentType Stage,
987 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
989 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
990 [](llvm::Triple::EnvironmentType ST) {
992 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
994 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
995 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
996 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
999template <CastKind Kind>
1002 Ty = VTy->getElementType();
1007template <CastKind Kind>
1019 if (LHSFloat && RHSFloat) {
1047 if (LHSSigned == RHSSigned) {
1048 if (IsCompAssign || IntOrder >= 0)
1056 if (IntOrder != (LHSSigned ? 1 : -1)) {
1057 if (IsCompAssign || RHSSigned)
1065 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1066 if (IsCompAssign || LHSSigned)
1082 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1083 QualType NewTy = Ctx.getExtVectorType(
1093 return CK_FloatingCast;
1095 return CK_IntegralCast;
1097 return CK_IntegralToFloating;
1099 return CK_FloatingToIntegral;
1105 bool IsCompAssign) {
1112 if (!LVecTy && IsCompAssign) {
1114 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1116 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1118 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1123 unsigned EndSz = std::numeric_limits<unsigned>::max();
1126 LSz = EndSz = LVecTy->getNumElements();
1129 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1130 "one of the above should have had a value");
1134 if (IsCompAssign && LSz != EndSz) {
1136 diag::err_hlsl_vector_compound_assignment_truncation)
1137 << LHSType << RHSType;
1143 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1148 if (!IsCompAssign && !LVecTy)
1152 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1153 return Ctx.getCommonSugaredType(LHSType, RHSType);
1161 LElTy, RElTy, IsCompAssign);
1164 "HLSL Vectors can only contain integer or floating point types");
1166 LElTy, RElTy, IsCompAssign);
1171 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1172 "Called with non-logical operator");
1174 llvm::raw_svector_ostream OS(Buff);
1176 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1177 OS << NewFnName <<
"(";
1187std::pair<IdentifierInfo *, bool>
1190 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1197 return {DeclIdent,
Found};
1208 for (
auto &RootSigElement : RootElements)
1209 Elements.push_back(RootSigElement.getElement());
1213 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1215 SignatureDecl->setImplicit();
1221 if (RootSigOverrideIdent) {
1224 if (
SemaRef.LookupQualifiedName(R, DC))
1225 return dyn_cast<HLSLRootSignatureDecl>(R.
getFoundDecl());
1233struct PerVisibilityBindingChecker {
1236 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1240 llvm::dxbc::ShaderVisibility Vis;
1245 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1247 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1248 llvm::dxil::ResourceClass RC, uint32_t Space,
1249 uint32_t LowerBound, uint32_t UpperBound,
1250 const hlsl::RootSignatureElement *Elem) {
1252 assert(BuilderIndex < Builders.size() &&
1253 "Not enough builders for visibility type");
1254 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1255 static_cast<const void *
>(Elem));
1257 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1258 "'All' visibility must come first");
1259 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1260 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1261 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1262 static_cast<const void *
>(Elem));
1264 ElemInfoMap.push_back({Elem,
Visibility,
false});
1267 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1268 auto It = llvm::lower_bound(
1270 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1271 assert(It->Elem == Elem &&
"Element not in map");
1275 bool checkOverlap() {
1276 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1277 return LHS.Elem < RHS.Elem;
1280 bool HadOverlap =
false;
1282 using llvm::hlsl::BindingInfoBuilder;
1283 auto ReportOverlap = [
this,
1284 &HadOverlap](
const BindingInfoBuilder &Builder,
1285 const llvm::hlsl::Binding &Reported) {
1289 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1290 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1291 const auto *PrevElem =
1292 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1294 ElemInfo &Info =
getInfo(Elem);
1299 Info.Diagnosed =
true;
1301 ElemInfo &PrevInfo =
getInfo(PrevElem);
1302 llvm::dxbc::ShaderVisibility CommonVis =
1303 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1306 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1307 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1308 << Reported.isUnbounded() << Reported.UpperBound
1313 this->S->
Diag(PrevElem->getLocation(),
1314 diag::note_hlsl_resource_range_here);
1317 for (BindingInfoBuilder &Builder : Builders)
1318 Builder.calculateBindingInfo(ReportOverlap);
1342 if (
const auto *ResTy =
1343 SecondField->
getType()->
getAs<HLSLAttributedResourceType>()) {
1344 return ResTy->getAttrs().IsCounter;
1352 bool HadError =
false;
1353 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1354 uint32_t UpperBound) {
1356 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1357 << LowerBound << UpperBound;
1364 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1365 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1366 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1369 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1370 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1371 ReportError(Loc, 0, 0xfffffffe);
1374 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1375 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1376 ReportError(Loc, 0, 0xffffffef);
1379 const uint32_t Version =
1380 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1381 const uint32_t VersionEnum = Version - 1;
1382 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1384 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1391 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1392 if (
const auto *Descriptor =
1393 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1394 VerifyRegister(Loc, Descriptor->Reg.Number);
1395 VerifySpace(Loc, Descriptor->Space);
1397 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1399 ReportFlagError(Loc);
1400 }
else if (
const auto *Constants =
1401 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1402 VerifyRegister(Loc, Constants->Reg.Number);
1403 VerifySpace(Loc, Constants->Space);
1404 }
else if (
const auto *Sampler =
1405 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1406 VerifyRegister(Loc, Sampler->Reg.Number);
1407 VerifySpace(Loc, Sampler->Space);
1410 "By construction, parseFloatParam can't produce a NaN from a "
1411 "float_literal token");
1413 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1414 ReportError(Loc, 0, 16);
1415 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1416 ReportFloatError(Loc, -16.f, 15.99f);
1417 }
else if (
const auto *Clause =
1418 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1420 VerifyRegister(Loc, Clause->Reg.Number);
1421 VerifySpace(Loc, Clause->Space);
1423 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1427 ReportError(Loc, 1, 0xfffffffe);
1430 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1432 ReportFlagError(Loc);
1436 PerVisibilityBindingChecker BindingChecker(
this);
1437 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1442 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1443 if (
const auto *Descriptor =
1444 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1445 uint32_t LowerBound(Descriptor->Reg.Number);
1446 uint32_t UpperBound(LowerBound);
1448 BindingChecker.trackBinding(
1449 Descriptor->Visibility,
1450 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1451 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1452 }
else if (
const auto *Constants =
1453 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1454 uint32_t LowerBound(Constants->Reg.Number);
1455 uint32_t UpperBound(LowerBound);
1457 BindingChecker.trackBinding(
1458 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1459 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1460 }
else if (
const auto *Sampler =
1461 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1462 uint32_t LowerBound(Sampler->Reg.Number);
1463 uint32_t UpperBound(LowerBound);
1465 BindingChecker.trackBinding(
1466 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1467 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1468 }
else if (
const auto *Clause =
1469 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1472 UnboundClauses.emplace_back(Clause, &RootSigElem);
1473 }
else if (
const auto *Table =
1474 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1475 assert(UnboundClauses.size() == Table->NumClauses &&
1476 "Number of unbound elements must match the number of clauses");
1477 bool HasAnySampler =
false;
1478 bool HasAnyNonSampler =
false;
1479 uint64_t Offset = 0;
1480 bool IsPrevUnbound =
false;
1481 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1483 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1484 HasAnySampler =
true;
1486 HasAnyNonSampler =
true;
1488 if (HasAnySampler && HasAnyNonSampler)
1489 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1494 if (Clause->NumDescriptors == 0)
1498 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1500 Offset = Clause->Offset;
1502 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1503 Offset, Clause->NumDescriptors);
1505 if (IsPrevUnbound && IsAppending)
1506 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1507 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1508 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1511 Offset = RangeBound + 1;
1512 IsPrevUnbound = Clause->NumDescriptors ==
1513 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1516 uint32_t LowerBound(Clause->Reg.Number);
1517 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1518 LowerBound, Clause->NumDescriptors);
1520 BindingChecker.trackBinding(
1522 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
1523 LowerBound, UpperBound, ClauseElem);
1525 UnboundClauses.clear();
1529 return BindingChecker.checkOverlap();
1534 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1539 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
1540 if (RS->getSignatureIdent() != Ident) {
1541 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1545 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1551 if (
auto *SignatureDecl =
1559 llvm::VersionTuple SMVersion =
1564 uint32_t ZMax = 1024;
1565 uint32_t ThreadMax = 1024;
1566 if (IsDXIL && SMVersion.getMajor() <= 4) {
1569 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
1579 diag::err_hlsl_numthreads_argument_oor)
1588 diag::err_hlsl_numthreads_argument_oor)
1597 diag::err_hlsl_numthreads_argument_oor)
1602 if (
X * Y * Z > ThreadMax) {
1603 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1620 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1628 if (SpelledArgsCount > 1 &&
1632 uint32_t Preferred = 0;
1633 if (SpelledArgsCount > 2 &&
1637 if (SpelledArgsCount > 2) {
1640 diag::err_attribute_power_of_two_in_range)
1641 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1646 if (Preferred < Min || Preferred >
Max) {
1648 diag::err_attribute_power_of_two_in_range)
1649 << AL <<
Min <<
Max << Preferred;
1652 }
else if (SpelledArgsCount > 1) {
1655 diag::err_attribute_power_of_two_in_range)
1656 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
1660 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1663 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
1668 diag::err_attribute_power_of_two_in_range)
1669 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
1674 HLSLWaveSizeAttr *NewAttr =
1698 uint32_t Binding = 0;
1713 if (!
T->hasUnsignedIntegerRepresentation() ||
1714 (VT && VT->getNumElements() > 3)) {
1715 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1716 << AL <<
"uint/uint2/uint3";
1725 if (!
T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1726 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1727 << AL <<
"float/float1/float2/float3/float4";
1735 std::optional<unsigned> Index) {
1739 QualType ValueType = VD->getType();
1740 if (
auto *FD = dyn_cast<FunctionDecl>(D))
1743 bool IsOutput =
false;
1744 if (HLSLParamModifierAttr *MA = D->
getAttr<HLSLParamModifierAttr>()) {
1751 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1754 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1755 if (Index.has_value())
1756 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1761 if (SemanticName ==
"SV_GROUPINDEX") {
1763 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1764 if (Index.has_value())
1765 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1770 if (SemanticName ==
"SV_GROUPTHREADID") {
1773 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1774 if (Index.has_value())
1775 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1780 if (SemanticName ==
"SV_GROUPID") {
1783 Diag(AL.
getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1784 if (Index.has_value())
1785 Diag(AL.
getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1790 if (SemanticName ==
"SV_POSITION") {
1791 const auto *VT = ValueType->getAs<
VectorType>();
1792 if (!ValueType->hasFloatingRepresentation() ||
1793 (VT && VT->getNumElements() > 4))
1794 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_type)
1795 << AL <<
"float/float1/float2/float3/float4";
1800 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1804 uint32_t IndexValue, ExplicitIndex;
1807 assert(IndexValue > 0 ? ExplicitIndex :
true);
1808 std::optional<unsigned> Index =
1809 ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
1819 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1820 << AL <<
"shader constant in a constant buffer";
1824 uint32_t SubComponent;
1834 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
1839 if (IsAggregateTy || Size > 128) {
1840 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1844 if ((Component * 32 + Size) > 128) {
1845 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1850 EltTy = VT->getElementType();
1852 if (Align > 32 && Component == 1) {
1855 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1869 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1872 llvm::Triple::EnvironmentType ShaderType;
1873 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1874 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1875 << AL << Str << ArgLoc;
1889 assert(AttrList.size() &&
"expected list of resource attributes");
1896 HLSLAttributedResourceType::Attributes ResAttrs;
1898 bool HasResourceClass =
false;
1899 for (
const Attr *A : AttrList) {
1902 LocEnd = A->getRange().getEnd();
1903 switch (A->getKind()) {
1904 case attr::HLSLResourceClass: {
1906 if (HasResourceClass) {
1907 S.
Diag(A->getLocation(), ResAttrs.ResourceClass == RC
1908 ? diag::warn_duplicate_attribute_exact
1909 : diag::warn_duplicate_attribute)
1913 ResAttrs.ResourceClass = RC;
1914 HasResourceClass =
true;
1918 if (ResAttrs.IsROV) {
1919 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1922 ResAttrs.IsROV =
true;
1924 case attr::HLSLRawBuffer:
1925 if (ResAttrs.RawBuffer) {
1926 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1929 ResAttrs.RawBuffer =
true;
1931 case attr::HLSLIsCounter:
1932 if (ResAttrs.IsCounter) {
1933 S.
Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
1936 ResAttrs.IsCounter =
true;
1938 case attr::HLSLContainedType: {
1941 if (!ContainedTy.
isNull()) {
1942 S.
Diag(A->getLocation(), ContainedTy == Ty
1943 ? diag::warn_duplicate_attribute_exact
1944 : diag::warn_duplicate_attribute)
1953 llvm_unreachable(
"unhandled resource attribute type");
1957 if (!HasResourceClass) {
1958 S.
Diag(AttrList.back()->getRange().getEnd(),
1959 diag::err_hlsl_missing_resource_class);
1964 Wrapped, ContainedTy, ResAttrs);
1966 if (LocInfo && ContainedTyInfo) {
1979 if (!
T->isHLSLResourceType()) {
1980 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
1995 AttributeCommonInfo::AS_CXX11, 0, false ,
2000 case ParsedAttr::AT_HLSLResourceClass: {
2002 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2013 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2014 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2015 <<
"ResourceClass" << Identifier;
2018 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2022 case ParsedAttr::AT_HLSLROV:
2026 case ParsedAttr::AT_HLSLRawBuffer:
2030 case ParsedAttr::AT_HLSLIsCounter:
2034 case ParsedAttr::AT_HLSLContainedType: {
2036 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2042 assert(TSI &&
"no type source info for attribute argument");
2044 diag::err_incomplete_type))
2046 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2051 llvm_unreachable(
"unhandled HLSL attribute");
2054 HLSLResourcesTypeAttrs.emplace_back(A);
2060 if (!HLSLResourcesTypeAttrs.size())
2066 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2067 const HLSLAttributedResourceType *RT =
2074 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2076 HLSLResourcesTypeAttrs.clear();
2084 auto I = LocsForHLSLAttributedResources.find(RT);
2085 if (I != LocsForHLSLAttributedResources.end()) {
2086 LocInfo = I->second;
2087 LocsForHLSLAttributedResources.erase(I);
2096void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2097 const RecordType *RT) {
2098 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
2105 "incomplete arrays inside user defined types are not supported");
2114 if (
const HLSLAttributedResourceType *AttrResType =
2115 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2120 Bindings.addDeclBindingInfo(VD, RC);
2121 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2127 collectResourceBindingsOnUserRecordDecl(VD, RT);
2139 bool SpecifiedSpace) {
2140 int RegTypeNum =
static_cast<int>(RegType);
2143 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2144 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2149 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2150 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2151 : ResourceClass::SRV;
2161 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2165 if (
const HLSLAttributedResourceType *AttrResType =
2166 HLSLAttributedResourceType::findHandleTypeOnResource(
2183 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2184 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2189 if (RegType == RegisterType::CBuffer)
2190 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2191 else if (RegType != RegisterType::C)
2192 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2196 if (RegType == RegisterType::C)
2197 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2199 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2209 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2217 bool RegisterTypesDetected[5] = {
false};
2218 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2221 if (HLSLResourceBindingAttr *
attr =
2222 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2225 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2226 int otherRegTypeNum =
static_cast<int>(otherRegType);
2228 diag::err_hlsl_duplicate_register_annotation)
2232 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2240 bool SpecifiedSpace) {
2245 "expecting VarDecl or HLSLBufferDecl");
2256 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2258 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2259 Ty = IAT->getElementType();
2261 diag::err_incomplete_type))
2265 StringRef Slot =
"";
2266 StringRef Space =
"";
2270 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2280 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2286 SpaceLoc = Loc->
getLoc();
2289 if (Str.starts_with(
"space")) {
2291 SpaceLoc = Loc->
getLoc();
2300 std::optional<unsigned> SlotNum;
2301 unsigned SpaceNum = 0;
2304 if (!Slot.empty()) {
2306 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2309 if (RegType == RegisterType::I) {
2310 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2313 StringRef SlotNumStr = Slot.substr(1);
2315 if (SlotNumStr.getAsInteger(10, N)) {
2316 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2323 if (!Space.starts_with(
"space")) {
2324 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2327 StringRef SpaceNumStr = Space.substr(5);
2328 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2329 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2334 if (SlotNum.has_value())
2339 HLSLResourceBindingAttr *NewAttr =
2340 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2342 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2397 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2401 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2402 unsigned CurrentShaderStageBit;
2407 bool ReportOnlyShaderStageIssues;
2410 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2411 static_assert(
sizeof(
unsigned) >= 4);
2412 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2413 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2414 "ShaderType is too big for this bitmap");
2417 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2418 CurrentShaderEnvironment = ShaderType;
2419 CurrentShaderStageBit = (1 << bitmapIndex);
2422 void SetUnknownShaderStageContext() {
2423 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2424 CurrentShaderStageBit = (1 << 31);
2427 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
2428 return CurrentShaderEnvironment;
2431 bool InUnknownShaderStageContext()
const {
2432 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2436 void AddToScannedFunctions(
const FunctionDecl *FD) {
2437 unsigned &ScannedStages = ScannedDecls[FD];
2438 ScannedStages |= CurrentShaderStageBit;
2441 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
2443 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
2444 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2447 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
2448 return ScannerStages & CurrentShaderStageBit;
2451 static bool NeverBeenScanned(
unsigned ScannedStages) {
2452 return ScannedStages == 0;
2456 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2457 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
2459 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
2460 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
2463 DiagnoseHLSLAvailability(Sema &SemaRef)
2465 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2466 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
2469 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
2470 void RunOnFunction(
const FunctionDecl *FD);
2472 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
2473 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
2475 HandleFunctionOrMethodRef(FD, DRE);
2479 bool VisitMemberExpr(MemberExpr *ME)
override {
2480 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
2482 HandleFunctionOrMethodRef(FD, ME);
2487void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
2490 "expected DeclRefExpr or MemberExpr");
2494 if (FD->
hasBody(FDWithBody)) {
2495 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2496 DeclsToScan.push_back(FDWithBody);
2501 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2503 CheckDeclAvailability(
2507void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2516 DeclContextsToScan.push_back(TU);
2518 while (!DeclContextsToScan.empty()) {
2519 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2520 for (
auto &D : DC->
decls()) {
2527 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
2528 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
2533 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
2538 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
2539 SetShaderStageContext(ShaderAttr->getType());
2548 for (
const auto *Redecl : FD->
redecls()) {
2549 if (Redecl->isInExportDeclContext()) {
2556 SetUnknownShaderStageContext();
2564void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
2565 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
2566 DeclsToScan.push_back(FD);
2568 while (!DeclsToScan.empty()) {
2576 const unsigned ScannedStages = GetScannedStages(FD);
2577 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2580 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2582 AddToScannedFunctions(FD);
2587bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2588 const AvailabilityAttr *AA) {
2593 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2594 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2597 llvm::Triple::EnvironmentType AttrEnv =
2598 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
2600 return CurrentEnv == AttrEnv;
2603const AvailabilityAttr *
2604DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
2605 AvailabilityAttr
const *PartialMatch =
nullptr;
2609 for (
const auto *A : D->
attrs()) {
2610 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
2611 StringRef AttrPlatform = Avail->getPlatform()->getName();
2612 StringRef TargetPlatform =
2616 if (AttrPlatform == TargetPlatform) {
2618 if (HasMatchingEnvironmentOrNone(Avail))
2620 PartialMatch = Avail;
2624 return PartialMatch;
2629void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
2630 const AvailabilityAttr *AA,
2649 if (ReportOnlyShaderStageIssues)
2655 if (InUnknownShaderStageContext())
2660 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2661 VersionTuple Introduced = AA->getIntroduced();
2670 llvm::StringRef PlatformName(
2673 llvm::StringRef CurrentEnvStr =
2674 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2676 llvm::StringRef AttrEnvStr =
2677 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
2678 bool UseEnvironment = !AttrEnvStr.empty();
2680 if (EnvironmentMatches) {
2681 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
2682 <<
Range << D << PlatformName << Introduced.getAsString()
2683 << UseEnvironment << CurrentEnvStr;
2685 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2689 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
2690 << D << PlatformName << Introduced.getAsString()
2692 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2699 if (!DefaultCBufferDecls.empty()) {
2702 DefaultCBufferDecls);
2704 getNextImplicitBindingOrderID());
2705 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2709 for (
const Decl *VD : DefaultCBufferDecls) {
2710 const HLSLResourceBindingAttr *RBA =
2711 VD->
getAttr<HLSLResourceBindingAttr>();
2712 if (RBA && RBA->hasRegisterSlot() &&
2713 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2720 SemaRef.Consumer.HandleTopLevelDecl(DG);
2722 diagnoseAvailabilityViolations(TU);
2732 TI.
getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2735 DiagnoseHLSLAvailability(
SemaRef).RunOnTranslationUnit(TU);
2742 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
2745 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2770 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
2785 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2786 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2787 << ArgOrdinal << 5 << 0
2793 unsigned ArgIndex) {
2794 auto *Arg = TheCall->
getArg(ArgIndex);
2796 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
2799 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2809 if (VecTy->getElementType()->isDoubleType())
2810 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2811 << ArgOrdinal << 1 << 0 << 1
2821 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2822 << ArgOrdinal << 5 << 1
2831 if (VecTy->getElementType()->isUnsignedIntegerType())
2834 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2835 << ArgOrdinal << 4 << 3 << 0
2844 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
2845 << ArgOrdinal << 5 << 3
2851 unsigned ArgOrdinal,
unsigned Width) {
2854 ArgTy = VTy->getElementType();
2856 uint64_t ElementBitCount =
2858 if (ElementBitCount != Width) {
2860 diag::err_integer_incorrect_bit_count)
2861 << Width << ElementBitCount;
2878 unsigned ArgIndex) {
2887 diag::err_typecheck_expect_scalar_or_vector)
2888 << ArgType << Scalar;
2895 unsigned ArgIndex) {
2900 if (!(ArgType->isScalarType() ||
2901 (VTy && VTy->getElementType()->isScalarType()))) {
2903 diag::err_typecheck_expect_any_scalar_or_vector)
2920 diag::err_typecheck_expect_any_scalar_or_vector)
2933 diag::err_typecheck_call_different_arg_types)
2952 Arg1ScalarTy = VTy->getElementType();
2956 Arg2ScalarTy = VTy->getElementType();
2959 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
2960 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
2970 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
2972 diag::err_typecheck_vector_lengths_not_equal)
2978 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
2980 diag::err_typecheck_vector_lengths_not_equal)
2993 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
2997 const HLSLAttributedResourceType *ResTy =
3001 diag::err_typecheck_expect_hlsl_resource)
3005 if (Check && Check(ResTy)) {
3007 diag::err_invalid_hlsl_resource_type)
3017 switch (BuiltinID) {
3018 case Builtin::BI__builtin_hlsl_adduint64: {
3019 if (
SemaRef.checkArgCount(TheCall, 2))
3033 if (NumElementsArg != 2 && NumElementsArg != 4) {
3035 << 1 << 64 << NumElementsArg * 32;
3049 case Builtin::BI__builtin_hlsl_resource_getpointer: {
3050 if (
SemaRef.checkArgCount(TheCall, 2) ||
3053 SemaRef.getASTContext().UnsignedIntTy))
3058 QualType ContainedTy = ResourceTy->getContainedType();
3061 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
3067 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
3068 if (
SemaRef.checkArgCount(TheCall, 3) ||
3071 SemaRef.getASTContext().UnsignedIntTy) ||
3073 SemaRef.getASTContext().UnsignedIntTy) ||
3079 QualType ReturnType = ResourceTy->getContainedType();
3085 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
3086 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
3092 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
3093 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
3099 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
3100 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
3106 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
3107 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
3110 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
3111 auto MainAttrs = MainResType->getAttrs();
3112 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
3113 MainAttrs.IsCounter =
true;
3115 MainResType->getWrappedType(), MainResType->getContainedType(),
3119 TheCall->
setType(CounterHandleTy);
3122 case Builtin::BI__builtin_hlsl_and:
3123 case Builtin::BI__builtin_hlsl_or: {
3124 if (
SemaRef.checkArgCount(TheCall, 2))
3137 case Builtin::BI__builtin_hlsl_all:
3138 case Builtin::BI__builtin_hlsl_any: {
3139 if (
SemaRef.checkArgCount(TheCall, 1))
3145 case Builtin::BI__builtin_hlsl_asdouble: {
3146 if (
SemaRef.checkArgCount(TheCall, 2))
3150 SemaRef.Context.UnsignedIntTy,
3155 SemaRef.Context.UnsignedIntTy,
3164 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3165 if (
SemaRef.BuiltinElementwiseTernaryMath(
3171 case Builtin::BI__builtin_hlsl_dot: {
3173 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
3179 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3180 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3181 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3191 EltTy = VecTy->getElementType();
3192 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3205 case Builtin::BI__builtin_hlsl_select: {
3206 if (
SemaRef.checkArgCount(TheCall, 3))
3214 if (VTy && VTy->getElementType()->isBooleanType() &&
3219 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3220 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3221 if (
SemaRef.checkArgCount(TheCall, 1))
3227 diag::err_builtin_invalid_arg_type)
3230 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3234 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3235 case Builtin::BI__builtin_hlsl_elementwise_radians:
3236 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3237 case Builtin::BI__builtin_hlsl_elementwise_frac:
3238 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
3239 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
3240 if (
SemaRef.checkArgCount(TheCall, 1))
3245 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3249 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3250 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3251 if (
SemaRef.checkArgCount(TheCall, 1))
3256 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3261 case Builtin::BI__builtin_hlsl_lerp: {
3262 if (
SemaRef.checkArgCount(TheCall, 3))
3269 if (
SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3273 case Builtin::BI__builtin_hlsl_mad: {
3274 if (
SemaRef.BuiltinElementwiseTernaryMath(
3280 case Builtin::BI__builtin_hlsl_normalize: {
3281 if (
SemaRef.checkArgCount(TheCall, 1))
3292 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3293 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3301 case Builtin::BI__builtin_hlsl_step: {
3302 if (
SemaRef.checkArgCount(TheCall, 2))
3314 case Builtin::BI__builtin_hlsl_wave_active_max:
3315 case Builtin::BI__builtin_hlsl_wave_active_min:
3316 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3317 if (
SemaRef.checkArgCount(TheCall, 1))
3332 case Builtin::BI__builtin_elementwise_bitreverse: {
3340 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3341 if (
SemaRef.checkArgCount(TheCall, 2))
3349 diag::err_typecheck_convert_incompatible)
3350 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3363 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3364 if (
SemaRef.checkArgCount(TheCall, 0))
3368 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3369 if (
SemaRef.checkArgCount(TheCall, 3))
3384 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3385 if (
SemaRef.checkArgCount(TheCall, 1))
3392 case Builtin::BI__builtin_elementwise_acos:
3393 case Builtin::BI__builtin_elementwise_asin:
3394 case Builtin::BI__builtin_elementwise_atan:
3395 case Builtin::BI__builtin_elementwise_atan2:
3396 case Builtin::BI__builtin_elementwise_ceil:
3397 case Builtin::BI__builtin_elementwise_cos:
3398 case Builtin::BI__builtin_elementwise_cosh:
3399 case Builtin::BI__builtin_elementwise_exp:
3400 case Builtin::BI__builtin_elementwise_exp2:
3401 case Builtin::BI__builtin_elementwise_exp10:
3402 case Builtin::BI__builtin_elementwise_floor:
3403 case Builtin::BI__builtin_elementwise_fmod:
3404 case Builtin::BI__builtin_elementwise_log:
3405 case Builtin::BI__builtin_elementwise_log2:
3406 case Builtin::BI__builtin_elementwise_log10:
3407 case Builtin::BI__builtin_elementwise_pow:
3408 case Builtin::BI__builtin_elementwise_roundeven:
3409 case Builtin::BI__builtin_elementwise_sin:
3410 case Builtin::BI__builtin_elementwise_sinh:
3411 case Builtin::BI__builtin_elementwise_sqrt:
3412 case Builtin::BI__builtin_elementwise_tan:
3413 case Builtin::BI__builtin_elementwise_tanh:
3414 case Builtin::BI__builtin_elementwise_trunc: {
3420 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3421 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
3422 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
3423 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3424 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3429 std::optional<llvm::APSInt> Offset =
3431 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
3433 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3439 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
3440 if (
SemaRef.checkArgCount(TheCall, 1))
3451 ArgTy = VTy->getElementType();
3454 diag::err_builtin_invalid_arg_type)
3470 WorkList.push_back(BaseTy);
3471 while (!WorkList.empty()) {
3473 T =
T.getCanonicalType().getUnqualifiedType();
3474 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
3482 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3483 llvm::append_range(List, ElementFields);
3488 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
3489 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3492 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
3493 List.insert(List.end(), MT->getNumElementsFlattened(),
3494 MT->getElementType());
3497 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
3498 if (RD->isStandardLayout())
3499 RD = RD->getStandardLayoutBaseWithFields();
3503 if (RD->
isUnion() || !RD->isAggregate()) {
3509 for (
const auto *FD : RD->
fields())
3510 if (!FD->isUnnamedBitField())
3511 FieldTypes.push_back(FD->
getType());
3513 std::reverse(FieldTypes.begin(), FieldTypes.end());
3514 llvm::append_range(WorkList, FieldTypes);
3518 if (!RD->isStandardLayout()) {
3520 for (
const auto &
Base : RD->bases())
3521 FieldTypes.push_back(
Base.getType());
3522 std::reverse(FieldTypes.begin(), FieldTypes.end());
3523 llvm::append_range(WorkList, FieldTypes);
3545 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3551 int ArraySize = VT->getNumElements();
3556 QualType ElTy = VT->getElementType();
3560 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
3576 if (
SemaRef.getASTContext().hasSameType(T1, T2))
3585 return llvm::equal(T1Types, T2Types,
3587 return SemaRef.IsLayoutCompatible(LHS, RHS);
3596 bool HadError =
false;
3598 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
3606 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
3607 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3608 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
3609 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3611 if (NSpellingIdx != OSpellingIdx) {
3613 diag::err_hlsl_param_qualifier_mismatch)
3614 << NDAttr << NewParam;
3630 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3645 llvm_unreachable(
"HLSL doesn't support pointers.");
3648 llvm_unreachable(
"HLSL doesn't support complex types.");
3650 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3652 llvm_unreachable(
"Should have returned before this");
3662 llvm_unreachable(
"HLSL doesn't support complex types.");
3664 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3669 llvm_unreachable(
"HLSL doesn't support pointers.");
3671 llvm_unreachable(
"Should have returned before this");
3677 llvm_unreachable(
"HLSL doesn't support pointers.");
3680 llvm_unreachable(
"HLSL doesn't support fixed point types.");
3684 llvm_unreachable(
"HLSL doesn't support complex types.");
3687 llvm_unreachable(
"Unhandled scalar cast");
3714 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3715 if (DestTypes[I]->isUnionType())
3744 if (SrcTypes.size() < DestTypes.size())
3747 unsigned SrcSize = SrcTypes.size();
3748 unsigned DstSize = DestTypes.size();
3750 for (I = 0; I < DstSize && I < SrcSize; I++) {
3751 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3759 for (; I < SrcSize; I++) {
3760 if (SrcTypes[I]->isUnionType())
3767 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
3768 "We should not get here without a parameter modifier expression");
3769 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
3776 << Arg << (IsInOut ? 1 : 0);
3782 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3789 << Arg << (IsInOut ? 1 : 0);
3801 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3807 auto *OpV =
new (Ctx)
3812 Res =
SemaRef.ActOnBinOp(
SemaRef.getCurScope(), Param->getBeginLoc(),
3813 tok::equal, ArgOpV, OpV);
3829 "Pointer and reference types cannot be inout or out parameters");
3830 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
3840 !VD->
hasAttr<HLSLVkConstantIdAttr>() &&
3846 if (
Decl->getType().hasAddressSpace())
3849 if (
Decl->getType()->isDependentType())
3881 if (
SemaRef.RequireCompleteType(
3884 diag::err_typecheck_decl_incomplete_type)) {
3898 DefaultCBufferDecls.push_back(VD);
3903 collectResourceBindingsOnVarDecl(VD);
3905 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
3917 processExplicitBindingsOnDecl(VD);
3925 uint32_t OrderID = getNextImplicitBindingOrderID();
3943 uint32_t OrderID = getNextImplicitBindingOrderID();
3953bool SemaHLSL::initGlobalResourceDecl(
VarDecl *VD) {
3955 "expected resource record type");
3971 const char *CreateMethodName;
3972 if (Binding.isExplicit())
3973 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
3974 :
"__createFromBinding";
3976 CreateMethodName = HasCounter
3977 ?
"__createFromImplicitBindingWithImplicitCounter"
3978 :
"__createFromImplicitBinding";
3989 if (Binding.isExplicit()) {
3993 Args.push_back(RegSlot);
3995 uint32_t OrderID = (Binding.hasImplicitOrderID())
3996 ? Binding.getImplicitOrderID()
3997 : getNextImplicitBindingOrderID();
4001 Args.push_back(OrderId);
4004 IntegerLiteral *Space =
4007 Args.push_back(Space);
4010 AST, llvm::APInt(IntTySize, 1), AST.
IntTy, SourceLocation());
4011 Args.push_back(RangeSize);
4014 AST, llvm::APInt(UIntTySize, 0), AST.
UnsignedIntTy, SourceLocation());
4015 Args.push_back(Index);
4017 StringRef VarName = VD->
getName();
4024 Name,
nullptr,
VK_PRValue, FPOptionsOverride());
4025 Args.push_back(NameCast);
4029 uint32_t CounterOrderID = getNextImplicitBindingOrderID();
4030 IntegerLiteral *CounterId =
4033 Args.push_back(CounterId);
4044 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod,
false,
4049 CK_FunctionToPointerDecay, DRE,
nullptr,
VK_PRValue, FPOptionsOverride());
4051 CallExpr *InitExpr =
4053 SourceLocation(), FPOptionsOverride());
4056 SemaRef.CheckCompleteVariableDeclaration(VD);
4060bool SemaHLSL::initGlobalResourceArrayDecl(
VarDecl *VD) {
4062 "expected array of resource records");
4073 ASTContext &AST =
SemaRef.getASTContext();
4076 CXXMethodDecl *CreateMethod =
nullptr;
4079 ResourceBindingAttrs ResourceAttrs(VD);
4080 if (ResourceAttrs.isExplicit())
4083 lookupMethod(
SemaRef, ResourceDecl,
4084 HasCounter ?
"__createFromBindingWithImplicitCounter"
4085 :
"__createFromBinding",
4089 CreateMethod = lookupMethod(
4091 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
4092 :
"__createFromImplicitBinding",
4117 return initGlobalResourceDecl(VD);
4119 return initGlobalResourceArrayDecl(VD);
4129 "expected LHS to be a resource record or array of resource records");
4130 if (Opc != BO_Assign)
4135 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
4143 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
4154void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
4156 "expected global variable that contains HLSL resource");
4159 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
4160 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
4161 ? ResourceClass::CBuffer
4162 : ResourceClass::SRV);
4175 if (
const HLSLAttributedResourceType *AttrResType =
4176 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4177 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4182 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
4183 collectResourceBindingsOnUserRecordDecl(VD, RT);
4189void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
4192 bool HasBinding =
false;
4193 for (Attr *A : VD->
attrs()) {
4197 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
4198 if (!RBA || !RBA->hasRegisterSlot())
4203 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
4204 "never have an attribute created");
4206 if (RT == RegisterType::C) {
4207 if (Bindings.hasBindingInfoForDecl(VD))
4209 diag::warn_hlsl_user_defined_type_missing_member)
4210 <<
static_cast<int>(RT);
4218 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4223 diag::warn_hlsl_user_defined_type_missing_member)
4224 <<
static_cast<int>(RT);
4232class InitListTransformer {
4236 QualType *DstIt =
nullptr;
4237 Expr **ArgIt =
nullptr;
4243 bool castInitializer(Expr *E) {
4244 assert(DstIt &&
"This should always be something!");
4245 if (DstIt == DestTypes.end()) {
4247 ArgExprs.push_back(E);
4252 DstIt = DestTypes.begin();
4255 Ctx, *DstIt,
false);
4260 ArgExprs.push_back(
Init);
4265 bool buildInitializerListImpl(Expr *E) {
4267 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
4268 for (
auto *SubInit :
Init->inits())
4269 if (!buildInitializerListImpl(SubInit))
4278 return castInitializer(E);
4280 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
4285 for (uint64_t I = 0; I <
Size; ++I) {
4287 SizeTy, SourceLocation());
4293 if (!castInitializer(ElExpr.
get()))
4298 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
4299 unsigned Rows = MTy->getNumRows();
4300 unsigned Cols = MTy->getNumColumns();
4301 QualType ElemTy = MTy->getElementType();
4303 for (
unsigned C = 0;
C < Cols; ++
C) {
4304 for (
unsigned R = 0; R < Rows; ++R) {
4317 if (!castInitializer(ElExpr.
get()))
4325 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
4329 for (uint64_t I = 0; I <
Size; ++I) {
4331 SizeTy, SourceLocation());
4336 if (!buildInitializerListImpl(ElExpr.
get()))
4343 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4344 RecordDecls.push_back(RD);
4345 while (RecordDecls.back()->getNumBases()) {
4346 CXXRecordDecl *D = RecordDecls.back();
4348 "HLSL doesn't support multiple inheritance");
4349 RecordDecls.push_back(
4352 while (!RecordDecls.empty()) {
4353 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4354 for (
auto *FD : RD->
fields()) {
4355 if (FD->isUnnamedBitField())
4363 if (!buildInitializerListImpl(Res.
get()))
4371 Expr *generateInitListsImpl(QualType Ty) {
4372 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
4376 llvm::SmallVector<Expr *> Inits;
4382 if (
auto *ATy = Ty->
getAs<VectorType>()) {
4383 ElTy = ATy->getElementType();
4384 Size = ATy->getNumElements();
4385 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
4386 ElTy = CMTy->getElementType();
4387 Size = CMTy->getNumElementsFlattened();
4390 ElTy = VTy->getElementType();
4391 Size = VTy->getZExtSize();
4393 for (uint64_t I = 0; I <
Size; ++I)
4394 Inits.push_back(generateInitListsImpl(ElTy));
4397 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4398 RecordDecls.push_back(RD);
4399 while (RecordDecls.back()->getNumBases()) {
4400 CXXRecordDecl *D = RecordDecls.back();
4402 "HLSL doesn't support multiple inheritance");
4403 RecordDecls.push_back(
4406 while (!RecordDecls.empty()) {
4407 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4408 for (
auto *FD : RD->
fields())
4409 if (!FD->isUnnamedBitField())
4410 Inits.push_back(generateInitListsImpl(FD->
getType()));
4413 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4414 Inits, Inits.back()->getEndLoc());
4415 NewInit->setType(Ty);
4420 llvm::SmallVector<QualType, 16> DestTypes;
4421 llvm::SmallVector<Expr *, 16> ArgExprs;
4422 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
4423 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4424 Wrap(Entity.
getType()->isIncompleteArrayType()) {
4425 InitTy = Entity.
getType().getNonReferenceType();
4435 DstIt = DestTypes.begin();
4438 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
4440 Expr *generateInitLists() {
4441 assert(!ArgExprs.empty() &&
4442 "Call buildInitializerList to generate argument expressions.");
4443 ArgIt = ArgExprs.begin();
4445 return generateInitListsImpl(InitTy);
4446 llvm::SmallVector<Expr *> Inits;
4447 while (ArgIt != ArgExprs.end())
4448 Inits.push_back(generateInitListsImpl(InitTy));
4450 auto *NewInit =
new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4451 Inits, Inits.back()->getEndLoc());
4452 llvm::APInt ArySize(64, Inits.size());
4454 ArraySizeModifier::Normal, 0));
4463 if (
Init->getType()->isScalarType())
4466 InitListTransformer ILT(
SemaRef, Entity);
4468 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
4476 Init->setInit(I, E);
4478 if (!ILT.buildInitializerList(E))
4481 size_t ExpectedSize = ILT.DestTypes.size();
4482 size_t ActualSize = ILT.ArgExprs.size();
4483 if (ExpectedSize == 0 && ActualSize == 0)
4492 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4499 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4500 if (ExpectedSize != ActualSize) {
4501 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4502 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4503 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4510 Init->resizeInits(Ctx, NewInit->getNumInits());
4511 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
4512 Init->updateInit(Ctx, I, NewInit->getInit(I));
4517 const HLSLVkConstantIdAttr *ConstIdAttr =
4518 VDecl->
getAttr<HLSLVkConstantIdAttr>();
4525 if (!
Init->isCXX11ConstantExpr(Context, &InitValue)) {
4535 int ConstantID = ConstIdAttr->getId();
4536 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4538 ConstIdAttr->getLocation());
4542 if (
C->getType()->getCanonicalTypeUnqualified() !=
4546 Context.getTrivialTypeSourceInfo(
4547 Init->getType(),
Init->getExprLoc()),
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
llvm::dxil::ResourceClass ResourceClass
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static bool isResourceRecordTypeOrArrayOf(VarDecl *VD)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static const HLSLAttributedResourceType * getResourceArrayHandleType(VarDecl *VD)
static RegisterType getRegisterType(ResourceClass RC)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static bool hasCounterHandle(const CXXRecordDecl *RD)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool isValidWaveSizeValue(unsigned Value)
static bool IsDefaultBufferConstantDecl(VarDecl *VD)
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
void completeDefinition() override
Indicates that the definition of this class is now complete.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Decl - This represents one declaration (or definition), e.g.
attr_iterator attr_end() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
attr_iterator attr_begin() const
SourceLocation getLocation() const
void setImplicit(bool I=true)
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
Represents a ValueDecl that came out of a declarator.
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
DeclarationNameInfo getNameInfo() const
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
void addLayoutStruct(CXXRecordDecl *LS)
void setHasValidPackoffset(bool PO)
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
buffer_decl_range buffer_decls() const
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Represents the results of name lookup.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
bool hasParsedType() const
const ParsedType & getTypeArg() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
AttributeCommonInfo::Kind getKind() const
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
field_iterator field_begin() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
ASTContext & getASTContext() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
void handleSemanticAttr(Decl *D, const ParsedAttr &AL)
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
void CheckEntryPoint(FunctionDecl *FD)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void deduceAddressSpace(VarDecl *Decl)
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, std::optional< unsigned > Index)
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
bool ActOnUninitializedVarDecl(VarDecl *D)
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
QualType getInoutParameterType(QualType Ty)
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const