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"
59using llvm::hlsl::InterpolationModifier;
60using llvm::hlsl::IOType;
61using llvm::hlsl::SemanticStageInfo;
70 return VT->getElementType();
72 return MT->getElementType();
78 case ResourceClass::SRV:
79 return RegisterType::SRV;
80 case ResourceClass::UAV:
81 return RegisterType::UAV;
82 case ResourceClass::CBuffer:
83 return RegisterType::CBuffer;
84 case ResourceClass::Sampler:
85 return RegisterType::Sampler;
87 llvm_unreachable(
"unexpected ResourceClass value");
96 case ResourceClass::SRV:
97 case ResourceClass::UAV:
99 case ResourceClass::CBuffer:
101 case ResourceClass::Sampler:
104 llvm_unreachable(
"unexpected ResourceClass value");
110 assert(RT !=
nullptr);
114 *RT = RegisterType::SRV;
118 *RT = RegisterType::UAV;
122 *RT = RegisterType::CBuffer;
126 *RT = RegisterType::Sampler;
130 *RT = RegisterType::C;
134 *RT = RegisterType::I;
143 case RegisterType::SRV:
145 case RegisterType::UAV:
147 case RegisterType::CBuffer:
149 case RegisterType::Sampler:
151 case RegisterType::C:
153 case RegisterType::I:
156 llvm_unreachable(
"unexpected RegisterType value");
161 case RegisterType::SRV:
162 return ResourceClass::SRV;
163 case RegisterType::UAV:
164 return ResourceClass::UAV;
165 case RegisterType::CBuffer:
166 return ResourceClass::CBuffer;
167 case RegisterType::Sampler:
168 return ResourceClass::Sampler;
169 case RegisterType::C:
170 case RegisterType::I:
174 llvm_unreachable(
"unexpected RegisterType value");
178 const auto *BT = dyn_cast<BuiltinType>(
Type);
182 return Builtin::BI__builtin_get_spirv_spec_constant_int;
185 switch (BT->getKind()) {
186 case BuiltinType::Bool:
187 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
188 case BuiltinType::Short:
189 return Builtin::BI__builtin_get_spirv_spec_constant_short;
190 case BuiltinType::Int:
191 return Builtin::BI__builtin_get_spirv_spec_constant_int;
192 case BuiltinType::LongLong:
193 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
194 case BuiltinType::UShort:
195 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
196 case BuiltinType::UInt:
197 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
198 case BuiltinType::ULongLong:
199 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
200 case BuiltinType::Half:
201 return Builtin::BI__builtin_get_spirv_spec_constant_half;
202 case BuiltinType::Float:
203 return Builtin::BI__builtin_get_spirv_spec_constant_float;
204 case BuiltinType::Double:
205 return Builtin::BI__builtin_get_spirv_spec_constant_double;
214 llvm::raw_svector_ostream OS(Buffer);
221 ResourceClass ResClass) {
223 "DeclBindingInfo already added");
229 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
230 return &BindingsList.emplace_back(VD, ResClass);
234 ResourceClass ResClass) {
235 auto Entry = DeclToBindingListIndex.find(VD);
236 if (Entry != DeclToBindingListIndex.end()) {
237 for (
unsigned Index = Entry->getSecond();
238 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
240 if (BindingsList[Index].ResClass == ResClass)
241 return &BindingsList[Index];
248 return DeclToBindingListIndex.contains(VD);
260 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
263 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
264 : llvm::hlsl::ResourceClass::SRV;
276 if (
T->isArrayType() ||
T->isStructureType() ||
T->isConstantMatrixType())
283 assert(Context.getTypeSize(
T) <= 64 &&
284 "Scalar bit widths larger than 64 not supported");
287 return Context.getTypeSize(
T) / 8;
294 constexpr unsigned CBufferAlign = 16;
295 if (
const auto *RD =
T->getAsRecordDecl()) {
297 for (
const FieldDecl *Field : RD->fields()) {
304 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
305 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
306 FieldAlign = CBufferAlign;
309 Size = llvm::alignTo(Size, FieldAlign);
316 unsigned ElementCount = AT->getSize().getZExtValue();
317 if (ElementCount == 0)
320 unsigned ElementSize =
322 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
323 return AlignedElementSize * (ElementCount - 1) + ElementSize;
327 unsigned ElementCount = VT->getNumElements();
328 unsigned ElementSize =
330 return ElementSize * ElementCount;
333 return Context.getTypeSize(
T) / 8;
344 bool HasPackOffset =
false;
345 bool HasNonPackOffset =
false;
347 VarDecl *Var = dyn_cast<VarDecl>(Field);
350 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
351 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
352 HasPackOffset =
true;
354 HasNonPackOffset =
true;
361 if (HasNonPackOffset)
368 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
369 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
370 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
371 return LHS.second->getOffsetInBytes() <
372 RHS.second->getOffsetInBytes();
374 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
375 VarDecl *Var = PackOffsetVec[i].first;
376 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
378 unsigned Begin =
Attr->getOffsetInBytes();
379 unsigned End = Begin + Size;
380 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
381 if (End > NextBegin) {
382 VarDecl *NextVar = PackOffsetVec[i + 1].first;
394 CAT = dyn_cast<ConstantArrayType>(
396 return CAT !=
nullptr;
407static const HLSLAttributedResourceType *
410 "expected array of resource records");
412 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
414 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
417static const HLSLAttributedResourceType *
431 return RD->isEmpty();
460 Base.getType()->castAsCXXRecordDecl()))
471 assert(RD ==
nullptr &&
472 "there should be at most 1 record by a given name in a scope");
489 Name.append(NameBaseII->
getName());
496 size_t NameLength = Name.size();
505 Name.append(llvm::Twine(suffix).str());
506 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
513 Name.truncate(NameLength);
528 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
530 S, CAT->getElementType()->getUnqualifiedDesugaredType());
535 CAT->getSizeModifier(),
536 CAT->getIndexTypeCVRQualifiers())
585 "struct is already HLSL buffer compatible");
599 LS->
addAttr(PackedAttr::CreateImplicit(AST));
603 if (
unsigned NumBases = StructDecl->
getNumBases()) {
604 assert(NumBases == 1 &&
"HLSL supports only one base type");
654 LS->
addAttr(PackedAttr::CreateImplicit(AST));
659 VarDecl *VD = dyn_cast<VarDecl>(D);
675 "host layout field for $Globals decl failed to be created");
694 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
695 Attr->setBinding(RT, std::nullopt, 0);
696 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
703 BufDecl->setRBraceLoc(RBrace);
720 BufDecl->isCBuffer() ? RegisterType::CBuffer
730 int X,
int Y,
int Z) {
731 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
732 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
733 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
734 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
744 int Min,
int Max,
int Preferred,
745 int SpelledArgsCount) {
746 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
747 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
748 WS->getPreferred() != Preferred ||
749 WS->getSpelledArgsCount() != SpelledArgsCount) {
750 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
751 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
757 Result->setSpelledArgsCount(SpelledArgsCount);
761HLSLVkConstantIdAttr *
767 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
775 Diag(VD->getLocation(), diag::err_specialization_const);
779 if (!VD->getType().isConstQualified()) {
780 Diag(VD->getLocation(), diag::err_specialization_const);
784 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
785 if (CI->getId() != Id) {
786 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
787 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
792 HLSLVkConstantIdAttr *
Result =
799 llvm::Triple::EnvironmentType ShaderType) {
800 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
801 if (NT->getType() != ShaderType) {
802 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
803 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
807 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
810HLSLParamModifierAttr *
812 HLSLParamModifierAttr::Spelling Spelling) {
815 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
816 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
817 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
818 D->
dropAttr<HLSLParamModifierAttr>();
820 return HLSLParamModifierAttr::Create(
822 HLSLParamModifierAttr::Keyword_inout);
824 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
825 Diag(PA->getLocation(), diag::note_conflicting_attribute);
832 InterpolationModifier Modifier;
833 switch (
static_cast<HLSLInterpolationModifierAttr::Spelling
>(
835 case HLSLInterpolationModifierAttr::Keyword_nointerpolation:
836 Modifier = InterpolationModifier::NoInterpolation;
838 case HLSLInterpolationModifierAttr::Keyword_linear:
839 Modifier = InterpolationModifier::Linear;
841 case HLSLInterpolationModifierAttr::Keyword_centroid:
842 Modifier = InterpolationModifier::Centroid;
844 case HLSLInterpolationModifierAttr::Keyword_noperspective:
845 Modifier = InterpolationModifier::NoPerspective;
847 case HLSLInterpolationModifierAttr::Keyword_sample:
848 Modifier = InterpolationModifier::Sample;
850 case HLSLInterpolationModifierAttr::Keyword_center:
851 Modifier = InterpolationModifier::Center;
853 case HLSLInterpolationModifierAttr::SpellingNotCalculated:
854 llvm_unreachable(
"interpolation modifier spelling was not calculated");
857 InterpolationModifier Modifiers = Modifier;
859 auto Old =
static_cast<InterpolationModifier
>(
Previous->getModifiers());
861 if (
any(Old & Modifier)) {
862 Diag(AL.
getLoc(), diag::warn_hlsl_duplicate_interpolation) << AL;
863 }
else if (llvm::hlsl::getInterpolationMode(Modifiers) ==
864 llvm::dxbc::PSV::InterpolationMode::Invalid &&
865 llvm::hlsl::getInterpolationMode(Old) !=
866 llvm::dxbc::PSV::InterpolationMode::Invalid) {
867 Diag(AL.
getLoc(), diag::err_hlsl_interpolation_conflict);
868 Diag(
Previous->getLocation(), diag::note_conflicting_attribute);
871 InterpolationModifier OldLocation =
872 llvm::hlsl::getInterpolationSamplingLocation(Old);
873 InterpolationModifier NewLocation =
874 llvm::hlsl::getInterpolationSamplingLocation(Modifier);
875 if (
any(OldLocation) &&
any(NewLocation)) {
876 Diag(AL.
getLoc(), diag::warn_hlsl_interpolation_override)
877 << (std::max(OldLocation, NewLocation) ==
878 InterpolationModifier::Sample)
879 << (std::min(OldLocation, NewLocation) ==
880 InterpolationModifier::Centroid);
883 D->
dropAttr<HLSLInterpolationModifierAttr>();
885 D->
addAttr(HLSLInterpolationModifierAttr::Create(
889bool SemaHLSL::checkInterpolationModifiers(
890 const DeclaratorDecl *D,
const HLSLInterpolationModifierAttr *Inherited,
891 const HLSLParsedSemanticAttr *Semantic) {
894 const auto *A = D->
getAttr<HLSLInterpolationModifierAttr>();
898 Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
900 const auto *FD = dyn_cast<FunctionDecl>(D);
903 if (
T->isDependentType())
905 if (
const auto *RT =
T->getAs<RecordType>()) {
911 Valid &= checkInterpolationModifiers(Field, A, Semantic);
917 auto Modifiers =
static_cast<InterpolationModifier
>(A->getModifiers());
918 if (Modifiers == InterpolationModifier::NoInterpolation) {
922 llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
923 if (Kind != SemanticKind::Position && Kind != SemanticKind::Barycentrics)
925 Diag(A->getLocation(), diag::err_hlsl_interpolation_semantic)
926 << Semantic->getSemanticName();
927 Diag(Semantic->getLocation(), diag::note_conflicting_attribute);
934 Diag(A->getLocation(), diag::err_hlsl_interpolation_type) <<
T;
960 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
961 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
964 if (Shader->getType() != Env) {
965 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
977 case llvm::Triple::UnknownEnvironment:
978 case llvm::Triple::Library:
980 case llvm::Triple::RootSignature:
981 llvm_unreachable(
"rootsig environment has no functions");
983 llvm_unreachable(
"Unhandled environment in triple");
989 HLSLAppliedSemanticAttr *Semantic,
994 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
995 assert(ShaderAttr &&
"Entry point has no shader attribute");
996 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
997 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
1000 case SemanticKind::Position:
1004 return (ST == llvm::Triple::Vertex && !IsInput) ||
1005 (ST == llvm::Triple::Pixel && IsInput);
1006 case SemanticKind::VertexID:
1008 case SemanticKind::InstanceID:
1009 return ST == llvm::Triple::Vertex && IsInput;
1010 case SemanticKind::ShadingRate:
1015 return (ST == llvm::Triple::Pixel && IsInput) ||
1016 (ST == llvm::Triple::Vertex && !IsInput);
1017 case SemanticKind::Barycentrics:
1018 return ST == llvm::Triple::Pixel && IsInput;
1019 case SemanticKind::StartVertexLocation:
1020 case SemanticKind::StartInstanceLocation:
1021 return ST == llvm::Triple::Vertex && IsInput;
1027bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1030 SemanticInfo &ActiveSemantic,
1031 SemaHLSL::SemanticContext &SC) {
1032 if (ActiveSemantic.Semantic ==
nullptr) {
1033 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1034 if (ActiveSemantic.Semantic)
1035 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1038 if (!ActiveSemantic.Semantic) {
1044 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1045 ActiveSemantic.Semantic->getAttrName()->getName(),
1046 ActiveSemantic.Index.value_or(0));
1051 QualType
T = D == FD ? FD->getReturnType() : D->
getType();
1052 const ConstantArrayType *AT =
1055 Diag(A->getLoc(), diag::err_hlsl_semantic_zero_sized_array)
1056 << A->getAttrName();
1064 if (
const auto *MT = BaseTy->
getAs<ConstantMatrixType>())
1067 : MT->getNumColumns();
1069 checkSemanticAnnotation(FD, D, A, SC, ElementCount);
1072 unsigned Location = ActiveSemantic.Index.value_or(0);
1075 any(SC.CurrentIOType & IOType::In))) {
1076 bool HasVkLocation =
false;
1077 if (
auto *A = D->
getAttr<HLSLVkLocationAttr>()) {
1078 HasVkLocation =
true;
1079 Location = A->getLocation();
1082 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1083 Diag(D->
getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1086 SC.UsesExplicitVkLocations = HasVkLocation;
1089 ActiveSemantic.Index = Location + ElementCount;
1091 StringRef BaseName = ActiveSemantic.Semantic->getAttrName()->getName();
1092 std::string LowerName = BaseName.lower();
1093 for (
unsigned I = 0; I < ElementCount; ++I) {
1094 auto [It, Inserted] = SC.ActiveSemantics.try_emplace(
1095 (Twine(LowerName) + Twine(Location + I)).str(), D->
getLocation());
1098 << (BaseName + Twine(Location + I)).str();
1099 Diag(It->second, diag::note_previous_use);
1107bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1110 SemanticInfo &ActiveSemantic,
1111 SemaHLSL::SemanticContext &SC) {
1112 if (ActiveSemantic.Semantic ==
nullptr) {
1113 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1114 if (ActiveSemantic.Semantic)
1115 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1121 const RecordType *RT = dyn_cast<RecordType>(
T);
1123 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1126 const RecordDecl *RD = RT->getDecl();
1127 for (FieldDecl *Field : RD->
fields()) {
1128 SemanticInfo Info = ActiveSemantic;
1129 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1130 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1133 if (ActiveSemantic.Semantic)
1134 ActiveSemantic = Info;
1141 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1142 assert(ShaderAttr &&
"Entry point has no shader attribute");
1143 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1147 case llvm::Triple::Pixel:
1148 case llvm::Triple::Vertex:
1149 case llvm::Triple::Geometry:
1150 case llvm::Triple::Hull:
1151 case llvm::Triple::Domain:
1152 case llvm::Triple::RayGeneration:
1153 case llvm::Triple::Intersection:
1154 case llvm::Triple::AnyHit:
1155 case llvm::Triple::ClosestHit:
1156 case llvm::Triple::Miss:
1157 case llvm::Triple::Callable:
1158 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1159 diagnoseAttrStageMismatch(NT, ST,
1160 {llvm::Triple::Compute,
1161 llvm::Triple::Amplification,
1162 llvm::Triple::Mesh});
1165 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1166 diagnoseAttrStageMismatch(WS, ST,
1167 {llvm::Triple::Compute,
1168 llvm::Triple::Amplification,
1169 llvm::Triple::Mesh});
1174 case llvm::Triple::Compute:
1175 case llvm::Triple::Amplification:
1176 case llvm::Triple::Mesh:
1177 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1179 << llvm::Triple::getEnvironmentTypeName(ST);
1182 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1184 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1185 }
else if (Ver < VersionTuple(6, 6)) {
1186 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1189 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1192 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1193 << WS << WS->getSpelledArgsCount() <<
"6.8";
1198 case llvm::Triple::RootSignature:
1199 llvm_unreachable(
"rootsig environment has no function entry point");
1201 llvm_unreachable(
"Unhandled environment in triple");
1204 SemaHLSL::SemanticContext InputSC = {};
1205 InputSC.CurrentIOType = IOType::In;
1206 SemaHLSL::SemanticContext OutputSC = {};
1207 OutputSC.CurrentIOType = IOType::Out;
1210 SemanticInfo ActiveSemantic;
1211 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1212 if (ActiveSemantic.Semantic)
1213 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1217 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1218 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1222 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1223 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1224 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1227 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1228 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1233 SemanticInfo ActiveSemantic;
1234 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1235 if (ActiveSemantic.Semantic)
1236 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1238 if (ST == llvm::Triple::Vertex &&
1239 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1241 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1245void SemaHLSL::checkSemanticAnnotation(
1247 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC,
1248 unsigned ElementCount) {
1249 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1250 assert(ShaderAttr &&
"Entry point has no shader attribute");
1251 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1254 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1255 llvm::hlsl::SemanticInterpretation Interpretation =
1256 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1257 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid) {
1258 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1264 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary) {
1265 diagnoseSemanticType(Param, SemanticAttr, SemanticKind::Arbitrary);
1269 diagnoseSystemSemanticIndex(SemanticAttr, Kind, ElementCount);
1270 diagnoseSemanticType(Param, SemanticAttr, Kind);
1271 diagnoseSemanticShaderModel(SemanticAttr, Kind);
1274void SemaHLSL::diagnoseSemanticShaderModel(
const HLSLAppliedSemanticAttr *A,
1277 if (!Triple.isDXIL())
1281 case SemanticKind::Barycentrics:
1282 if (Triple.getOSVersion() < VersionTuple(6, 1))
1283 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1284 << A->getAttrName() <<
"6.1";
1286 case SemanticKind::ShadingRate:
1287 if (Triple.getOSVersion() < VersionTuple(6, 4))
1288 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1289 << A->getAttrName() <<
"6.4";
1291 case SemanticKind::StartVertexLocation:
1292 case SemanticKind::StartInstanceLocation:
1293 if (Triple.getOSVersion() < VersionTuple(6, 8))
1294 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1295 << A->getAttrName() <<
"6.8";
1302void SemaHLSL::diagnoseSystemSemanticIndex(
const HLSLAppliedSemanticAttr *A,
1304 unsigned ElementCount) {
1305 assert(Kind != SemanticKind::Invalid && Kind != SemanticKind::Arbitrary &&
1306 "expected a recognized system semantic");
1307 assert(ElementCount > 0 &&
"a semantic covers at least one element");
1310 uint32_t FirstIndex = A->getSemanticIndex();
1312 constexpr uint32_t MaxSemanticIndex = std::numeric_limits<uint32_t>::max();
1313 if (LastIndex > MaxSemanticIndex) {
1314 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1315 << A->getAttrName() << LastIndex << MaxSemanticIndex;
1323 case SemanticKind::ClipDistance:
1324 case SemanticKind::CullDistance:
1326 case SemanticKind::Target: {
1327 constexpr unsigned MaxTargetIndex = 7;
1328 if (LastIndex > MaxTargetIndex)
1329 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1330 << A->getAttrName() << LastIndex << MaxTargetIndex;
1334 Diag(A->getLoc(), diag::err_hlsl_semantic_indexing_not_supported)
1335 << A->getAttrName();
1342 return VT->getElementType();
1345 return MT->getElementType();
1351 return VT->getNumElements();
1372void SemaHLSL::diagnoseSemanticType(
const Decl *D,
1373 const HLSLAppliedSemanticAttr *A,
1375 assert(Kind != SemanticKind::Invalid &&
"expected a valid semantic");
1379 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
1385 T =
T.getNonReferenceType();
1388 QualType DeclaredTy =
T;
1390 T = AT->getElementType();
1398 case SemanticKind::Barycentrics:
1400 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1401 << A->getAttrName() << 2 << 3
1404 case SemanticKind::DispatchThreadID:
1405 case SemanticKind::GroupID:
1406 case SemanticKind::GroupThreadID:
1408 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1409 << A->getAttrName() << 1 << 3
1412 case SemanticKind::StartVertexLocation:
1413 case SemanticKind::StartInstanceLocation:
1416 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1417 << A->getAttrName() << 0 << 1 << 1
1420 case SemanticKind::GroupIndex:
1422 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1423 << A->getAttrName() << 0 << 1 << 1
1426 case SemanticKind::VertexID:
1428 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1429 << A->getAttrName() << 0 << 1
1432 case SemanticKind::Position:
1433 case SemanticKind::Target:
1435 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1436 << A->getAttrName() << 1 << 4
1439 case SemanticKind::InstanceID:
1440 case SemanticKind::ShadingRate:
1447 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1448 << A->getAttrName() << 0 << 1
1450 (IsSPIRV ? 4 : 3) << DeclaredTy;
1463 Diag(A->getLoc(), diag::err_hlsl_semantic_64bit_type)
1464 << A->getAttrName() << DeclaredTy;
1467void SemaHLSL::diagnoseAttrStageMismatch(
1468 const Attr *A, llvm::Triple::EnvironmentType Stage,
1469 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1470 SmallVector<StringRef, 8> StageStrings;
1471 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1472 [](llvm::Triple::EnvironmentType ST) {
1474 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1476 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1477 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1478 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1481void SemaHLSL::diagnoseSemanticStageMismatch(
1482 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1485 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1486 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1487 return Info.Stage == Stage;
1490 StringRef CurrentIOTypeName =
"patch constants or primitives";
1491 if (
any(CurrentIOType & IOType::In))
1492 CurrentIOTypeName =
"inputs";
1493 else if (
any(CurrentIOType & IOType::Out))
1494 CurrentIOTypeName =
"outputs";
1497 if (It == Allowed.end()) {
1498 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1499 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1500 << CurrentIOTypeName;
1504 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1505 if (!(AllowedIOTypes & CurrentIOType)) {
1506 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1507 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1508 << CurrentIOTypeName;
1513template <CastKind Kind>
1516 Ty = VTy->getElementType();
1521template <CastKind Kind>
1533 if (LHSFloat && RHSFloat) {
1561 if (LHSSigned == RHSSigned) {
1562 if (IsCompAssign || IntOrder >= 0)
1570 if (IntOrder != (LHSSigned ? 1 : -1)) {
1571 if (IsCompAssign || RHSSigned)
1580 if (IsCompAssign || LHSSigned)
1607 return CK_FloatingCast;
1609 return CK_IntegralCast;
1611 return CK_IntegralToFloating;
1613 return CK_FloatingToIntegral;
1619 bool IsCompAssign) {
1626 if (!LVecTy && IsCompAssign) {
1628 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1630 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1632 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1637 unsigned EndSz = std::numeric_limits<unsigned>::max();
1640 LSz = EndSz = LVecTy->getNumElements();
1643 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1644 "one of the above should have had a value");
1648 if (IsCompAssign && LSz != EndSz) {
1650 diag::err_hlsl_vector_compound_assignment_truncation)
1651 << LHSType << RHSType;
1657 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1662 if (!IsCompAssign && !LVecTy)
1666 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1667 return Ctx.getCommonSugaredType(LHSType, RHSType);
1675 LElTy, RElTy, IsCompAssign);
1678 "HLSL Vectors can only contain integer or floating point types");
1680 LElTy, RElTy, IsCompAssign);
1685 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1686 "Called with non-logical operator");
1688 llvm::raw_svector_ostream OS(Buff);
1690 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1691 OS << NewFnName <<
"(";
1701std::pair<IdentifierInfo *, bool>
1704 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1711 return {DeclIdent,
Found};
1722 for (
auto &RootSigElement : RootElements)
1723 Elements.push_back(RootSigElement.getElement());
1727 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1729 SignatureDecl->setImplicit();
1735 if (RootSigOverrideIdent) {
1738 if (
SemaRef.LookupQualifiedName(R, DC))
1739 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1747struct PerVisibilityBindingChecker {
1750 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1754 llvm::dxbc::ShaderVisibility Vis;
1759 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1761 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1762 llvm::dxil::ResourceClass RC,
uint32_t Space,
1764 const hlsl::RootSignatureElement *Elem) {
1766 assert(BuilderIndex < Builders.size() &&
1767 "Not enough builders for visibility type");
1768 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1769 static_cast<const void *
>(Elem));
1771 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1772 "'All' visibility must come first");
1773 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1774 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1775 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1776 static_cast<const void *
>(Elem));
1778 ElemInfoMap.push_back({Elem,
Visibility,
false});
1781 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1782 auto It = llvm::lower_bound(
1784 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1785 assert(It->Elem == Elem &&
"Element not in map");
1789 bool checkOverlap() {
1790 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1791 return LHS.Elem < RHS.Elem;
1794 bool HadOverlap =
false;
1796 using llvm::hlsl::BindingInfoBuilder;
1797 auto ReportOverlap = [
this,
1798 &HadOverlap](
const BindingInfoBuilder &Builder,
1799 const llvm::hlsl::Binding &Reported) {
1803 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1804 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1805 const auto *PrevElem =
1806 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1808 ElemInfo &Info =
getInfo(Elem);
1813 Info.Diagnosed =
true;
1815 ElemInfo &PrevInfo =
getInfo(PrevElem);
1816 llvm::dxbc::ShaderVisibility CommonVis =
1817 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1820 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1821 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1822 << Reported.isUnbounded() << Reported.UpperBound
1827 this->S->
Diag(PrevElem->getLocation(),
1828 diag::note_hlsl_resource_range_here);
1831 for (BindingInfoBuilder &Builder : Builders)
1832 Builder.calculateBindingInfo(ReportOverlap);
1852 bool HadError =
false;
1853 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1854 uint32_t UpperBound) {
1856 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1857 << LowerBound << UpperBound;
1864 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1865 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1866 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1869 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1870 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1871 ReportError(Loc, 0, 0xfffffffe);
1874 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1875 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1876 ReportError(Loc, 0, 0xffffffef);
1879 const uint32_t Version =
1880 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1881 const uint32_t VersionEnum = Version - 1;
1882 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1884 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1891 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1892 if (
const auto *Descriptor =
1893 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1894 VerifyRegister(Loc, Descriptor->Reg.Number);
1895 VerifySpace(Loc, Descriptor->Space);
1897 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1899 ReportFlagError(Loc);
1900 }
else if (
const auto *Constants =
1901 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1902 VerifyRegister(Loc, Constants->Reg.Number);
1903 VerifySpace(Loc, Constants->Space);
1904 }
else if (
const auto *Sampler =
1905 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1906 VerifyRegister(Loc, Sampler->Reg.Number);
1907 VerifySpace(Loc, Sampler->Space);
1910 "By construction, parseFloatParam can't produce a NaN from a "
1911 "float_literal token");
1913 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1914 ReportError(Loc, 0, 16);
1915 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1916 ReportFloatError(Loc, -16.f, 15.99f);
1917 }
else if (
const auto *Clause =
1918 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1920 VerifyRegister(Loc, Clause->Reg.Number);
1921 VerifySpace(Loc, Clause->Space);
1923 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1927 ReportError(Loc, 1, 0xfffffffe);
1930 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1932 ReportFlagError(Loc);
1936 PerVisibilityBindingChecker BindingChecker(
this);
1937 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1942 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1943 if (
const auto *Descriptor =
1944 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1945 uint32_t LowerBound(Descriptor->Reg.Number);
1946 uint32_t UpperBound(LowerBound);
1948 BindingChecker.trackBinding(
1949 Descriptor->Visibility,
1950 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1951 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1952 }
else if (
const auto *Constants =
1953 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1954 uint32_t LowerBound(Constants->Reg.Number);
1955 uint32_t UpperBound(LowerBound);
1957 BindingChecker.trackBinding(
1958 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1959 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1960 }
else if (
const auto *Sampler =
1961 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1962 uint32_t LowerBound(Sampler->Reg.Number);
1963 uint32_t UpperBound(LowerBound);
1965 BindingChecker.trackBinding(
1966 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1967 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1968 }
else if (
const auto *Clause =
1969 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1972 UnboundClauses.emplace_back(Clause, &RootSigElem);
1973 }
else if (
const auto *Table =
1974 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1975 assert(UnboundClauses.size() == Table->NumClauses &&
1976 "Number of unbound elements must match the number of clauses");
1977 bool HasAnySampler =
false;
1978 bool HasAnyNonSampler =
false;
1979 uint64_t Offset = 0;
1980 bool IsPrevUnbound =
false;
1981 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1983 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1984 HasAnySampler =
true;
1986 HasAnyNonSampler =
true;
1988 if (HasAnySampler && HasAnyNonSampler)
1989 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1994 if (Clause->NumDescriptors == 0)
1998 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
2000 Offset = Clause->Offset;
2002 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
2003 Offset, Clause->NumDescriptors);
2005 if (IsPrevUnbound && IsAppending)
2006 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
2007 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
2008 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
2011 Offset = RangeBound + 1;
2012 IsPrevUnbound = Clause->NumDescriptors ==
2013 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
2016 uint32_t LowerBound(Clause->Reg.Number);
2017 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
2018 LowerBound, Clause->NumDescriptors);
2020 BindingChecker.trackBinding(
2022 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
2023 LowerBound, UpperBound, ClauseElem);
2025 UnboundClauses.clear();
2029 return BindingChecker.checkOverlap();
2034 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2039 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
2040 if (RS->getSignatureIdent() != Ident) {
2041 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
2045 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
2051 if (
auto *SignatureDecl =
2052 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
2059 llvm::VersionTuple SMVersion =
2064 uint32_t ZMax = 1024;
2065 uint32_t ThreadMax = 1024;
2066 if (IsDXIL && SMVersion.getMajor() <= 4) {
2069 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
2079 diag::err_hlsl_numthreads_argument_oor)
2088 diag::err_hlsl_numthreads_argument_oor)
2097 diag::err_hlsl_numthreads_argument_oor)
2102 if (
X * Y * Z > ThreadMax) {
2103 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
2120 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
2128 if (SpelledArgsCount > 1 &&
2132 uint32_t Preferred = 0;
2133 if (SpelledArgsCount > 2 &&
2137 if (SpelledArgsCount > 2) {
2140 diag::err_attribute_power_of_two_in_range)
2141 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
2146 if (Preferred < Min || Preferred >
Max) {
2148 diag::err_attribute_power_of_two_in_range)
2149 << AL <<
Min <<
Max << Preferred;
2152 }
else if (SpelledArgsCount > 1) {
2155 diag::err_attribute_power_of_two_in_range)
2156 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
2160 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
2163 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
2168 diag::err_attribute_power_of_two_in_range)
2169 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
2174 HLSLWaveSizeAttr *NewAttr =
2211 uint32_t Binding = 0;
2233 uint32_t IndexValue(0), ExplicitIndex(0);
2236 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2238 assert(IndexValue > 0 ? ExplicitIndex :
true);
2241 if (Kind == SemanticKind::Invalid) {
2242 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2248 case SemanticKind::RenderTargetArrayIndex:
2249 case SemanticKind::ViewPortArrayIndex:
2250 case SemanticKind::ClipDistance:
2251 case SemanticKind::CullDistance:
2252 case SemanticKind::OutputControlPointID:
2253 case SemanticKind::DomainLocation:
2254 case SemanticKind::PrimitiveID:
2255 case SemanticKind::GSInstanceID:
2256 case SemanticKind::SampleIndex:
2257 case SemanticKind::IsFrontFace:
2258 case SemanticKind::Coverage:
2259 case SemanticKind::InnerCoverage:
2260 case SemanticKind::Depth:
2261 case SemanticKind::DepthLessEqual:
2262 case SemanticKind::DepthGreaterEqual:
2263 case SemanticKind::StencilRef:
2264 case SemanticKind::TessFactor:
2265 case SemanticKind::InsideTessFactor:
2266 case SemanticKind::ViewID:
2267 case SemanticKind::CullPrimitive:
2268 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2274 D->
addAttr(HLSLParsedSemanticAttr::Create(
2280 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2281 << AL <<
"shader constant in a constant buffer";
2285 uint32_t SubComponent;
2295 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2300 if (IsAggregateTy) {
2301 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2305 if ((Component * 32 + Size) > 128) {
2306 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2311 EltTy = VT->getElementType();
2313 if (Align > 32 && Component == 1) {
2316 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2330 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2333 llvm::Triple::EnvironmentType ShaderType;
2334 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2335 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2336 << AL << Str << ArgLoc;
2350 Expr *SampleCountExpr) {
2351 assert(AttrList.size() &&
"expected list of resource attributes");
2358 HLSLAttributedResourceType::Attributes ResAttrs;
2360 bool HasResourceClass =
false;
2361 bool HasResourceDimension =
false;
2362 for (
const Attr *A : AttrList) {
2367 case attr::HLSLResourceClass: {
2369 if (HasResourceClass) {
2371 ? diag::warn_duplicate_attribute_exact
2372 : diag::warn_duplicate_attribute)
2376 ResAttrs.ResourceClass = RC;
2377 HasResourceClass =
true;
2380 case attr::HLSLResourceDimension: {
2381 llvm::dxil::ResourceDimension RD =
2383 if (HasResourceDimension) {
2385 ? diag::warn_duplicate_attribute_exact
2386 : diag::warn_duplicate_attribute)
2390 ResAttrs.ResourceDimension = RD;
2391 HasResourceDimension =
true;
2394 case attr::HLSLIsROV:
2395 if (ResAttrs.IsROV) {
2399 ResAttrs.IsROV =
true;
2401 case attr::HLSLRawBuffer:
2402 if (ResAttrs.RawBuffer) {
2406 ResAttrs.RawBuffer =
true;
2408 case attr::HLSLIsArray:
2409 if (ResAttrs.IsArray) {
2413 ResAttrs.IsArray =
true;
2415 case attr::HLSLIsMultiSampled:
2416 if (ResAttrs.SampleCountExpr) {
2422 ResAttrs.SampleCountExpr =
2428 case attr::HLSLIsCounter:
2429 if (ResAttrs.IsCounter) {
2433 ResAttrs.IsCounter =
true;
2435 case attr::HLSLContainedType: {
2438 if (!ContainedTy.
isNull()) {
2440 ? diag::warn_duplicate_attribute_exact
2441 : diag::warn_duplicate_attribute)
2450 llvm_unreachable(
"unhandled resource attribute type");
2454 if (!HasResourceClass) {
2455 S.
Diag(AttrList.back()->getRange().getEnd(),
2456 diag::err_hlsl_missing_resource_class);
2461 Wrapped, ContainedTy, ResAttrs);
2463 if (LocInfo && ContainedTyInfo) {
2476 if (!
T->isHLSLResourceType()) {
2477 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2492 AttributeCommonInfo::AS_CXX11, 0, false ,
2497 case ParsedAttr::AT_HLSLResourceClass: {
2498 StringRef Identifier;
2500 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2505 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2506 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2507 <<
"ResourceClass" << Identifier;
2510 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2514 case ParsedAttr::AT_HLSLResourceDimension: {
2515 StringRef Identifier;
2517 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2521 llvm::dxil::ResourceDimension RD;
2522 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2524 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2525 <<
"ResourceDimension" << Identifier;
2528 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2532 case ParsedAttr::AT_HLSLIsROV:
2536 case ParsedAttr::AT_HLSLRawBuffer:
2540 case ParsedAttr::AT_HLSLIsCounter:
2544 case ParsedAttr::AT_HLSLIsArray:
2548 case ParsedAttr::AT_HLSLIsMultiSampled:
2552 case ParsedAttr::AT_HLSLContainedType: {
2554 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2560 assert(TSI &&
"no type source info for attribute argument");
2562 diag::err_incomplete_type))
2564 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2569 llvm_unreachable(
"unhandled HLSL attribute");
2572 HLSLResourcesTypeAttrs.emplace_back(A);
2578 if (!HLSLResourcesTypeAttrs.size())
2584 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2585 const HLSLAttributedResourceType *RT =
2592 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2594 HLSLResourcesTypeAttrs.clear();
2602 auto I = LocsForHLSLAttributedResources.find(RT);
2603 if (I != LocsForHLSLAttributedResources.end()) {
2604 LocInfo = I->second;
2605 LocsForHLSLAttributedResources.erase(I);
2614void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2615 const RecordType *RT) {
2623 "incomplete arrays inside user defined types are not supported");
2632 if (
const HLSLAttributedResourceType *AttrResType =
2633 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2638 Bindings.addDeclBindingInfo(VD, RC);
2639 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2645 collectResourceBindingsOnUserRecordDecl(VD, RT);
2657 bool SpecifiedSpace) {
2658 int RegTypeNum =
static_cast<int>(RegType);
2661 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2662 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2667 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2668 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2669 : ResourceClass::SRV;
2679 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2683 if (
const HLSLAttributedResourceType *AttrResType =
2684 HLSLAttributedResourceType::findHandleTypeOnResource(
2701 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2702 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2707 if (RegType == RegisterType::CBuffer)
2708 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2709 else if (RegType != RegisterType::C)
2710 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2714 if (RegType == RegisterType::C)
2715 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2717 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2727 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2735 bool RegisterTypesDetected[5] = {
false};
2736 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2739 if (HLSLResourceBindingAttr *
attr =
2740 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2743 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2744 int otherRegTypeNum =
static_cast<int>(otherRegType);
2746 diag::err_hlsl_duplicate_register_annotation)
2750 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2758 bool SpecifiedSpace) {
2763 "expecting VarDecl or HLSLBufferDecl");
2775 const uint64_t &Limit,
2778 uint64_t ArrayCount = 1) {
2783 if (StartSlot > Limit)
2787 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2790 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2791 Count = CAT->
getSize().getZExtValue();
2793 QualType ElemTy = AT->getElementType();
2795 ArrayCount * Count);
2799 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2802 if (ResTy->getAttrs().ResourceClass != ResClass)
2806 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2807 if (EndSlot > Limit)
2811 StartSlot = EndSlot + 1;
2816 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2819 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2822 ResClass, Ctx, ArrayCount))
2829 ResClass, Ctx, ArrayCount))
2843 const uint64_t Limit = UINT32_MAX;
2844 if (SlotNum > Limit)
2849 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2852 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2853 uint64_t BaseSlot = SlotNum;
2861 return (BaseSlot > Limit);
2868 return (SlotNum > Limit);
2871 llvm_unreachable(
"unexpected decl type");
2875 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2877 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2878 Ty = IAT->getElementType();
2880 diag::err_incomplete_type))
2884 StringRef Slot =
"";
2885 StringRef Space =
"";
2889 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2899 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2905 SpaceLoc = Loc->
getLoc();
2908 if (Str.starts_with(
"space")) {
2910 SpaceLoc = Loc->
getLoc();
2919 std::optional<unsigned> SlotNum;
2920 unsigned SpaceNum = 0;
2923 if (!Slot.empty()) {
2925 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2928 if (RegType == RegisterType::I) {
2929 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2932 const StringRef SlotNumStr = Slot.substr(1);
2937 if (SlotNumStr.getAsInteger(10, N)) {
2938 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2946 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2955 if (!Space.starts_with(
"space")) {
2956 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2959 StringRef SpaceNumStr = Space.substr(5);
2960 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2961 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2966 if (SlotNum.has_value())
2971 HLSLResourceBindingAttr *NewAttr =
2972 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
2974 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2998 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
3000 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
3004 Cur = AT->getModifiedType();
3015 ? attr::HLSLRowMajor
3016 : attr::HLSLColumnMajor;
3020 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
3029 if (ExistingKind == AttrK) {
3030 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
3032 Diag(AL.
getLoc(), diag::note_previous_attribute);
3036 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3037 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
3039 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
3044 if (AttrK == attr::HLSLRowMajor)
3045 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
3046 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
3057 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
3059 if (
T.isNull() ||
T->isDependentType())
3064 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3065 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
3073using llvm::dxil::BarrierMemoryTypeFlag;
3074using llvm::dxil::BarrierSemanticFlag;
3076template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
3077 return llvm::to_underlying(Flag);
3091 bool DiagnoseAvailability;
3118 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
3122 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
3123 unsigned CurrentShaderStageBit;
3128 bool ReportOnlyShaderStageIssues;
3131 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
3132 static_assert(
sizeof(
unsigned) >= 4);
3133 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
3134 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
3135 "ShaderType is too big for this bitmap");
3138 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
3139 CurrentShaderEnvironment = ShaderType;
3140 CurrentShaderStageBit = (1 << bitmapIndex);
3143 void SetUnknownShaderStageContext() {
3144 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
3145 CurrentShaderStageBit = (1 << 31);
3148 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
3149 return CurrentShaderEnvironment;
3152 bool InUnknownShaderStageContext()
const {
3153 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
3157 void AddToScannedFunctions(
const FunctionDecl *FD) {
3158 unsigned &ScannedStages = ScannedDecls[FD];
3159 ScannedStages |= CurrentShaderStageBit;
3162 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
3164 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
3165 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
3168 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
3169 return ScannerStages & CurrentShaderStageBit;
3172 static bool NeverBeenScanned(
unsigned ScannedStages) {
3173 return ScannedStages == 0;
3177 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3178 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3180 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3181 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3182 void DiagnoseBarrierCall(CallExpr *CE);
3183 uint64_t DiagnoseBarrierGroupMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3184 bool HasVisibleGroup,
bool IsAllMemory);
3185 uint64_t DiagnoseBarrierNodeMemory(Expr *MemoryArg, uint64_t MemoryFlags,
3186 bool HasKnownStage,
bool IsAllMemory);
3187 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg, uint64_t SemanticFlags,
3188 bool HasVisibleGroup);
3189 void DiagnoseBarrierScope(Expr *SemanticArg, uint64_t MemoryFlags,
3190 uint64_t SemanticFlags);
3193 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3194 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3195 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3196 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3199 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3200 void RunOnFunction(
const FunctionDecl *FD);
3202 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3203 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3205 HandleFunctionOrMethodRef(FD, DRE);
3209 bool VisitMemberExpr(MemberExpr *ME)
override {
3210 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3212 HandleFunctionOrMethodRef(FD, ME);
3216 bool VisitCallExpr(CallExpr *CE)
override {
3217 DiagnoseBarrierCall(CE);
3222uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3223 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasVisibleGroup,
3226 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3227 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3232 diag::err_hlsl_barrier_flag_requires_group)
3237 return MemoryFlags & ~GroupSharedMemory;
3240uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3241 Expr *MemoryArg, uint64_t MemoryFlags,
bool HasKnownStage,
3244 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3245 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3250 diag::err_hlsl_barrier_node_memory_requires_node);
3254 return MemoryFlags & ~NodeMemory;
3257void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3258 Expr *SemanticArg, uint64_t SemanticFlags,
bool HasVisibleGroup) {
3259 if (HasVisibleGroup ||
3260 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3264 diag::err_hlsl_barrier_flag_requires_group)
3265 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3271void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3272 uint64_t MemoryFlags,
3273 uint64_t SemanticFlags) {
3274 if (ReportOnlyShaderStageIssues)
3278 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3279 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3280 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3282 (MemoryFlags & DeviceScopeMemory) == 0)
3284 diag::err_hlsl_barrier_scope_requires_memory)
3286 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3290 diag::err_hlsl_barrier_scope_requires_memory)
3294void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3296 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3299 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3300 const bool HasKnownStage = !InUnknownShaderStageContext();
3301 const bool HasVisibleGroup =
3302 !HasKnownStage || Stage == llvm::Triple::Compute ||
3303 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3305 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3308 std::optional<llvm::APSInt>
Value =
3312 MemoryFlags =
Value->getZExtValue();
3313 const bool IsAllMemory =
3314 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3316 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3317 HasVisibleGroup, IsAllMemory);
3318 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3319 HasKnownStage, IsAllMemory);
3320 }
else if (!HasVisibleGroup) {
3322 diag::err_hlsl_barrier_resource_requires_group);
3327 std::optional<llvm::APSInt>
Value =
3333 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3336 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3339void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3342 "expected DeclRefExpr or MemberExpr");
3344 if (DiagnoseAvailability)
3345 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3346 CheckDeclAvailability(
3351 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3352 DeclsToScan.push_back(FDWithBody);
3355void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3360 llvm::Triple::EnvironmentType::Library;
3369 DeclContextsToScan.push_back(TU);
3371 while (!DeclContextsToScan.empty()) {
3372 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3373 for (
auto &D : DC->
decls()) {
3380 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3381 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3386 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3391 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3392 if (!IsLibraryShader && FD->
getName() == EntryName) {
3395 diag::err_hlsl_ambiguous_entry_point)
3397 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3403 SetShaderStageContext(ShaderAttr->getType());
3412 for (
const auto *Redecl : FD->
redecls()) {
3413 if (Redecl->isInExportDeclContext()) {
3420 SetUnknownShaderStageContext();
3427 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3434void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3435 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3436 DeclsToScan.push_back(FD);
3438 while (!DeclsToScan.empty()) {
3446 const unsigned ScannedStages = GetScannedStages(FD);
3447 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3450 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3452 AddToScannedFunctions(FD);
3457bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3458 const AvailabilityAttr *AA) {
3463 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3464 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3467 llvm::Triple::EnvironmentType AttrEnv =
3468 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3470 return CurrentEnv == AttrEnv;
3473const AvailabilityAttr *
3474DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3475 AvailabilityAttr
const *PartialMatch =
nullptr;
3479 for (
const auto *A : D->
attrs()) {
3480 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3481 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3482 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3483 StringRef TargetPlatform =
3487 if (AttrPlatform == TargetPlatform) {
3489 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3491 PartialMatch = Avail;
3495 return PartialMatch;
3500void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3501 const AvailabilityAttr *AA,
3520 if (ReportOnlyShaderStageIssues)
3526 if (InUnknownShaderStageContext())
3531 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3532 VersionTuple Introduced = AA->getIntroduced();
3541 llvm::StringRef PlatformName(
3544 llvm::StringRef CurrentEnvStr =
3545 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3547 llvm::StringRef AttrEnvStr =
3548 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3549 bool UseEnvironment = !AttrEnvStr.empty();
3551 if (EnvironmentMatches) {
3552 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3553 <<
Range << D << PlatformName << Introduced.getAsString()
3554 << UseEnvironment << CurrentEnvStr;
3556 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3560 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3561 << D << PlatformName << Introduced.getAsString()
3563 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3570 if (!DefaultCBufferDecls.empty()) {
3573 DefaultCBufferDecls);
3576 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3580 for (
const Decl *VD : DefaultCBufferDecls) {
3581 const HLSLResourceBindingAttr *RBA =
3582 VD->
getAttr<HLSLResourceBindingAttr>();
3583 if (RBA && RBA->hasRegisterSlot() &&
3584 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3591 SemaRef.Consumer.HandleTopLevelDecl(DG);
3593 diagnoseAvailabilityViolations(TU);
3602 "expected member expr to have resource record type or array of them");
3608 const Expr *NonConstIndexExpr =
nullptr;
3611 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3612 if (!NonConstIndexExpr)
3620 diag::err_hlsl_resource_member_array_access_not_constant);
3624 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3625 const Expr *IdxExpr = ASE->getIdx();
3627 NonConstIndexExpr = IdxExpr;
3629 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3630 E = SubME->getBase();
3631 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3632 E = ICE->getSubExpr();
3634 llvm_unreachable(
"unexpected expr type in resource member access");
3643 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3646 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3649 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3653 [[maybe_unused]]
bool LookupSucceeded =
3654 SemaRef.LookupQualifiedName(ConvR, RD);
3655 assert(LookupSucceeded);
3664std::optional<ExprResult>
3667 const HLSLAttributedResourceType *ResTy =
3668 HLSLAttributedResourceType::findHandleTypeOnResource(
3669 BaseType.getTypePtr());
3671 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3672 return std::nullopt;
3674 QualType TemplateType = ResTy->getContainedType();
3678 assert(NamedConversionDecl &&
3679 "Could not find conversion function for ConstantBuffer.");
3680 auto *ConversionDecl =
3683 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3693 const bool DiagnoseAvailability =
3695 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3696 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3697 .RunOnTranslationUnit(TU);
3704 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3707 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3732 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3745 if (!BaseType->isFloat32Type())
3746 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3747 << ArgOrdinal << 5 << 0
3757 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3758 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3759 << ArgOrdinal << 5 << 0
3768 if (!BaseType->isDoubleType()) {
3771 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3772 << ArgOrdinal << PassedType;
3779 unsigned ArgIndex) {
3780 auto *Arg = TheCall->
getArg(ArgIndex);
3782 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3785 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3799 << (ArgIndex + 1) << LValueTy;
3809 if (VecTy->getElementType()->isDoubleType())
3810 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3811 << ArgOrdinal << 1 << 0 << 1
3821 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3822 << ArgOrdinal << 5 << 1
3831 if (VecTy->getElementType()->isUnsignedIntegerType())
3834 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3835 << ArgOrdinal << 4 << 3 << 0
3844 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3845 << ArgOrdinal << 5 << 3
3851 unsigned ArgOrdinal,
unsigned Width) {
3854 ArgTy = VTy->getElementType();
3856 uint64_t ElementBitCount =
3858 if (ElementBitCount != Width) {
3860 diag::err_integer_incorrect_bit_count)
3861 << Width << ElementBitCount;
3872 else if (
auto *MatTyA =
3875 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3881 unsigned ArgIndex) {
3890 diag::err_typecheck_expect_scalar_or_vector)
3891 << ArgType << Scalar;
3898 QualType Scalar,
unsigned ArgIndex) {
3909 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3922 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3923 << ArgType << Scalar;
3928 unsigned ArgIndex) {
3933 if (!(ArgType->isScalarType() ||
3934 (VTy && VTy->getElementType()->isScalarType()))) {
3936 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3944 unsigned ArgIndex) {
3947 if (ArgType->isDependentType())
3951 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3952 ElementType = VectorTy->getElementType();
3954 ElementType = MatrixTy->getElementType();
3956 if (ElementType->isBooleanType())
3959 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
3961 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
3966 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3974 unsigned ArgIndex) {
3976 assert(ArgIndex < TheCall->getNumArgs());
3984 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4009 diag::err_typecheck_call_different_arg_types)
4028 Arg1ScalarTy = VTy->getElementType();
4032 Arg2ScalarTy = VTy->getElementType();
4035 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4036 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4046 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
4048 diag::err_typecheck_vector_lengths_not_equal)
4054 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
4056 diag::err_typecheck_vector_lengths_not_equal)
4076 Arg1ScalarTy = MTy->getElementType();
4080 Arg2ScalarTy = MTy->getElementType();
4083 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4084 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4089 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
4091 for (
Expr *Arg : {Arg1, Arg2}) {
4094 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
4096 diag::err_typecheck_vector_lengths_not_equal)
4098 << Arg->getSourceRange();
4114 unsigned ArgIndex) {
4119 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
4122 unsigned int ActualDim = 1;
4124 ActualDim = VTy->getNumElements();
4125 IndexTy = VTy->getElementType();
4129 diag::err_typecheck_expect_int)
4135 const HLSLAttributedResourceType *ResTy =
4137 assert(ResTy &&
"Resource argument must be a resource");
4138 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
4140 unsigned int ExpectedDim = 1;
4141 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
4143 (ResAttrs.IsArray ? 1 : 0);
4145 if (ActualDim != ExpectedDim) {
4147 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
4158 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
4162 const HLSLAttributedResourceType *ResTy =
4166 diag::err_typecheck_expect_hlsl_resource)
4170 if (Check && Check(ResTy)) {
4172 diag::err_invalid_hlsl_resource_type)
4182 "expected resource handle type");
4183 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4184 auto MainAttrs = MainResType->getAttrs();
4185 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4186 MainAttrs.IsCounter =
true;
4188 MainResType->getContainedType(),
4199 return "SampleBias";
4201 return "SampleGrad";
4203 return "SampleLevel";
4207 return "SampleCmpLevelZero";
4209 llvm_unreachable(
"Invalid SampleKind");
4219 if (!MD || !MD->getDeclName().isIdentifier())
4226 return MD->getName();
4234 StringRef DefaultName) {
4239 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4266 if (SMVersion >= VersionTuple(6, 7))
4269 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4271 << ContainedType << SMVersion.getAsString();
4276 bool IncludeArraySlice =
true) {
4279 [](
const HLSLAttributedResourceType *ResType) {
4280 return ResType->getAttrs().ResourceDimension ==
4281 llvm::dxil::ResourceDimension::Unknown;
4287 [](
const HLSLAttributedResourceType *ResType) {
4288 return ResType->getAttrs().ResourceClass !=
4289 llvm::hlsl::ResourceClass::Sampler;
4297 unsigned ExpectedDim =
4299 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4328 unsigned NextIdx = 3;
4340 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4344 std::optional<llvm::APSInt> ComponentOpt =
4347 int64_t ComponentVal = ComponentOpt->getSExtValue();
4348 if (ComponentVal != 0) {
4351 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4352 "The component is not in the expected range.");
4354 diag::err_hlsl_gathercmp_invalid_component)
4364 const HLSLAttributedResourceType *ResourceTy =
4367 unsigned ExpectedDim =
4370 &S, TheCall->
getArg(NextIdx),
4376 assert(ResourceTy->hasContainedType() &&
4377 "Expecting a contained type for resource with a dimension "
4379 QualType ReturnType = ResourceTy->getContainedType();
4382 IsCmp ?
"GatherCmp" :
"Gather"))
4387 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4393 ReturnType = VecTy->getElementType();
4406 [](
const HLSLAttributedResourceType *ResType) {
4407 return ResType->getAttrs().ResourceDimension ==
4408 llvm::dxil::ResourceDimension::Unknown;
4418 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4425 unsigned ResourceDim =
4427 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4443 TheCall->
setType(ResourceTy->getContainedType());
4453 [](
const HLSLAttributedResourceType *ResType) {
4454 return !ResType->isMultiSampled();
4463 unsigned ResourceDim =
4465 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4483 TheCall->
setType(ResourceTy->getContainedType());
4488 unsigned MinArgs, MaxArgs;
4516 const HLSLAttributedResourceType *ResourceTy =
4518 unsigned ExpectedDim =
4521 unsigned NextIdx = 3;
4546 &S, TheCall->
getArg(NextIdx),
4559 assert(ResourceTy->hasContainedType() &&
4560 "Expecting a contained type for resource with a dimension "
4562 QualType ReturnType = ResourceTy->getContainedType();
4573 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4590 unsigned MinArgs,
unsigned MaxArgs,
4592 bool ReportsOriginalValue) {
4593 if (MinArgs == MaxArgs) {
4596 }
else if (TheCall->
getNumArgs() < MinArgs) {
4597 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4607 const bool DestIsOK =
4613 diag::err_builtin_invalid_arg_type)
4627 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4643 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4649 const unsigned NumArgs = TheCall->
getNumArgs();
4650 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4661 switch (BuiltinID) {
4662 case Builtin::BI__builtin_hlsl_barrier: {
4663 if (
SemaRef.checkArgCount(TheCall, 2))
4666 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4667 llvm::Triple::dxil) {
4675 std::optional<llvm::APSInt> MemoryFlags =
4679 diag::err_constant_integer_arg_type)
4683 if ((MemoryFlags->getZExtValue() &
4684 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4686 diag::err_hlsl_invalid_barrier_memory_flags);
4690 const HLSLAttributedResourceType *ResTy =
4691 HLSLAttributedResourceType::findHandleTypeOnResource(
4695 diag::err_typecheck_expect_hlsl_resource)
4699 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4701 diag::err_invalid_hlsl_resource_type)
4708 std::optional<llvm::APSInt> SemanticFlags =
4710 if (!SemanticFlags) {
4712 diag::err_constant_integer_arg_type)
4716 if ((SemanticFlags->getZExtValue() &
4717 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4719 diag::err_hlsl_invalid_barrier_semantic_flags);
4726 case Builtin::BI__builtin_hlsl_adduint64: {
4727 if (
SemaRef.checkArgCount(TheCall, 2))
4741 if (NumElementsArg != 2 && NumElementsArg != 4) {
4743 << 1 << 64 << NumElementsArg * 32;
4757 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4758 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4765 QualType ContainedTy = ResourceTy->getContainedType();
4766 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4769 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4774 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4775 if (
SemaRef.checkArgCount(TheCall, 3) ||
4782 "expected pointer type for second argument");
4789 diag::err_invalid_use_of_array_type);
4793 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4796 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4801 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4802 if (
SemaRef.checkArgCount(TheCall, 2) ||
4804 SemaRef.getASTContext().IntTy))
4811 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4812 if (
SemaRef.checkArgCount(TheCall, 3) ||
4815 SemaRef.getASTContext().UnsignedIntTy) ||
4817 SemaRef.getASTContext().UnsignedIntTy) ||
4823 QualType ReturnType = ResourceTy->getContainedType();
4828 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4829 if (
SemaRef.checkArgCount(TheCall, 4) ||
4832 SemaRef.getASTContext().UnsignedIntTy) ||
4834 SemaRef.getASTContext().UnsignedIntTy) ||
4840 "expected pointer type for second argument");
4847 diag::err_invalid_use_of_array_type);
4853 case Builtin::BI__builtin_hlsl_resource_load_level:
4855 case Builtin::BI__builtin_hlsl_resource_load_ms:
4857 case Builtin::BI__builtin_hlsl_resource_sample:
4859 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4861 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4863 case Builtin::BI__builtin_hlsl_resource_sample_level:
4865 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4867 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4869 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4870 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4872 case Builtin::BI__builtin_hlsl_resource_gather:
4874 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4876 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4877 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4883 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4884 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4890 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4891 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4897 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4898 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4904 TheCall->
setType(CounterHandleTy);
4907 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4908 if (
SemaRef.checkArgCount(TheCall, 2) ||
4911 SemaRef.getASTContext().UnsignedIntTy))
4919 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4920 if (
SemaRef.checkArgCount(TheCall, 1) ||
4928 TheCall->
setType(CounterHandleTy);
4931 case Builtin::BI__builtin_hlsl_and:
4932 case Builtin::BI__builtin_hlsl_or: {
4933 if (
SemaRef.checkArgCount(TheCall, 2))
4947 case Builtin::BI__builtin_hlsl_all:
4948 case Builtin::BI__builtin_hlsl_any: {
4949 if (
SemaRef.checkArgCount(TheCall, 1))
4955 case Builtin::BI__builtin_hlsl_asdouble: {
4956 if (
SemaRef.checkArgCount(TheCall, 2))
4960 SemaRef.Context.UnsignedIntTy,
4965 SemaRef.Context.UnsignedIntTy,
4974 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
4975 if (
SemaRef.BuiltinElementwiseTernaryMath(
4981 case Builtin::BI__builtin_hlsl_dot: {
4983 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
4989 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
4990 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
4991 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5001 EltTy = VecTy->getElementType();
5002 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
5015 case Builtin::BI__builtin_hlsl_select: {
5016 if (
SemaRef.checkArgCount(TheCall, 3))
5025 if (VTy && VTy->getElementType()->isBooleanType() &&
5029 if (MTy && MTy->getElementType()->isBooleanType() &&
5034 case Builtin::BI__builtin_hlsl_elementwise_saturate:
5035 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
5036 if (
SemaRef.checkArgCount(TheCall, 1))
5042 diag::err_builtin_invalid_arg_type)
5045 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5049 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
5050 case Builtin::BI__builtin_hlsl_elementwise_frac:
5051 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
5052 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
5053 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
5054 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
5055 if (
SemaRef.checkArgCount(TheCall, 1))
5060 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5064 case Builtin::BI__builtin_hlsl_elementwise_isfinite:
5065 case Builtin::BI__builtin_hlsl_elementwise_isinf:
5066 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
5067 if (
SemaRef.checkArgCount(TheCall, 1))
5072 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5077 case Builtin::BI__builtin_hlsl_mad: {
5078 if (
SemaRef.BuiltinElementwiseTernaryMath(
5084 case Builtin::BI__builtin_hlsl_mul: {
5085 if (
SemaRef.checkArgCount(TheCall, 2))
5095 return VTy->getElementType();
5097 return MTy->getElementType();
5101 QualType EltTy0 = getElemType(Ty0);
5110 if (IsVec0 && IsMat1) {
5113 }
else if (IsMat0 && IsVec1) {
5117 assert(IsMat0 && IsMat1);
5127 case Builtin::BI__builtin_elementwise_fma: {
5128 if (
SemaRef.checkArgCount(TheCall, 3) ||
5143 case Builtin::BI__builtin_hlsl_transpose: {
5144 if (
SemaRef.checkArgCount(TheCall, 1))
5153 << 1 << 3 << 0 << 0 << ArgTy;
5158 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
5162 case Builtin::BI__builtin_hlsl_elementwise_sign: {
5163 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5171 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5172 if (
SemaRef.checkArgCount(TheCall, 1))
5186 unsigned NumElts = VecTy->getNumElements();
5196 case Builtin::BI__builtin_hlsl_wave_active_max:
5197 case Builtin::BI__builtin_hlsl_wave_active_min:
5198 case Builtin::BI__builtin_hlsl_wave_active_sum:
5199 case Builtin::BI__builtin_hlsl_wave_active_product: {
5200 if (
SemaRef.checkArgCount(TheCall, 1))
5213 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5214 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5215 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5216 if (
SemaRef.checkArgCount(TheCall, 1))
5231 (VTy && VTy->getElementType()->isIntegerType()))) {
5233 diag::err_builtin_invalid_arg_type)
5234 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5242 case Builtin::BI__builtin_hlsl_interlocked_add:
5243 case Builtin::BI__builtin_hlsl_interlocked_and:
5244 case Builtin::BI__builtin_hlsl_interlocked_max:
5245 case Builtin::BI__builtin_hlsl_interlocked_min:
5246 case Builtin::BI__builtin_hlsl_interlocked_or:
5247 case Builtin::BI__builtin_hlsl_interlocked_xor:
5253 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5259 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5265 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5271 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5277 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5285 case Builtin::BI__builtin_elementwise_bitreverse: {
5293 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits: {
5294 if (
SemaRef.checkArgCount(TheCall, 1))
5299 if (!(
ArgType->isScalarType())) {
5301 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5306 if (!(
ArgType->isBooleanType())) {
5308 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5315 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5316 if (
SemaRef.checkArgCount(TheCall, 2))
5324 diag::err_typecheck_convert_incompatible)
5325 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5338 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5339 if (
SemaRef.checkArgCount(TheCall, 1))
5348 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5349 if (
SemaRef.checkArgCount(TheCall, 0))
5353 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5354 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5355 if (
SemaRef.checkArgCount(TheCall, 1))
5368 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5369 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5370 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5371 if (
SemaRef.checkArgCount(TheCall, 1))
5383 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5384 if (
SemaRef.checkArgCount(TheCall, 3))
5390 SemaRef.Context.UnsignedIntTy, 1) ||
5392 SemaRef.Context.UnsignedIntTy, 2))
5400 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5401 if (
SemaRef.checkArgCount(TheCall, 1))
5408 case Builtin::BI__builtin_elementwise_acos:
5409 case Builtin::BI__builtin_elementwise_asin:
5410 case Builtin::BI__builtin_elementwise_atan:
5411 case Builtin::BI__builtin_elementwise_atan2:
5412 case Builtin::BI__builtin_elementwise_ceil:
5413 case Builtin::BI__builtin_elementwise_cos:
5414 case Builtin::BI__builtin_elementwise_cosh:
5415 case Builtin::BI__builtin_elementwise_exp:
5416 case Builtin::BI__builtin_elementwise_exp2:
5417 case Builtin::BI__builtin_elementwise_exp10:
5418 case Builtin::BI__builtin_elementwise_floor:
5419 case Builtin::BI__builtin_elementwise_fmod:
5420 case Builtin::BI__builtin_elementwise_log:
5421 case Builtin::BI__builtin_elementwise_log2:
5422 case Builtin::BI__builtin_elementwise_log10:
5423 case Builtin::BI__builtin_elementwise_pow:
5424 case Builtin::BI__builtin_elementwise_roundeven:
5425 case Builtin::BI__builtin_elementwise_sin:
5426 case Builtin::BI__builtin_elementwise_sinh:
5427 case Builtin::BI__builtin_elementwise_sqrt:
5428 case Builtin::BI__builtin_elementwise_tan:
5429 case Builtin::BI__builtin_elementwise_tanh:
5430 case Builtin::BI__builtin_elementwise_trunc: {
5436 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5437 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5438 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5439 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5440 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5445 std::optional<llvm::APSInt> Offset =
5447 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5449 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5455 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5456 if (
SemaRef.checkArgCount(TheCall, 1))
5467 ArgTy = VTy->getElementType();
5470 diag::err_builtin_invalid_arg_type)
5479 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5480 if (
SemaRef.checkArgCount(TheCall, 1))
5495 WorkList.push_back(BaseTy);
5496 while (!WorkList.empty()) {
5498 T =
T.getCanonicalType().getUnqualifiedType();
5499 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5507 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5508 llvm::append_range(List, ElementFields);
5513 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5514 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5517 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5518 List.insert(List.end(), MT->getNumElementsFlattened(),
5519 MT->getElementType());
5522 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5523 if (RD->isStandardLayout())
5524 RD = RD->getStandardLayoutBaseWithFields();
5528 if (RD->
isUnion() || !RD->isAggregate()) {
5534 for (
const auto *FD : RD->
fields())
5535 if (!FD->isUnnamedBitField())
5536 FieldTypes.push_back(FD->
getType());
5538 std::reverse(FieldTypes.begin(), FieldTypes.end());
5539 llvm::append_range(WorkList, FieldTypes);
5543 if (!RD->isStandardLayout()) {
5545 for (
const auto &
Base : RD->bases())
5546 FieldTypes.push_back(
Base.getType());
5547 std::reverse(FieldTypes.begin(), FieldTypes.end());
5548 llvm::append_range(WorkList, FieldTypes);
5583 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5589 int ArraySize = VT->getNumElements();
5594 QualType ElTy = VT->getElementType();
5598 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5614 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5623 return llvm::equal(T1Types, T2Types,
5625 return SemaRef.IsLayoutCompatible(LHS, RHS);
5634 bool HadError =
false;
5636 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5644 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5645 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5646 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5647 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5649 if (NSpellingIdx != OSpellingIdx) {
5651 diag::err_hlsl_param_qualifier_mismatch)
5652 << NDAttr << NewParam;
5668 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5683 llvm_unreachable(
"HLSL doesn't support pointers.");
5686 llvm_unreachable(
"HLSL doesn't support complex types.");
5688 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5690 llvm_unreachable(
"Should have returned before this");
5700 llvm_unreachable(
"HLSL doesn't support complex types.");
5702 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5707 llvm_unreachable(
"HLSL doesn't support pointers.");
5709 llvm_unreachable(
"Should have returned before this");
5715 llvm_unreachable(
"HLSL doesn't support pointers.");
5718 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5722 llvm_unreachable(
"HLSL doesn't support complex types.");
5725 llvm_unreachable(
"Unhandled scalar cast");
5746 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5752 SrcTy = SrcMatTy->getElementType();
5757 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5758 if (DestTypes[I]->isUnionType())
5790 if (SrcTypes.size() < DestTypes.size())
5793 unsigned SrcSize = SrcTypes.size();
5794 unsigned DstSize = DestTypes.size();
5796 for (I = 0; I < DstSize && I < SrcSize; I++) {
5797 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5805 for (; I < SrcSize; I++) {
5806 if (SrcTypes[I]->isUnionType())
5849 tok::equal, ArgOpV, OpV);
5861 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5862 "We should not get here without a parameter modifier expression");
5863 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5870 << Arg << (IsInOut ? 1 : 0);
5874 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5881 << Arg << (IsInOut ? 1 : 0);
5889 Param->getBeginLoc(), IsInOut);
5897 "Pointer and reference types cannot be inout or out parameters");
5898 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
5914 for (
const auto *FD : RD->
fields()) {
5918 assert(RD->getNumBases() <= 1 &&
5919 "HLSL doesn't support multiple inheritance");
5920 return RD->getNumBases()
5925 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
5926 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
5938 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
5943 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
5949 if (
Decl->getType().hasAddressSpace())
5952 if (
Decl->getType()->isDependentType())
5964 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
5978 llvm::Triple::Vulkan;
5979 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
5980 if (HasDeclaredAPushConstant)
5986 HasDeclaredAPushConstant =
true;
6013class StructBindingContext {
6016 HLSLResourceBindingAttr *RegBindingsAttrs[4];
6017 unsigned RegBindingOffset[4];
6020 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
6021 static_cast<unsigned>(RegisterType::UAV) == 1 &&
6022 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
6023 static_cast<unsigned>(RegisterType::Sampler) == 3,
6024 "unexpected register type values");
6027 HLSLVkBindingAttr *VkBindingAttr;
6028 unsigned VkBindingOffset;
6033 StructBindingContext(
VarDecl *VD) {
6034 for (
unsigned i = 0; i < 4; ++i) {
6035 RegBindingsAttrs[i] =
nullptr;
6036 RegBindingOffset[i] = 0;
6038 VkBindingAttr =
nullptr;
6039 VkBindingOffset = 0;
6045 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
6047 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
6050 RegBindingsAttrs[RegTypeIdx] = RBA;
6055 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
6056 VkBindingAttr = VBA;
6063 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
6064 unsigned Range,
bool HasCounter) {
6065 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
6067 if (VkBindingAttr) {
6068 unsigned Offset = VkBindingOffset;
6069 VkBindingOffset +=
Range;
6070 return HLSLVkBindingAttr::CreateImplicit(
6071 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
6072 VkBindingAttr->getRange());
6075 HLSLResourceBindingAttr *RBA =
6076 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6077 HLSLResourceBindingAttr *NewAttr =
nullptr;
6079 if (RBA && RBA->hasRegisterSlot()) {
6082 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6083 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6085 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6086 StringRef NewSlotNumberStr =
6088 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6089 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6090 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6094 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6095 NewAttr->setBinding(RegType, std::nullopt,
6096 RBA ? RBA->getSpaceNumber() : 0);
6100 NewAttr->setImplicitCounterBindingOrderID(
6109static void createGlobalResourceDeclForStruct(
6111 QualType ResTy, StructBindingContext &BindingCtx) {
6113 "expected resource type or array of resources");
6124 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6125 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6130 const HLSLAttributedResourceType *ResHandleTy =
6131 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6135 Attr *BindingAttr = BindingCtx.createBindingAttr(
6137 ResDecl->
addAttr(BindingAttr);
6138 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6147 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6154static void handleArrayOfStructWithResources(
6156 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6161static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6163 EmbeddedResourceNameBuilder &NameBuilder,
6164 StructBindingContext &BindingCtx) {
6167 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6174 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6188 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6191 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6193 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6195 "resource arrays should have been already handled");
6196 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6205handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6207 EmbeddedResourceNameBuilder &NameBuilder,
6208 StructBindingContext &BindingCtx) {
6216 if (!SubCAT && !ElementRD)
6219 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6222 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6225 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6238void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6239 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6240 StructBindingContext BindingCtx(VD);
6244 "Expected non-resource struct or array type");
6247 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6251 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6252 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6260 if (
SemaRef.RequireCompleteType(
6263 diag::err_typecheck_decl_incomplete_type)) {
6277 DefaultCBufferDecls.push_back(VD);
6282 collectResourceBindingsOnVarDecl(VD);
6284 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6296 processExplicitBindingsOnDecl(VD);
6334 handleGlobalStructOrArrayOfWithResources(VD);
6338 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6347 "expected resource record type");
6363 const char *CreateMethodName;
6365 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6366 :
"__createFromBinding";
6368 CreateMethodName = HasCounter
6369 ?
"__createFromImplicitBindingWithImplicitCounter"
6370 :
"__createFromImplicitBinding";
6375 if (!CreateMethod) {
6380 "create method lookup should always succeed for built-in resource "
6389 Args.push_back(RegSlot);
6397 Args.push_back(OrderId);
6403 Args.push_back(Space);
6407 Args.push_back(RangeSize);
6411 Args.push_back(Index);
6413 StringRef VarName = VD->
getName();
6421 Args.push_back(NameCast);
6429 Args.push_back(CounterId);
6452 SemaRef.CheckCompleteVariableDeclaration(VD);
6458 "expected array of resource records");
6479 lookupMethod(
SemaRef, ResourceDecl,
6480 HasCounter ?
"__createFromBindingWithImplicitCounter"
6481 :
"__createFromBinding",
6485 CreateMethod = lookupMethod(
6487 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6488 :
"__createFromImplicitBinding",
6531std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6532 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6533 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6534 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6535 if (!TrueInfo || !FalseInfo)
6536 return std::nullopt;
6537 if (*TrueInfo != *FalseInfo)
6538 return std::nullopt;
6542 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6551 if (
const auto *AttrResType =
6552 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6554 return Bindings.getDeclBindingInfo(VD, RC);
6561void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6562 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6565 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6570 if (*ExprBinding ==
nullptr)
6573 auto PrevBinding = Assigns.find(VD);
6574 if (PrevBinding == Assigns.end()) {
6576 Assigns.insert({VD, *ExprBinding});
6581 if (*ExprBinding != PrevBinding->second) {
6583 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6585 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6596 "expected LHS to be a resource record or array of resource records");
6597 if (Opc != BO_Assign)
6602 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6610 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6615 trackLocalResource(VD, RHSExpr);
6632void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6634 "expected global variable that contains HLSL resource");
6637 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6638 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6639 ? ResourceClass::CBuffer
6640 : ResourceClass::SRV);
6653 if (
const HLSLAttributedResourceType *AttrResType =
6654 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6655 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6660 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6661 collectResourceBindingsOnUserRecordDecl(VD, RT);
6667void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6670 bool HasBinding =
false;
6671 for (Attr *A : VD->
attrs()) {
6674 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6675 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6678 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6679 if (!RBA || !RBA->hasRegisterSlot())
6684 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6685 "never have an attribute created");
6687 if (RT == RegisterType::C) {
6688 if (Bindings.hasBindingInfoForDecl(VD))
6690 diag::warn_hlsl_user_defined_type_missing_member)
6691 <<
static_cast<int>(RT);
6699 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6704 diag::warn_hlsl_user_defined_type_missing_member)
6705 <<
static_cast<int>(RT);
6713class InitListTransformer {
6717 QualType *DstIt =
nullptr;
6718 Expr **ArgIt =
nullptr;
6724 bool castInitializer(Expr *E) {
6725 assert(DstIt &&
"This should always be something!");
6726 if (DstIt == DestTypes.end()) {
6728 ArgExprs.push_back(E);
6733 DstIt = DestTypes.begin();
6736 Ctx, *DstIt,
false);
6741 ArgExprs.push_back(
Init);
6746 bool buildInitializerListImpl(Expr *E) {
6748 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6749 for (
auto *SubInit :
Init->inits())
6750 if (!buildInitializerListImpl(SubInit))
6760 return castInitializer(E);
6774 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6779 for (uint64_t I = 0; I <
Size; ++I) {
6781 SizeTy, SourceLocation());
6787 if (!castInitializer(ElExpr.
get()))
6792 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6793 unsigned Rows = MTy->getNumRows();
6794 unsigned Cols = MTy->getNumColumns();
6795 QualType ElemTy = MTy->getElementType();
6797 for (
unsigned R = 0;
R < Rows; ++
R) {
6798 for (
unsigned C = 0;
C < Cols; ++
C) {
6811 if (!castInitializer(ElExpr.
get()))
6819 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6823 for (uint64_t I = 0; I <
Size; ++I) {
6825 SizeTy, SourceLocation());
6830 if (!buildInitializerListImpl(ElExpr.
get()))
6837 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6838 RecordDecls.push_back(RD);
6839 while (RecordDecls.back()->getNumBases()) {
6840 CXXRecordDecl *D = RecordDecls.back();
6842 "HLSL doesn't support multiple inheritance");
6843 RecordDecls.push_back(
6846 while (!RecordDecls.empty()) {
6847 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6848 for (
auto *FD : RD->
fields()) {
6849 if (FD->isUnnamedBitField())
6857 if (!buildInitializerListImpl(Res.
get()))
6865 Expr *generateInitListsImpl(QualType Ty) {
6867 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6872 llvm::SmallVector<Expr *>
Inits;
6877 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6878 ElTy = ATy->getElementType();
6879 Size = ATy->getNumElements();
6880 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6881 ElTy = CMTy->getElementType();
6882 Size = CMTy->getNumElementsFlattened();
6885 ElTy = VTy->getElementType();
6886 Size = VTy->getZExtSize();
6888 for (uint64_t I = 0; I <
Size; ++I)
6889 Inits.push_back(generateInitListsImpl(ElTy));
6892 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6893 RecordDecls.push_back(RD);
6894 while (RecordDecls.back()->getNumBases()) {
6895 CXXRecordDecl *D = RecordDecls.back();
6897 "HLSL doesn't support multiple inheritance");
6898 RecordDecls.push_back(
6901 while (!RecordDecls.empty()) {
6902 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6903 for (
auto *FD : RD->
fields())
6904 if (!FD->isUnnamedBitField())
6909 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6910 Inits.back()->getEndLoc(),
false);
6911 NewInit->setType(Ty);
6916 llvm::SmallVector<QualType, 16> DestTypes;
6917 llvm::SmallVector<Expr *, 16> ArgExprs;
6918 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
6919 : S(SemaRef), Ctx(SemaRef.getASTContext()),
6920 Wrap(Entity.
getType()->isIncompleteArrayType()) {
6921 InitTy = Entity.
getType().getNonReferenceType();
6931 DstIt = DestTypes.begin();
6934 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
6936 Expr *generateInitLists() {
6937 assert(!ArgExprs.empty() &&
6938 "Call buildInitializerList to generate argument expressions.");
6939 ArgIt = ArgExprs.begin();
6941 return generateInitListsImpl(InitTy);
6942 llvm::SmallVector<Expr *>
Inits;
6943 while (ArgIt != ArgExprs.end())
6944 Inits.push_back(generateInitListsImpl(InitTy));
6947 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
6948 Inits.back()->getEndLoc(),
false);
6949 llvm::APInt ArySize(64,
Inits.size());
6951 ArraySizeModifier::Normal, 0));
6963 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
6970 if (
const auto *RT = Ty->
getAs<RecordType>()) {
6974 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
6994 if (
Init->getType()->isScalarType())
6997 InitListTransformer ILT(
SemaRef, Entity);
6999 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
7007 Init->setInit(I, E);
7009 if (!ILT.buildInitializerList(E))
7012 size_t ExpectedSize = ILT.DestTypes.size();
7013 size_t ActualSize = ILT.ArgExprs.size();
7014 if (ExpectedSize == 0 && ActualSize == 0)
7021 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7023 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7024 << (int)(ExpectedSize < ActualSize) << InitTy
7025 << ExpectedSize << ActualSize;
7035 assert(ExpectedSize > 0 &&
7036 "The expected size of an incomplete array type must be at least 1.");
7038 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
7046 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7047 if (ExpectedSize != ActualSize) {
7048 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
7049 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7050 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
7057 Init->resizeInits(Ctx, NewInit->getNumInits());
7058 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
7059 Init->updateInit(Ctx, I, NewInit->getInit(I));
7067 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7077 StringRef AccessorName = CompName->
getName();
7078 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7080 unsigned Rows = MT->getNumRows();
7081 unsigned Cols = MT->getNumColumns();
7082 bool IsZeroBasedAccessor =
false;
7083 unsigned ChunkLen = 0;
7084 if (AccessorName.size() < 2)
7086 "length 4 for zero based: \'_mRC\' or "
7087 "length 3 for one-based: \'_RC\' accessor",
7090 if (AccessorName[0] ==
'_') {
7091 if (AccessorName[1] ==
'm') {
7092 IsZeroBasedAccessor =
true;
7099 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7102 if (AccessorName.size() % ChunkLen != 0) {
7103 const llvm::StringRef
Expected = IsZeroBasedAccessor
7104 ?
"zero based: '_mRC' accessor"
7105 :
"one-based: '_RC' accessor";
7110 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7111 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7112 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7114 bool HasRepeated =
false;
7116 unsigned NumComponents = 0;
7117 const char *Begin = AccessorName.data();
7119 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7120 const char *Chunk = Begin + I;
7121 char RowChar = 0, ColChar = 0;
7122 if (IsZeroBasedAccessor) {
7124 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7125 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7127 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7134 if (Chunk[0] !=
'_')
7136 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7143 bool IsDigitsError =
false;
7145 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7149 IsDigitsError =
true;
7153 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7157 IsDigitsError =
true;
7162 unsigned Row = RowChar -
'0';
7163 unsigned Col = ColChar -
'0';
7165 bool HasIndexingError =
false;
7166 if (IsZeroBasedAccessor) {
7168 if (!isZeroBasedIndex(Row)) {
7169 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7171 HasIndexingError =
true;
7173 if (!isZeroBasedIndex(Col)) {
7174 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7176 HasIndexingError =
true;
7180 if (!isOneBasedIndex(Row)) {
7181 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7183 HasIndexingError =
true;
7185 if (!isOneBasedIndex(Col)) {
7186 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7188 HasIndexingError =
true;
7195 if (HasIndexingError)
7201 bool HasBoundsError =
false;
7203 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7205 HasBoundsError =
true;
7208 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7210 HasBoundsError =
true;
7215 unsigned FlatIndex = Row * Cols + Col;
7216 if (Seen[FlatIndex])
7218 Seen[FlatIndex] =
true;
7221 if (NumComponents == 0 || NumComponents > 4) {
7222 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7227 QualType ElemTy = MT->getElementType();
7228 if (NumComponents == 1)
7234 for (Sema::ExtVectorDeclsType::iterator
7238 if ((*I)->getUnderlyingType() == VT)
7249 trackLocalResource(VDecl,
Init);
7251 const HLSLVkConstantIdAttr *ConstIdAttr =
7252 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7259 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7269 int ConstantID = ConstIdAttr->getId();
7270 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7272 ConstIdAttr->getLocation());
7276 if (
C->getType()->getCanonicalTypeUnqualified() !=
7280 Context.getTrivialTypeSourceInfo(
7281 Init->getType(),
Init->getExprLoc()),
7300 if (!Params || Params->
size() != 1)
7313 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7314 if (TTP->hasDefaultArgument()) {
7315 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7318 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7319 if (NTTP->hasDefaultArgument()) {
7320 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7323 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7324 if (TTPD->hasDefaultArgument()) {
7325 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7332 return SemaRef.CheckTemplateIdType(
7334 TemplateArgs,
nullptr,
false);
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.
Defines AST-level helper utilities for matrix types.
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 bool containsIncompleteArrayType(QualType Ty)
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 StringRef createRegisterString(ASTContext &AST, RegisterType RegType, unsigned N)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static QualType ReportMatrixInvalidMember(Sema &S, StringRef Name, StringRef Expected, SourceLocation OpLoc, SourceLocation CompLoc)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static bool isIntUpTo32Element(const ASTContext &Ctx, QualType Elem)
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
static bool CheckScalarFloatOperand(Sema &S, CallExpr *TheCall, unsigned ArgIndex)
static bool isIntElementOfWidth(const ASTContext &Ctx, QualType Elem, uint64_t Width)
static bool isZeroSizedArray(const ConstantArrayType *CAT)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckAnyScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool hasConstantBufferLayout(QualType QT)
llvm::dxbc::PSV::SemanticKind SemanticKind
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
static bool CheckIntegerElementTypeShaderModel(Sema &S, CallExpr *TheCall, QualType ContainedType, SampleKind Kind)
static bool isMatrixType(QualType QT)
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
static bool CheckCalculateLodBuiltin(Sema &S, CallExpr *TheCall)
static QualType getScalarComponentType(QualType T)
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
static bool CheckNoDoubleElementType(Sema &S, CallExpr *TheCall, QualType ContainedType, StringRef DefaultName)
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static const Type * createHostLayoutType(Sema &S, const Type *Ty)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool CheckInterlockedBuiltin(Sema &S, CallExpr *TheCall, unsigned MinArgs, unsigned MaxArgs, InterlockedDest Dest, bool ReportsOriginalValue)
Check a call to an HLSL interlocked builtin.
static const HLSLAttributedResourceType * getResourceArrayHandleType(QualType QT)
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
static QualType createCounterHandleType(ASTContext &AST, QualType MainHandleTy)
static bool CheckMatrixSelect(Sema *S, CallExpr *TheCall)
static bool CheckArgAddrSpaceOneOf(Sema *S, CallExpr *TheCall, unsigned ArgIndex, ArrayRef< LangAS > AllowedSpaces)
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
static StringRef getSampleMethodName(SampleKind Kind)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall)
static RegisterType getRegisterType(ResourceClass RC)
static bool ValidateRegisterNumber(uint64_t SlotNum, Decl *TheDecl, ASTContext &Ctx, RegisterType RegTy)
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static char getRegisterTypeChar(RegisterType RT)
static bool CheckNotBoolScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static bool findExistingMatrixLayoutMarker(QualType T, attr::Kind &ExistingKind)
Walks the existing AttributedType sugar of T looking for a previously applied HLSLRowMajor/HLSLColumn...
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
static bool CheckWavePrefix(Sema *S, CallExpr *TheCall)
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
static LangAS getLangASFromResourceClass(ResourceClass RC)
static bool CheckTextureSamplerAndLocation(Sema &S, CallExpr *TheCall, bool IncludeArraySlice=true)
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 const Type * getHostLayoutFieldType(QualType QT)
InterlockedDest
The dest types an interlocked operation accepts. Float is 32-bit only.
static unsigned getComponentCountOf(QualType T)
static ResourceClass getResourceClass(RegisterType RT)
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static QualType getVectorOrScalarType(Sema &S, QualType BaseType, unsigned Count)
static bool CheckSamplingBuiltin(Sema &S, CallExpr *TheCall, SampleKind Kind)
static bool CheckScalarOrVectorOrMatrix(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckFloatRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
static bool CheckAnyDoubleRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
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)
static StringRef getCurrentResourceMethodName(Sema &S, StringRef DefaultName)
static bool IsDefaultBufferConstantDecl(const ASTContext &Ctx, VarDecl *VD)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool CheckGatherBuiltin(Sema &S, CallExpr *TheCall, bool IsCmp)
static QualType getElementTypeOf(QualType T, bool IncludeMatrix)
static bool isValidWaveSizeValue(unsigned Value)
static bool isResourceRecordTypeOrArrayOf(QualType Ty)
static bool CheckLoadMSBuiltin(Sema &S, CallExpr *TheCall)
static bool AccumulateHLSLResourceSlots(QualType Ty, uint64_t &StartSlot, const uint64_t &Limit, const ResourceClass ResClass, ASTContext &Ctx, uint64_t ArrayCount=1)
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)
static bool CheckIndexType(Sema *S, CallExpr *TheCall, unsigned IndexArgIndex)
static bool isFloatOrHalfElement(QualType Elem)
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],...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
unsigned getIntWidth(QualType T) const
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, unsigned NumColumns, std::optional< MatrixType::LayoutKind > Layout=std::nullopt) const
Return the unique reference to the matrix type of the specified element type and size.
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 getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
llvm::StringRef backupStr(llvm::StringRef S) const
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 getCorrespondingUnsignedType(QualType T) const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
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.
attr::Kind getKind() const
SourceLocation getLocation() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
base_class_iterator bases_end()
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.
bool isHLSLBuiltinRecord() const
Returns true if the class is a built-in HLSL record.
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.
SourceLocation getEndLoc() const
static CanQual< Type > CreateUnsafe(QualType Other)
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
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.
llvm::APInt getSize() const
Return the constant array size as an APInt.
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
unsigned getNumRows() const
Returns the number of rows in the matrix.
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.
ASTContext & getASTContext() const LLVM_READONLY
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
DeclContext * getNonTransparentDeclContext()
Return the non transparent context.
bool isInvalidDecl() 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.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
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.
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.
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
ExtVectorType - Extended vector type.
Represents difference between two FPOptions values.
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 ...
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
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.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
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'.
iterator begin(ExternalSemaSource *source, bool LocalOnly=false)
Represents the results of name lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Represents a matrix type, as defined in the Matrix Types clang extensions.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
NamedDecl * getUnderlyingDecl()
Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.
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.
A C++ nested-name-specifier augmented with source location information.
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
void setInvalid(bool b=true) const
const ParsedType & getTypeArg() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
AttributeCommonInfo::Kind getKind() const
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
RecordDecl * getDefinitionOrSelf() 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
const LangOptions & getLangOpts() 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)
ExprResult CreateOutArgExpr(Expr *Arg, QualType ArgTy, QualType ParamTy, InitializedEntity Entity, SourceLocation Loc, bool IsInOut)
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
void handleVkLocationAttr(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 handleInterpolationModifierAttr(Decl *D, const ParsedAttr &AL)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
uint32_t getNextImplicitBindingOrderID()
void CheckEntryPoint(FunctionDecl *FD)
void handleVkExtBuiltinOutputAttr(Decl *D, const ParsedAttr &AL)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
bool initGlobalResourceDecl(VarDecl *VD)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
bool initGlobalResourceArrayDecl(VarDecl *VD)
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)
Attr * buildMatrixLayoutTypeAttr(QualType T, const ParsedAttr &AL)
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
bool ActOnResourceMemberAccessExpr(MemberExpr *ME)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
QualType ActOnTemplateShorthand(TemplateDecl *Template, SourceLocation NameLoc)
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)
QualType checkMatrixComponent(Sema &S, QualType baseType, ExprValueKind &VK, SourceLocation OpLoc, const IdentifierInfo *CompName, SourceLocation CompLoc)
bool IsConstantBufferElementCompatible(QualType T1)
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)
bool canHaveOverloadedBinOp(QualType Ty, BinaryOperatorKind Opc)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
void handleVkPushConstantAttr(Decl *D, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
NamedDecl * getConstantBufferConversionFunction(QualType Type, CXXRecordDecl *RD)
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)
std::optional< ExprResult > tryPerformConstantBufferConversion(Expr *BaseExpr)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
bool diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T, SourceLocation Loc)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
bool CanPerformPackedTypeCast(Expr *Src, QualType DestTy)
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.
bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount)
Checks that a call expression's argument count is at most the desired number.
ExtVectorDeclsType ExtVectorDecls
ExtVectorDecls - This is a list all the extended vector types.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
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 TemporaryMaterializationConversion(Expr *E)
If E is a prvalue denoting an unmaterialized temporary, materialize it as an xvalue.
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExternalSemaSource * getExternalSource() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
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.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
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
StringLiteral - This represents a string literal expression, e.g.
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.
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
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
bool isFloat16Type() 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
bool isPointerType() 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...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
bool isFloat32Type() const
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 isMatrixType() const
bool isHLSLBuiltinPackedType() const
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
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
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.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
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
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
void pushBaseName(llvm::StringRef N)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
Defines the clang::TargetInfo interface.
uint32_t getResourceDimensions(llvm::dxil::ResourceDimension Dim)
bool hasResourceOffset(llvm::dxil::ResourceDimension Dim)
bool hasCounterHandle(const CXXRecordDecl *RD)
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
Top level wrappers for InstallAPI frontend operations.
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.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ 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)
bool isMatrixRowMajor(const LangOptions &LangOpts, QualType T)
Returns true if matrices of T should be laid out in row-major order.
@ 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
@ Template
We are parsing a template declaration.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ 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.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr, Expr *SampleCountExpr=nullptr)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
int __ovld __cnfn any(char)
Returns 1 if the most significant bit in any component of x is set; otherwise returns 0.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
unsigned getImplicitOrderID() const
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
bool hasImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const