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/Support/raw_ostream.h"
51#include "llvm/TargetParser/Triple.h"
60using llvm::hlsl::InterpolationModifier;
61using llvm::hlsl::IOType;
62using llvm::hlsl::SemanticStageInfo;
71 return VT->getElementType();
73 return MT->getElementType();
79 case ResourceClass::SRV:
80 return RegisterType::SRV;
81 case ResourceClass::UAV:
82 return RegisterType::UAV;
83 case ResourceClass::CBuffer:
84 return RegisterType::CBuffer;
85 case ResourceClass::Sampler:
86 return RegisterType::Sampler;
88 llvm_unreachable(
"unexpected ResourceClass value");
97 case ResourceClass::SRV:
98 case ResourceClass::UAV:
100 case ResourceClass::CBuffer:
102 case ResourceClass::Sampler:
105 llvm_unreachable(
"unexpected ResourceClass value");
111 assert(RT !=
nullptr);
115 *RT = RegisterType::SRV;
119 *RT = RegisterType::UAV;
123 *RT = RegisterType::CBuffer;
127 *RT = RegisterType::Sampler;
131 *RT = RegisterType::C;
135 *RT = RegisterType::I;
144 case RegisterType::SRV:
146 case RegisterType::UAV:
148 case RegisterType::CBuffer:
150 case RegisterType::Sampler:
152 case RegisterType::C:
154 case RegisterType::I:
157 llvm_unreachable(
"unexpected RegisterType value");
162 case RegisterType::SRV:
163 return ResourceClass::SRV;
164 case RegisterType::UAV:
165 return ResourceClass::UAV;
166 case RegisterType::CBuffer:
167 return ResourceClass::CBuffer;
168 case RegisterType::Sampler:
169 return ResourceClass::Sampler;
170 case RegisterType::C:
171 case RegisterType::I:
175 llvm_unreachable(
"unexpected RegisterType value");
179 const auto *BT = dyn_cast<BuiltinType>(
Type);
183 return Builtin::BI__builtin_get_spirv_spec_constant_int;
186 switch (BT->getKind()) {
187 case BuiltinType::Bool:
188 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
189 case BuiltinType::Short:
190 return Builtin::BI__builtin_get_spirv_spec_constant_short;
191 case BuiltinType::Int:
192 return Builtin::BI__builtin_get_spirv_spec_constant_int;
193 case BuiltinType::LongLong:
194 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
195 case BuiltinType::UShort:
196 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
197 case BuiltinType::UInt:
198 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
199 case BuiltinType::ULongLong:
200 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
201 case BuiltinType::Half:
202 return Builtin::BI__builtin_get_spirv_spec_constant_half;
203 case BuiltinType::Float:
204 return Builtin::BI__builtin_get_spirv_spec_constant_float;
205 case BuiltinType::Double:
206 return Builtin::BI__builtin_get_spirv_spec_constant_double;
215 llvm::raw_svector_ostream OS(Buffer);
222 ResourceClass ResClass) {
224 "DeclBindingInfo already added");
230 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
231 return &BindingsList.emplace_back(VD, ResClass);
235 ResourceClass ResClass) {
236 auto Entry = DeclToBindingListIndex.find(VD);
237 if (Entry != DeclToBindingListIndex.end()) {
238 for (
unsigned Index = Entry->getSecond();
239 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
241 if (BindingsList[Index].ResClass == ResClass)
242 return &BindingsList[Index];
249 return DeclToBindingListIndex.contains(VD);
261 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
264 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
265 : llvm::hlsl::ResourceClass::SRV;
277 if (
T->isArrayType() ||
T->isStructureType() ||
T->isConstantMatrixType())
284 assert(Context.getTypeSize(
T) <= 64 &&
285 "Scalar bit widths larger than 64 not supported");
288 return Context.getTypeSize(
T) / 8;
295 constexpr unsigned CBufferAlign = 16;
296 if (
const auto *RD =
T->getAsRecordDecl()) {
298 for (
const FieldDecl *Field : RD->fields()) {
305 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
306 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
307 FieldAlign = CBufferAlign;
310 Size = llvm::alignTo(Size, FieldAlign);
317 unsigned ElementCount = AT->getSize().getZExtValue();
318 if (ElementCount == 0)
321 unsigned ElementSize =
323 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
324 return AlignedElementSize * (ElementCount - 1) + ElementSize;
328 unsigned ElementCount = VT->getNumElements();
329 unsigned ElementSize =
331 return ElementSize * ElementCount;
334 return Context.getTypeSize(
T) / 8;
345 bool HasPackOffset =
false;
346 bool HasNonPackOffset =
false;
348 VarDecl *Var = dyn_cast<VarDecl>(Field);
351 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
352 PackOffsetVec.emplace_back(Var, Field->
getAttr<HLSLPackOffsetAttr>());
353 HasPackOffset =
true;
355 HasNonPackOffset =
true;
362 if (HasNonPackOffset)
369 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
370 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
371 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
372 return LHS.second->getOffsetInBytes() <
373 RHS.second->getOffsetInBytes();
375 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
376 VarDecl *Var = PackOffsetVec[i].first;
377 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
379 unsigned Begin =
Attr->getOffsetInBytes();
380 unsigned End = Begin + Size;
381 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
382 if (End > NextBegin) {
383 VarDecl *NextVar = PackOffsetVec[i + 1].first;
395 CAT = dyn_cast<ConstantArrayType>(
397 return CAT !=
nullptr;
408static const HLSLAttributedResourceType *
411 "expected array of resource records");
413 while (
const ArrayType *AT = dyn_cast<ArrayType>(Ty))
415 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
418static const HLSLAttributedResourceType *
432 return RD->isEmpty();
461 Base.getType()->castAsCXXRecordDecl()))
472 assert(RD ==
nullptr &&
473 "there should be at most 1 record by a given name in a scope");
490 Name.append(NameBaseII->
getName());
497 size_t NameLength = Name.size();
506 Name.append(llvm::Twine(suffix).str());
507 II = &AST.
Idents.
get(Name, tok::TokenKind::identifier);
514 Name.truncate(NameLength);
529 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
531 S, CAT->getElementType()->getUnqualifiedDesugaredType());
536 CAT->getSizeModifier(),
537 CAT->getIndexTypeCVRQualifiers())
586 "struct is already HLSL buffer compatible");
600 LS->
addAttr(PackedAttr::CreateImplicit(AST));
604 if (
unsigned NumBases = StructDecl->
getNumBases()) {
605 assert(NumBases == 1 &&
"HLSL supports only one base type");
655 LS->
addAttr(PackedAttr::CreateImplicit(AST));
660 VarDecl *VD = dyn_cast<VarDecl>(D);
676 "host layout field for $Globals decl failed to be created");
695 HLSLResourceBindingAttr::CreateImplicit(S.
getASTContext(),
"",
"0", {});
696 Attr->setBinding(RT, std::nullopt, 0);
697 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
704 BufDecl->setRBraceLoc(RBrace);
721 BufDecl->isCBuffer() ? RegisterType::CBuffer
731 int X,
int Y,
int Z) {
732 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
733 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
734 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
735 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
745 int Min,
int Max,
int Preferred,
746 int SpelledArgsCount) {
747 if (HLSLWaveSizeAttr *WS = D->
getAttr<HLSLWaveSizeAttr>()) {
748 if (WS->getMin() !=
Min || WS->getMax() !=
Max ||
749 WS->getPreferred() != Preferred ||
750 WS->getSpelledArgsCount() != SpelledArgsCount) {
751 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
752 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
758 Result->setSpelledArgsCount(SpelledArgsCount);
762HLSLVkConstantIdAttr *
768 Diag(AL.
getLoc(), diag::warn_attribute_ignored) << AL;
776 Diag(VD->getLocation(), diag::err_specialization_const);
780 if (!VD->getType().isConstQualified()) {
781 Diag(VD->getLocation(), diag::err_specialization_const);
785 if (HLSLVkConstantIdAttr *CI = D->
getAttr<HLSLVkConstantIdAttr>()) {
786 if (CI->getId() != Id) {
787 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
788 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
793 HLSLVkConstantIdAttr *
Result =
800 llvm::Triple::EnvironmentType ShaderType) {
801 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
802 if (NT->getType() != ShaderType) {
803 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
804 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
808 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
811HLSLParamModifierAttr *
813 HLSLParamModifierAttr::Spelling Spelling) {
816 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
817 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
818 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
819 D->
dropAttr<HLSLParamModifierAttr>();
821 return HLSLParamModifierAttr::Create(
823 HLSLParamModifierAttr::Keyword_inout);
825 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
826 Diag(PA->getLocation(), diag::note_conflicting_attribute);
833 InterpolationModifier Modifier;
834 switch (
static_cast<HLSLInterpolationModifierAttr::Spelling
>(
836 case HLSLInterpolationModifierAttr::Keyword_nointerpolation:
837 Modifier = InterpolationModifier::NoInterpolation;
839 case HLSLInterpolationModifierAttr::Keyword_linear:
840 Modifier = InterpolationModifier::Linear;
842 case HLSLInterpolationModifierAttr::Keyword_centroid:
843 Modifier = InterpolationModifier::Centroid;
845 case HLSLInterpolationModifierAttr::Keyword_noperspective:
846 Modifier = InterpolationModifier::NoPerspective;
848 case HLSLInterpolationModifierAttr::Keyword_sample:
849 Modifier = InterpolationModifier::Sample;
851 case HLSLInterpolationModifierAttr::Keyword_center:
852 Modifier = InterpolationModifier::Center;
854 case HLSLInterpolationModifierAttr::SpellingNotCalculated:
855 llvm_unreachable(
"interpolation modifier spelling was not calculated");
858 InterpolationModifier Modifiers = Modifier;
860 auto Old =
static_cast<InterpolationModifier
>(
Previous->getModifiers());
862 if (
any(Old & Modifier)) {
863 Diag(AL.
getLoc(), diag::warn_hlsl_duplicate_interpolation) << AL;
864 }
else if (llvm::hlsl::getInterpolationMode(Modifiers) ==
865 llvm::dxbc::PSV::InterpolationMode::Invalid &&
866 llvm::hlsl::getInterpolationMode(Old) !=
867 llvm::dxbc::PSV::InterpolationMode::Invalid) {
868 Diag(AL.
getLoc(), diag::err_hlsl_interpolation_conflict);
869 Diag(
Previous->getLocation(), diag::note_conflicting_attribute);
872 InterpolationModifier OldLocation =
873 llvm::hlsl::getInterpolationSamplingLocation(Old);
874 InterpolationModifier NewLocation =
875 llvm::hlsl::getInterpolationSamplingLocation(Modifier);
876 if (
any(OldLocation) &&
any(NewLocation)) {
877 Diag(AL.
getLoc(), diag::warn_hlsl_interpolation_override)
878 << (std::max(OldLocation, NewLocation) ==
879 InterpolationModifier::Sample)
880 << (std::min(OldLocation, NewLocation) ==
881 InterpolationModifier::Centroid);
884 D->
dropAttr<HLSLInterpolationModifierAttr>();
886 D->
addAttr(HLSLInterpolationModifierAttr::Create(
890bool SemaHLSL::checkInterpolationModifiers(
891 const DeclaratorDecl *D,
const HLSLInterpolationModifierAttr *Inherited,
892 const HLSLParsedSemanticAttr *Semantic) {
895 const auto *A = D->
getAttr<HLSLInterpolationModifierAttr>();
899 Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
901 const auto *FD = dyn_cast<FunctionDecl>(D);
904 if (
T->isDependentType())
906 if (
const auto *RT =
T->getAs<RecordType>()) {
912 Valid &= checkInterpolationModifiers(Field, A, Semantic);
918 auto Modifiers =
static_cast<InterpolationModifier
>(A->getModifiers());
919 if (Modifiers == InterpolationModifier::NoInterpolation) {
923 llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
924 if (Kind != SemanticKind::Position && Kind != SemanticKind::Barycentrics)
926 Diag(A->getLocation(), diag::err_hlsl_interpolation_semantic)
927 << Semantic->getSemanticName();
928 Diag(Semantic->getLocation(), diag::note_conflicting_attribute);
935 Diag(A->getLocation(), diag::err_hlsl_interpolation_type) <<
T;
961 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
962 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
965 if (Shader->getType() != Env) {
966 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
978 case llvm::Triple::UnknownEnvironment:
979 case llvm::Triple::Library:
981 case llvm::Triple::RootSignature:
982 llvm_unreachable(
"rootsig environment has no functions");
984 llvm_unreachable(
"Unhandled environment in triple");
990 HLSLAppliedSemanticAttr *Semantic,
995 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
996 assert(ShaderAttr &&
"Entry point has no shader attribute");
997 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
998 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
1001 case SemanticKind::Position:
1005 return (ST == llvm::Triple::Vertex && !IsInput) ||
1006 (ST == llvm::Triple::Pixel && IsInput);
1007 case SemanticKind::VertexID:
1009 case SemanticKind::InstanceID:
1010 return ST == llvm::Triple::Vertex && IsInput;
1011 case SemanticKind::ShadingRate:
1016 return (ST == llvm::Triple::Pixel && IsInput) ||
1017 (ST == llvm::Triple::Vertex && !IsInput);
1018 case SemanticKind::Barycentrics:
1019 case SemanticKind::SampleIndex:
1020 case SemanticKind::PrimitiveID:
1021 return ST == llvm::Triple::Pixel && IsInput;
1022 case SemanticKind::StartVertexLocation:
1023 case SemanticKind::StartInstanceLocation:
1024 return ST == llvm::Triple::Vertex && IsInput;
1025 case SemanticKind::ViewID:
1032bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1035 SemanticInfo &ActiveSemantic,
1036 SemaHLSL::SemanticContext &SC) {
1037 if (ActiveSemantic.Semantic ==
nullptr) {
1038 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1039 if (ActiveSemantic.Semantic)
1040 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1043 if (!ActiveSemantic.Semantic) {
1049 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1050 ActiveSemantic.Semantic->getAttrName()->getName(),
1051 ActiveSemantic.Index.value_or(0));
1056 QualType
T = D == FD ? FD->getReturnType() : D->
getType();
1057 const ConstantArrayType *AT =
1060 Diag(A->getLoc(), diag::err_hlsl_semantic_zero_sized_array)
1061 << A->getAttrName();
1069 if (
const auto *MT = BaseTy->
getAs<ConstantMatrixType>())
1072 : MT->getNumColumns();
1074 checkSemanticAnnotation(FD, D, A, SC, ElementCount);
1077 unsigned Location = ActiveSemantic.Index.value_or(0);
1080 any(SC.CurrentIOType & IOType::In))) {
1081 bool HasVkLocation =
false;
1082 if (
auto *A = D->
getAttr<HLSLVkLocationAttr>()) {
1083 HasVkLocation =
true;
1084 Location = A->getLocation();
1087 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1088 Diag(D->
getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1091 SC.UsesExplicitVkLocations = HasVkLocation;
1094 ActiveSemantic.Index = Location + ElementCount;
1096 StringRef BaseName = ActiveSemantic.Semantic->getAttrName()->getName();
1097 std::string LowerName = BaseName.lower();
1098 for (
unsigned I = 0; I < ElementCount; ++I) {
1099 auto [It, Inserted] = SC.ActiveSemantics.try_emplace(
1100 (Twine(LowerName) + Twine(Location + I)).str(), D->
getLocation());
1103 << (BaseName + Twine(Location + I)).str();
1104 Diag(It->second, diag::note_previous_use);
1112bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1115 SemanticInfo &ActiveSemantic,
1116 SemaHLSL::SemanticContext &SC) {
1117 if (ActiveSemantic.Semantic ==
nullptr) {
1118 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1119 if (ActiveSemantic.Semantic)
1120 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1126 const RecordType *RT = dyn_cast<RecordType>(
T);
1128 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1131 const RecordDecl *RD = RT->getDecl();
1132 for (FieldDecl *Field : RD->
fields()) {
1133 SemanticInfo Info = ActiveSemantic;
1134 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1135 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1138 if (ActiveSemantic.Semantic)
1139 ActiveSemantic = Info;
1146 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1147 assert(ShaderAttr &&
"Entry point has no shader attribute");
1148 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1152 case llvm::Triple::Pixel:
1153 case llvm::Triple::Vertex:
1154 case llvm::Triple::Geometry:
1155 case llvm::Triple::Hull:
1156 case llvm::Triple::Domain:
1157 case llvm::Triple::RayGeneration:
1158 case llvm::Triple::Intersection:
1159 case llvm::Triple::AnyHit:
1160 case llvm::Triple::ClosestHit:
1161 case llvm::Triple::Miss:
1162 case llvm::Triple::Callable:
1163 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1164 diagnoseAttrStageMismatch(NT, ST,
1165 {llvm::Triple::Compute,
1166 llvm::Triple::Amplification,
1167 llvm::Triple::Mesh});
1170 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1171 diagnoseAttrStageMismatch(WS, ST,
1172 {llvm::Triple::Compute,
1173 llvm::Triple::Amplification,
1174 llvm::Triple::Mesh});
1179 case llvm::Triple::Compute:
1180 case llvm::Triple::Amplification:
1181 case llvm::Triple::Mesh:
1182 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1184 << llvm::Triple::getEnvironmentTypeName(ST);
1187 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1189 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1190 }
else if (Ver < VersionTuple(6, 6)) {
1191 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1194 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1197 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1198 << WS << WS->getSpelledArgsCount() <<
"6.8";
1203 case llvm::Triple::RootSignature:
1204 llvm_unreachable(
"rootsig environment has no function entry point");
1206 llvm_unreachable(
"Unhandled environment in triple");
1209 SemaHLSL::SemanticContext InputSC = {};
1210 InputSC.CurrentIOType = IOType::In;
1211 SemaHLSL::SemanticContext OutputSC = {};
1212 OutputSC.CurrentIOType = IOType::Out;
1215 SemanticInfo ActiveSemantic;
1216 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1217 if (ActiveSemantic.Semantic)
1218 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1222 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1223 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1227 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1228 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1229 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1232 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1233 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1238 SemanticInfo ActiveSemantic;
1239 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1240 if (ActiveSemantic.Semantic)
1241 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1243 if (ST == llvm::Triple::Vertex &&
1244 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1246 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1250void SemaHLSL::checkSemanticAnnotation(
1252 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC,
1253 unsigned ElementCount) {
1254 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1255 assert(ShaderAttr &&
"Entry point has no shader attribute");
1256 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1259 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1260 llvm::hlsl::SemanticInterpretation Interpretation =
1261 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1262 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid) {
1263 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1269 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary) {
1270 diagnoseSemanticType(Param, SemanticAttr, SemanticKind::Arbitrary);
1274 diagnoseSystemSemanticIndex(SemanticAttr, Kind, ElementCount);
1275 diagnoseSemanticType(Param, SemanticAttr, Kind);
1276 diagnoseSemanticShaderModel(SemanticAttr, Kind);
1279void SemaHLSL::diagnoseSemanticShaderModel(
const HLSLAppliedSemanticAttr *A,
1282 if (!Triple.isDXIL())
1286 case SemanticKind::Barycentrics:
1287 case SemanticKind::ViewID:
1288 if (Triple.getOSVersion() < VersionTuple(6, 1))
1289 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1290 << A->getAttrName() <<
"6.1";
1292 case SemanticKind::ShadingRate:
1293 if (Triple.getOSVersion() < VersionTuple(6, 4))
1294 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1295 << A->getAttrName() <<
"6.4";
1297 case SemanticKind::StartVertexLocation:
1298 case SemanticKind::StartInstanceLocation:
1299 if (Triple.getOSVersion() < VersionTuple(6, 8))
1300 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1301 << A->getAttrName() <<
"6.8";
1308void SemaHLSL::diagnoseSystemSemanticIndex(
const HLSLAppliedSemanticAttr *A,
1310 unsigned ElementCount) {
1311 assert(Kind != SemanticKind::Invalid && Kind != SemanticKind::Arbitrary &&
1312 "expected a recognized system semantic");
1313 assert(ElementCount > 0 &&
"a semantic covers at least one element");
1316 uint32_t FirstIndex = A->getSemanticIndex();
1318 constexpr uint32_t MaxSemanticIndex = std::numeric_limits<uint32_t>::max();
1319 if (LastIndex > MaxSemanticIndex) {
1320 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1321 << A->getAttrName() << LastIndex << MaxSemanticIndex;
1329 case SemanticKind::ClipDistance:
1330 case SemanticKind::CullDistance:
1332 case SemanticKind::Target: {
1333 constexpr unsigned MaxTargetIndex = 7;
1334 if (LastIndex > MaxTargetIndex)
1335 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1336 << A->getAttrName() << LastIndex << MaxTargetIndex;
1340 Diag(A->getLoc(), diag::err_hlsl_semantic_indexing_not_supported)
1341 << A->getAttrName();
1348 return VT->getElementType();
1351 return MT->getElementType();
1357 return VT->getNumElements();
1378void SemaHLSL::diagnoseSemanticType(
const Decl *D,
1379 const HLSLAppliedSemanticAttr *A,
1381 assert(Kind != SemanticKind::Invalid &&
"expected a valid semantic");
1385 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
1391 T =
T.getNonReferenceType();
1394 QualType DeclaredTy =
T;
1396 T = AT->getElementType();
1404 case SemanticKind::Barycentrics:
1406 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1407 << A->getAttrName() << 2 << 3
1410 case SemanticKind::DispatchThreadID:
1411 case SemanticKind::GroupID:
1412 case SemanticKind::GroupThreadID:
1414 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1415 << A->getAttrName() << 1 << 3
1418 case SemanticKind::StartVertexLocation:
1419 case SemanticKind::StartInstanceLocation:
1420 case SemanticKind::ViewID:
1423 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1424 << A->getAttrName() << 0 << 1 << 1
1427 case SemanticKind::GroupIndex:
1429 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1430 << A->getAttrName() << 0 << 1 << 1
1433 case SemanticKind::VertexID:
1435 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1436 << A->getAttrName() << 0 << 1
1439 case SemanticKind::Position:
1440 case SemanticKind::Target:
1442 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1443 << A->getAttrName() << 1 << 4
1446 case SemanticKind::SampleIndex:
1447 case SemanticKind::PrimitiveID:
1451 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1452 << A->getAttrName() << 0 << 1
1455 case SemanticKind::InstanceID:
1456 case SemanticKind::ShadingRate:
1463 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1464 << A->getAttrName() << 0 << 1
1466 (IsSPIRV ? 4 : 3) << DeclaredTy;
1479 Diag(A->getLoc(), diag::err_hlsl_semantic_64bit_type)
1480 << A->getAttrName() << DeclaredTy;
1483void SemaHLSL::diagnoseAttrStageMismatch(
1484 const Attr *A, llvm::Triple::EnvironmentType Stage,
1485 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1486 SmallVector<StringRef, 8> StageStrings;
1487 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1488 [](llvm::Triple::EnvironmentType ST) {
1490 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1492 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1493 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1494 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1497void SemaHLSL::diagnoseSemanticStageMismatch(
1498 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1501 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1502 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1503 return Info.Stage == Stage;
1506 StringRef CurrentIOTypeName =
"patch constants or primitives";
1507 if (
any(CurrentIOType & IOType::In))
1508 CurrentIOTypeName =
"inputs";
1509 else if (
any(CurrentIOType & IOType::Out))
1510 CurrentIOTypeName =
"outputs";
1513 if (It == Allowed.end()) {
1514 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1515 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1516 << CurrentIOTypeName;
1520 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1521 if (!(AllowedIOTypes & CurrentIOType)) {
1522 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1523 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1524 << CurrentIOTypeName;
1529template <CastKind Kind>
1532 Ty = VTy->getElementType();
1537template <CastKind Kind>
1549 if (LHSFloat && RHSFloat) {
1577 if (LHSSigned == RHSSigned) {
1578 if (IsCompAssign || IntOrder >= 0)
1586 if (IntOrder != (LHSSigned ? 1 : -1)) {
1587 if (IsCompAssign || RHSSigned)
1596 if (IsCompAssign || LHSSigned)
1623 return CK_FloatingCast;
1625 return CK_IntegralCast;
1627 return CK_IntegralToFloating;
1629 return CK_FloatingToIntegral;
1635 bool IsCompAssign) {
1642 if (!LVecTy && IsCompAssign) {
1644 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1646 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1648 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1653 unsigned EndSz = std::numeric_limits<unsigned>::max();
1656 LSz = EndSz = LVecTy->getNumElements();
1659 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1660 "one of the above should have had a value");
1664 if (IsCompAssign && LSz != EndSz) {
1666 diag::err_hlsl_vector_compound_assignment_truncation)
1667 << LHSType << RHSType;
1673 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1678 if (!IsCompAssign && !LVecTy)
1682 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1683 return Ctx.getCommonSugaredType(LHSType, RHSType);
1691 LElTy, RElTy, IsCompAssign);
1694 "HLSL Vectors can only contain integer or floating point types");
1696 LElTy, RElTy, IsCompAssign);
1701 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1702 "Called with non-logical operator");
1704 llvm::raw_svector_ostream OS(Buff);
1706 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1707 OS << NewFnName <<
"(";
1717std::pair<IdentifierInfo *, bool>
1720 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1727 return {DeclIdent,
Found};
1738 for (
auto &RootSigElement : RootElements)
1739 Elements.push_back(RootSigElement.getElement());
1743 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1745 SignatureDecl->setImplicit();
1751 if (RootSigOverrideIdent) {
1754 if (
SemaRef.LookupQualifiedName(R, DC))
1755 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1763struct PerVisibilityBindingChecker {
1766 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1770 llvm::dxbc::ShaderVisibility Vis;
1775 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1777 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1778 llvm::dxil::ResourceClass RC,
uint32_t Space,
1780 const hlsl::RootSignatureElement *Elem) {
1782 assert(BuilderIndex < Builders.size() &&
1783 "Not enough builders for visibility type");
1784 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1785 static_cast<const void *
>(Elem));
1787 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1788 "'All' visibility must come first");
1789 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1790 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1791 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1792 static_cast<const void *
>(Elem));
1794 ElemInfoMap.push_back({Elem,
Visibility,
false});
1797 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1798 auto It = llvm::lower_bound(
1800 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1801 assert(It->Elem == Elem &&
"Element not in map");
1805 bool checkOverlap() {
1806 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1807 return LHS.Elem < RHS.Elem;
1810 bool HadOverlap =
false;
1812 using llvm::hlsl::BindingInfoBuilder;
1813 auto ReportOverlap = [
this,
1814 &HadOverlap](
const BindingInfoBuilder &Builder,
1815 const llvm::hlsl::Binding &Reported) {
1819 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1820 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1821 const auto *PrevElem =
1822 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1824 ElemInfo &Info =
getInfo(Elem);
1829 Info.Diagnosed =
true;
1831 ElemInfo &PrevInfo =
getInfo(PrevElem);
1832 llvm::dxbc::ShaderVisibility CommonVis =
1833 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1836 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1837 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1838 << Reported.isUnbounded() << Reported.UpperBound
1843 this->S->
Diag(PrevElem->getLocation(),
1844 diag::note_hlsl_resource_range_here);
1847 for (BindingInfoBuilder &Builder : Builders)
1848 Builder.calculateBindingInfo(ReportOverlap);
1868 bool HadError =
false;
1869 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1870 uint32_t UpperBound) {
1872 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1873 << LowerBound << UpperBound;
1880 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1881 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1882 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1885 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1886 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1887 ReportError(Loc, 0, 0xfffffffe);
1890 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1891 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1892 ReportError(Loc, 0, 0xffffffef);
1895 const uint32_t Version =
1896 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1897 const uint32_t VersionEnum = Version - 1;
1898 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1900 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1907 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1908 if (
const auto *Descriptor =
1909 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1910 VerifyRegister(Loc, Descriptor->Reg.Number);
1911 VerifySpace(Loc, Descriptor->Space);
1913 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1915 ReportFlagError(Loc);
1916 }
else if (
const auto *Constants =
1917 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1918 VerifyRegister(Loc, Constants->Reg.Number);
1919 VerifySpace(Loc, Constants->Space);
1920 }
else if (
const auto *Sampler =
1921 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1922 VerifyRegister(Loc, Sampler->Reg.Number);
1923 VerifySpace(Loc, Sampler->Space);
1926 "By construction, parseFloatParam can't produce a NaN from a "
1927 "float_literal token");
1929 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1930 ReportError(Loc, 0, 16);
1931 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1932 ReportFloatError(Loc, -16.f, 15.99f);
1933 }
else if (
const auto *Clause =
1934 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1936 VerifyRegister(Loc, Clause->Reg.Number);
1937 VerifySpace(Loc, Clause->Space);
1939 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1943 ReportError(Loc, 1, 0xfffffffe);
1946 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1948 ReportFlagError(Loc);
1952 PerVisibilityBindingChecker BindingChecker(
this);
1953 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
1958 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1959 if (
const auto *Descriptor =
1960 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1961 uint32_t LowerBound(Descriptor->Reg.Number);
1962 uint32_t UpperBound(LowerBound);
1964 BindingChecker.trackBinding(
1965 Descriptor->Visibility,
1966 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
1967 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1968 }
else if (
const auto *Constants =
1969 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1970 uint32_t LowerBound(Constants->Reg.Number);
1971 uint32_t UpperBound(LowerBound);
1973 BindingChecker.trackBinding(
1974 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1975 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1976 }
else if (
const auto *Sampler =
1977 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1978 uint32_t LowerBound(Sampler->Reg.Number);
1979 uint32_t UpperBound(LowerBound);
1981 BindingChecker.trackBinding(
1982 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1983 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1984 }
else if (
const auto *Clause =
1985 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
1988 UnboundClauses.emplace_back(Clause, &RootSigElem);
1989 }
else if (
const auto *Table =
1990 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
1991 assert(UnboundClauses.size() == Table->NumClauses &&
1992 "Number of unbound elements must match the number of clauses");
1993 bool HasAnySampler =
false;
1994 bool HasAnyNonSampler =
false;
1995 uint64_t Offset = 0;
1996 bool IsPrevUnbound =
false;
1997 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
1999 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
2000 HasAnySampler =
true;
2002 HasAnyNonSampler =
true;
2004 if (HasAnySampler && HasAnyNonSampler)
2005 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
2010 if (Clause->NumDescriptors == 0)
2014 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
2016 Offset = Clause->Offset;
2018 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
2019 Offset, Clause->NumDescriptors);
2021 if (IsPrevUnbound && IsAppending)
2022 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
2023 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
2024 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
2027 Offset = RangeBound + 1;
2028 IsPrevUnbound = Clause->NumDescriptors ==
2029 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
2032 uint32_t LowerBound(Clause->Reg.Number);
2033 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
2034 LowerBound, Clause->NumDescriptors);
2036 BindingChecker.trackBinding(
2038 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
2039 LowerBound, UpperBound, ClauseElem);
2041 UnboundClauses.clear();
2045 return BindingChecker.checkOverlap();
2050 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2055 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
2056 if (RS->getSignatureIdent() != Ident) {
2057 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
2061 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
2067 if (
auto *SignatureDecl =
2068 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
2075 llvm::VersionTuple SMVersion =
2080 uint32_t ZMax = 1024;
2081 uint32_t ThreadMax = 1024;
2082 if (IsDXIL && SMVersion.getMajor() <= 4) {
2085 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
2095 diag::err_hlsl_numthreads_argument_oor)
2104 diag::err_hlsl_numthreads_argument_oor)
2113 diag::err_hlsl_numthreads_argument_oor)
2118 if (
X * Y * Z > ThreadMax) {
2119 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
2136 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
2144 if (SpelledArgsCount > 1 &&
2148 uint32_t Preferred = 0;
2149 if (SpelledArgsCount > 2 &&
2153 if (SpelledArgsCount > 2) {
2156 diag::err_attribute_power_of_two_in_range)
2157 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
2162 if (Preferred < Min || Preferred >
Max) {
2164 diag::err_attribute_power_of_two_in_range)
2165 << AL <<
Min <<
Max << Preferred;
2168 }
else if (SpelledArgsCount > 1) {
2171 diag::err_attribute_power_of_two_in_range)
2172 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
2176 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
2179 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
2184 diag::err_attribute_power_of_two_in_range)
2185 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
2190 HLSLWaveSizeAttr *NewAttr =
2227 uint32_t Binding = 0;
2251 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, BuiltIn, &ArgLoc))
2259 if (!llvm::is_contained(SupportedBuiltIns, BuiltIn)) {
2261 llvm::raw_string_ostream OS(Quoted);
2262 if (SupportedBuiltIns.empty())
2265 llvm::interleaveComma(SupportedBuiltIns, OS,
2266 [&](StringRef S) { OS <<
"'" << S <<
"'"; });
2267 Diag(ArgLoc, diag::err_hlsl_vk_builtin_unsupported_value)
2268 << BuiltIn << Quoted;
2277 uint32_t IndexValue(0), ExplicitIndex(0);
2280 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2282 assert(IndexValue > 0 ? ExplicitIndex :
true);
2285 if (Kind == SemanticKind::Invalid) {
2286 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2292 case SemanticKind::RenderTargetArrayIndex:
2293 case SemanticKind::ViewPortArrayIndex:
2294 case SemanticKind::ClipDistance:
2295 case SemanticKind::CullDistance:
2296 case SemanticKind::OutputControlPointID:
2297 case SemanticKind::DomainLocation:
2298 case SemanticKind::GSInstanceID:
2299 case SemanticKind::IsFrontFace:
2300 case SemanticKind::Coverage:
2301 case SemanticKind::InnerCoverage:
2302 case SemanticKind::Depth:
2303 case SemanticKind::DepthLessEqual:
2304 case SemanticKind::DepthGreaterEqual:
2305 case SemanticKind::StencilRef:
2306 case SemanticKind::TessFactor:
2307 case SemanticKind::InsideTessFactor:
2308 case SemanticKind::CullPrimitive:
2309 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2315 D->
addAttr(HLSLParsedSemanticAttr::Create(
2321 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2322 << AL <<
"shader constant in a constant buffer";
2326 uint32_t SubComponent;
2336 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2341 if (IsAggregateTy) {
2342 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2346 if ((Component * 32 + Size) > 128) {
2347 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2352 EltTy = VT->getElementType();
2354 if (Align > 32 && Component == 1) {
2357 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2371 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2374 llvm::Triple::EnvironmentType ShaderType;
2375 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2376 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2377 << AL << Str << ArgLoc;
2391 Expr *SampleCountExpr) {
2392 assert(AttrList.size() &&
"expected list of resource attributes");
2399 HLSLAttributedResourceType::Attributes ResAttrs;
2401 bool HasResourceClass =
false;
2402 bool HasResourceDimension =
false;
2403 for (
const Attr *A : AttrList) {
2408 case attr::HLSLResourceClass: {
2410 if (HasResourceClass) {
2412 ? diag::warn_duplicate_attribute_exact
2413 : diag::warn_duplicate_attribute)
2417 ResAttrs.ResourceClass = RC;
2418 HasResourceClass =
true;
2421 case attr::HLSLResourceDimension: {
2422 llvm::dxil::ResourceDimension RD =
2424 if (HasResourceDimension) {
2426 ? diag::warn_duplicate_attribute_exact
2427 : diag::warn_duplicate_attribute)
2431 ResAttrs.ResourceDimension = RD;
2432 HasResourceDimension =
true;
2435 case attr::HLSLIsROV:
2436 if (ResAttrs.IsROV) {
2440 ResAttrs.IsROV =
true;
2442 case attr::HLSLRawBuffer:
2443 if (ResAttrs.RawBuffer) {
2447 ResAttrs.RawBuffer =
true;
2449 case attr::HLSLIsArray:
2450 if (ResAttrs.IsArray) {
2454 ResAttrs.IsArray =
true;
2456 case attr::HLSLIsMultiSampled:
2457 if (ResAttrs.SampleCountExpr) {
2463 ResAttrs.SampleCountExpr =
2469 case attr::HLSLIsCounter:
2470 if (ResAttrs.IsCounter) {
2474 ResAttrs.IsCounter =
true;
2476 case attr::HLSLContainedType: {
2479 if (!ContainedTy.
isNull()) {
2481 ? diag::warn_duplicate_attribute_exact
2482 : diag::warn_duplicate_attribute)
2491 llvm_unreachable(
"unhandled resource attribute type");
2495 if (!HasResourceClass) {
2496 S.
Diag(AttrList.back()->getRange().getEnd(),
2497 diag::err_hlsl_missing_resource_class);
2502 Wrapped, ContainedTy, ResAttrs);
2504 if (LocInfo && ContainedTyInfo) {
2517 if (!
T->isHLSLResourceType()) {
2518 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2533 AttributeCommonInfo::AS_CXX11, 0, false ,
2538 case ParsedAttr::AT_HLSLResourceClass: {
2539 StringRef Identifier;
2541 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2546 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2547 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2548 <<
"ResourceClass" << Identifier;
2551 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2555 case ParsedAttr::AT_HLSLResourceDimension: {
2556 StringRef Identifier;
2558 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2562 llvm::dxil::ResourceDimension RD;
2563 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2565 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2566 <<
"ResourceDimension" << Identifier;
2569 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2573 case ParsedAttr::AT_HLSLIsROV:
2577 case ParsedAttr::AT_HLSLRawBuffer:
2581 case ParsedAttr::AT_HLSLIsCounter:
2585 case ParsedAttr::AT_HLSLIsArray:
2589 case ParsedAttr::AT_HLSLIsMultiSampled:
2593 case ParsedAttr::AT_HLSLContainedType: {
2595 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2601 assert(TSI &&
"no type source info for attribute argument");
2603 diag::err_incomplete_type))
2605 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2610 llvm_unreachable(
"unhandled HLSL attribute");
2613 HLSLResourcesTypeAttrs.emplace_back(A);
2619 if (!HLSLResourcesTypeAttrs.size())
2625 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2626 const HLSLAttributedResourceType *RT =
2633 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2635 HLSLResourcesTypeAttrs.clear();
2643 auto I = LocsForHLSLAttributedResources.find(RT);
2644 if (I != LocsForHLSLAttributedResources.end()) {
2645 LocInfo = I->second;
2646 LocsForHLSLAttributedResources.erase(I);
2655void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2656 const RecordType *RT) {
2664 "incomplete arrays inside user defined types are not supported");
2673 if (
const HLSLAttributedResourceType *AttrResType =
2674 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2679 Bindings.addDeclBindingInfo(VD, RC);
2680 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2686 collectResourceBindingsOnUserRecordDecl(VD, RT);
2698 bool SpecifiedSpace) {
2699 int RegTypeNum =
static_cast<int>(RegType);
2702 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2703 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2708 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2709 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2710 : ResourceClass::SRV;
2720 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2724 if (
const HLSLAttributedResourceType *AttrResType =
2725 HLSLAttributedResourceType::findHandleTypeOnResource(
2742 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2743 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2748 if (RegType == RegisterType::CBuffer)
2749 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2750 else if (RegType != RegisterType::C)
2751 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2755 if (RegType == RegisterType::C)
2756 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2758 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2768 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2776 bool RegisterTypesDetected[5] = {
false};
2777 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2780 if (HLSLResourceBindingAttr *
attr =
2781 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2784 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2785 int otherRegTypeNum =
static_cast<int>(otherRegType);
2787 diag::err_hlsl_duplicate_register_annotation)
2791 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2799 bool SpecifiedSpace) {
2804 "expecting VarDecl or HLSLBufferDecl");
2824 if (StartSlot > Limit)
2828 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2831 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2832 Count = CAT->
getSize().getZExtValue();
2834 QualType ElemTy = AT->getElementType();
2836 ArrayCount * Count);
2840 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2843 if (ResTy->getAttrs().ResourceClass != ResClass)
2847 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2848 if (EndSlot > Limit)
2852 StartSlot = EndSlot + 1;
2857 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2860 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2863 ResClass, Ctx, ArrayCount))
2870 ResClass, Ctx, ArrayCount))
2885 if (SlotNum > Limit)
2890 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2893 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2902 return (BaseSlot > Limit);
2909 return (SlotNum > Limit);
2912 llvm_unreachable(
"unexpected decl type");
2916 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2918 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
2919 Ty = IAT->getElementType();
2921 diag::err_incomplete_type))
2925 StringRef Slot =
"";
2926 StringRef Space =
"";
2930 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2940 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
2946 SpaceLoc = Loc->
getLoc();
2949 if (Str.starts_with(
"space")) {
2951 SpaceLoc = Loc->
getLoc();
2960 std::optional<unsigned> SlotNum;
2961 unsigned SpaceNum = 0;
2964 if (!Slot.empty()) {
2966 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2969 if (RegType == RegisterType::I) {
2970 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2973 const StringRef SlotNumStr = Slot.substr(1);
2978 if (SlotNumStr.getAsInteger(10, N)) {
2979 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2987 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
2992 SlotNum = (unsigned)N;
2996 if (!Space.starts_with(
"space")) {
2997 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
3000 StringRef SpaceNumStr = Space.substr(5);
3001 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
3002 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
3007 if (SlotNum.has_value())
3012 HLSLResourceBindingAttr *NewAttr =
3013 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
3015 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
3039 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
3041 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
3045 Cur = AT->getModifiedType();
3056 ? attr::HLSLRowMajor
3057 : attr::HLSLColumnMajor;
3061 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
3070 if (ExistingKind == AttrK) {
3071 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
3073 Diag(AL.
getLoc(), diag::note_previous_attribute);
3077 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3078 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
3080 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
3085 if (AttrK == attr::HLSLRowMajor)
3086 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
3087 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
3098 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
3100 if (
T.isNull() ||
T->isDependentType())
3105 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3106 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
3114using llvm::dxil::BarrierMemoryTypeFlag;
3115using llvm::dxil::BarrierSemanticFlag;
3117template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
3118 return llvm::to_underlying(Flag);
3132 bool DiagnoseAvailability;
3159 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
3163 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
3164 unsigned CurrentShaderStageBit;
3169 bool ReportOnlyShaderStageIssues;
3172 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
3173 static_assert(
sizeof(
unsigned) >= 4);
3174 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
3175 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
3176 "ShaderType is too big for this bitmap");
3179 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
3180 CurrentShaderEnvironment = ShaderType;
3181 CurrentShaderStageBit = (1 << bitmapIndex);
3184 void SetUnknownShaderStageContext() {
3185 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
3186 CurrentShaderStageBit = (1 << 31);
3189 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
3190 return CurrentShaderEnvironment;
3193 bool InUnknownShaderStageContext()
const {
3194 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
3198 void AddToScannedFunctions(
const FunctionDecl *FD) {
3199 unsigned &ScannedStages = ScannedDecls[FD];
3200 ScannedStages |= CurrentShaderStageBit;
3203 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
3205 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
3206 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
3209 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
3210 return ScannerStages & CurrentShaderStageBit;
3213 static bool NeverBeenScanned(
unsigned ScannedStages) {
3214 return ScannedStages == 0;
3218 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3219 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3221 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3222 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3223 void DiagnoseBarrierCall(CallExpr *CE);
3225 bool HasVisibleGroup,
bool IsAllMemory);
3227 bool HasKnownStage,
bool IsAllMemory);
3228 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg,
uint64_t SemanticFlags,
3229 bool HasVisibleGroup);
3230 void DiagnoseBarrierScope(Expr *SemanticArg,
uint64_t MemoryFlags,
3234 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3235 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3236 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3237 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3240 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3241 void RunOnFunction(
const FunctionDecl *FD);
3243 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3244 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3246 HandleFunctionOrMethodRef(FD, DRE);
3250 bool VisitMemberExpr(MemberExpr *ME)
override {
3251 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3253 HandleFunctionOrMethodRef(FD, ME);
3257 bool VisitCallExpr(CallExpr *CE)
override {
3258 DiagnoseBarrierCall(CE);
3263uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3264 Expr *MemoryArg,
uint64_t MemoryFlags,
bool HasVisibleGroup,
3267 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3268 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3273 diag::err_hlsl_barrier_flag_requires_group)
3278 return MemoryFlags & ~GroupSharedMemory;
3281uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3282 Expr *MemoryArg,
uint64_t MemoryFlags,
bool HasKnownStage,
3285 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3286 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3291 diag::err_hlsl_barrier_node_memory_requires_node);
3295 return MemoryFlags & ~NodeMemory;
3298void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3299 Expr *SemanticArg,
uint64_t SemanticFlags,
bool HasVisibleGroup) {
3300 if (HasVisibleGroup ||
3301 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3305 diag::err_hlsl_barrier_flag_requires_group)
3306 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3312void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3315 if (ReportOnlyShaderStageIssues)
3319 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3320 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3321 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3323 (MemoryFlags & DeviceScopeMemory) == 0)
3325 diag::err_hlsl_barrier_scope_requires_memory)
3327 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3331 diag::err_hlsl_barrier_scope_requires_memory)
3335void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3337 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3340 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3341 const bool HasKnownStage = !InUnknownShaderStageContext();
3342 const bool HasVisibleGroup =
3343 !HasKnownStage || Stage == llvm::Triple::Compute ||
3344 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3346 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3349 std::optional<llvm::APSInt>
Value =
3353 MemoryFlags =
Value->getZExtValue();
3354 const bool IsAllMemory =
3355 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3357 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3358 HasVisibleGroup, IsAllMemory);
3359 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3360 HasKnownStage, IsAllMemory);
3361 }
else if (!HasVisibleGroup) {
3363 diag::err_hlsl_barrier_resource_requires_group);
3368 std::optional<llvm::APSInt>
Value =
3374 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3377 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3380void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3383 "expected DeclRefExpr or MemberExpr");
3385 if (DiagnoseAvailability)
3386 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3387 CheckDeclAvailability(
3392 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3393 DeclsToScan.push_back(FDWithBody);
3396void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3401 llvm::Triple::EnvironmentType::Library;
3410 DeclContextsToScan.push_back(TU);
3412 while (!DeclContextsToScan.empty()) {
3413 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3414 for (
auto &D : DC->
decls()) {
3421 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3422 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3427 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3432 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3433 if (!IsLibraryShader && FD->
getName() == EntryName) {
3436 diag::err_hlsl_ambiguous_entry_point)
3438 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3444 SetShaderStageContext(ShaderAttr->getType());
3453 for (
const auto *Redecl : FD->
redecls()) {
3454 if (Redecl->isInExportDeclContext()) {
3461 SetUnknownShaderStageContext();
3468 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3475void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3476 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3477 DeclsToScan.push_back(FD);
3479 while (!DeclsToScan.empty()) {
3487 const unsigned ScannedStages = GetScannedStages(FD);
3488 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3491 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3493 AddToScannedFunctions(FD);
3498bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3499 const AvailabilityAttr *AA) {
3504 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3505 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3508 llvm::Triple::EnvironmentType AttrEnv =
3509 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3511 return CurrentEnv == AttrEnv;
3514const AvailabilityAttr *
3515DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3516 AvailabilityAttr
const *PartialMatch =
nullptr;
3520 for (
const auto *A : D->
attrs()) {
3521 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3522 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3523 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3524 StringRef TargetPlatform =
3528 if (AttrPlatform == TargetPlatform) {
3530 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3532 PartialMatch = Avail;
3536 return PartialMatch;
3541void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3542 const AvailabilityAttr *AA,
3561 if (ReportOnlyShaderStageIssues)
3567 if (InUnknownShaderStageContext())
3572 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3573 VersionTuple Introduced = AA->getIntroduced();
3582 llvm::StringRef PlatformName(
3585 llvm::StringRef CurrentEnvStr =
3586 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3588 llvm::StringRef AttrEnvStr =
3589 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3590 bool UseEnvironment = !AttrEnvStr.empty();
3592 if (EnvironmentMatches) {
3593 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3594 <<
Range << D << PlatformName << Introduced.getAsString()
3595 << UseEnvironment << CurrentEnvStr;
3597 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3601 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3602 << D << PlatformName << Introduced.getAsString()
3604 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3611 if (!DefaultCBufferDecls.empty()) {
3614 DefaultCBufferDecls);
3617 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3621 for (
const Decl *VD : DefaultCBufferDecls) {
3622 const HLSLResourceBindingAttr *RBA =
3623 VD->
getAttr<HLSLResourceBindingAttr>();
3624 if (RBA && RBA->hasRegisterSlot() &&
3625 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3632 SemaRef.Consumer.HandleTopLevelDecl(DG);
3634 diagnoseAvailabilityViolations(TU);
3643 "expected member expr to have resource record type or array of them");
3649 const Expr *NonConstIndexExpr =
nullptr;
3652 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3653 if (!NonConstIndexExpr)
3661 diag::err_hlsl_resource_member_array_access_not_constant);
3665 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3666 const Expr *IdxExpr = ASE->getIdx();
3668 NonConstIndexExpr = IdxExpr;
3670 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3671 E = SubME->getBase();
3672 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3673 E = ICE->getSubExpr();
3677 llvm_unreachable(
"unexpected expr type in resource member access");
3686 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3689 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3692 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3696 [[maybe_unused]]
bool LookupSucceeded =
3697 SemaRef.LookupQualifiedName(ConvR, RD);
3698 assert(LookupSucceeded);
3707std::optional<ExprResult>
3710 const HLSLAttributedResourceType *ResTy =
3711 HLSLAttributedResourceType::findHandleTypeOnResource(
3712 BaseType.getTypePtr());
3714 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3715 return std::nullopt;
3717 QualType TemplateType = ResTy->getContainedType();
3721 assert(NamedConversionDecl &&
3722 "Could not find conversion function for ConstantBuffer.");
3723 auto *ConversionDecl =
3726 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3736 const bool DiagnoseAvailability =
3738 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3739 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3740 .RunOnTranslationUnit(TU);
3747 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3750 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3775 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3788 if (!BaseType->isFloat32Type())
3789 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3790 << ArgOrdinal << 5 << 0
3800 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3801 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3802 << ArgOrdinal << 5 << 0
3811 if (!BaseType->isDoubleType()) {
3814 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3815 << ArgOrdinal << PassedType;
3822 unsigned ArgIndex) {
3823 auto *Arg = TheCall->
getArg(ArgIndex);
3825 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3828 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3842 << (ArgIndex + 1) << LValueTy;
3852 if (VecTy->getElementType()->isDoubleType())
3853 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3854 << ArgOrdinal << 1 << 0 << 1
3864 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3865 << ArgOrdinal << 5 << 1
3874 if (VecTy->getElementType()->isUnsignedIntegerType())
3877 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3878 << ArgOrdinal << 4 << 3 << 0
3887 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3888 << ArgOrdinal << 5 << 3
3894 unsigned ArgOrdinal,
unsigned Width) {
3897 ArgTy = VTy->getElementType();
3901 if (ElementBitCount != Width) {
3903 diag::err_integer_incorrect_bit_count)
3904 << Width << ElementBitCount;
3915 else if (
auto *MatTyA =
3918 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
3924 unsigned ArgIndex) {
3933 diag::err_typecheck_expect_scalar_or_vector)
3934 << ArgType << Scalar;
3941 QualType Scalar,
unsigned ArgIndex) {
3952 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
3965 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
3966 << ArgType << Scalar;
3971 unsigned ArgIndex) {
3976 if (!(ArgType->isScalarType() ||
3977 (VTy && VTy->getElementType()->isScalarType()))) {
3979 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
3987 unsigned ArgIndex) {
3990 if (ArgType->isDependentType())
3994 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
3995 ElementType = VectorTy->getElementType();
3997 ElementType = MatrixTy->getElementType();
3999 if (ElementType->isBooleanType())
4002 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
4004 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
4009 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4017 unsigned ArgIndex) {
4019 assert(ArgIndex < TheCall->getNumArgs());
4027 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4053 diag::err_typecheck_convert_incompatible)
4054 << MaskTy << UInt4Ty << 1 << 0 << 0;
4064 diag::err_typecheck_call_different_arg_types)
4083 Arg1ScalarTy = VTy->getElementType();
4087 Arg2ScalarTy = VTy->getElementType();
4090 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4091 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4101 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
4103 diag::err_typecheck_vector_lengths_not_equal)
4109 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
4111 diag::err_typecheck_vector_lengths_not_equal)
4131 Arg1ScalarTy = MTy->getElementType();
4135 Arg2ScalarTy = MTy->getElementType();
4138 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4139 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4144 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
4146 for (
Expr *Arg : {Arg1, Arg2}) {
4149 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
4151 diag::err_typecheck_vector_lengths_not_equal)
4153 << Arg->getSourceRange();
4169 unsigned ArgIndex) {
4174 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
4177 unsigned int ActualDim = 1;
4179 ActualDim = VTy->getNumElements();
4180 IndexTy = VTy->getElementType();
4184 diag::err_typecheck_expect_int)
4190 const HLSLAttributedResourceType *ResTy =
4192 assert(ResTy &&
"Resource argument must be a resource");
4193 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
4195 unsigned int ExpectedDim = 1;
4196 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
4198 (ResAttrs.IsArray ? 1 : 0);
4200 if (ActualDim != ExpectedDim) {
4202 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
4213 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
4217 const HLSLAttributedResourceType *ResTy =
4221 diag::err_typecheck_expect_hlsl_resource)
4225 if (Check && Check(ResTy)) {
4227 diag::err_invalid_hlsl_resource_type)
4237 "expected resource handle type");
4238 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4239 auto MainAttrs = MainResType->getAttrs();
4240 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4241 MainAttrs.IsCounter =
true;
4243 MainResType->getContainedType(),
4254 return "SampleBias";
4256 return "SampleGrad";
4258 return "SampleLevel";
4262 return "SampleCmpLevelZero";
4264 llvm_unreachable(
"Invalid SampleKind");
4274 if (!MD || !MD->getDeclName().isIdentifier())
4281 return MD->getName();
4289 StringRef DefaultName) {
4294 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4321 if (SMVersion >= VersionTuple(6, 7))
4324 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4326 << ContainedType << SMVersion.getAsString();
4331 bool IncludeArraySlice =
true) {
4334 [](
const HLSLAttributedResourceType *ResType) {
4335 return ResType->getAttrs().ResourceDimension ==
4336 llvm::dxil::ResourceDimension::Unknown;
4342 [](
const HLSLAttributedResourceType *ResType) {
4343 return ResType->getAttrs().ResourceClass !=
4344 llvm::hlsl::ResourceClass::Sampler;
4352 unsigned ExpectedDim =
4354 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4383 unsigned NextIdx = 3;
4395 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4399 std::optional<llvm::APSInt> ComponentOpt =
4402 int64_t ComponentVal = ComponentOpt->getSExtValue();
4403 if (ComponentVal != 0) {
4406 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4407 "The component is not in the expected range.");
4409 diag::err_hlsl_gathercmp_invalid_component)
4419 const HLSLAttributedResourceType *ResourceTy =
4422 unsigned ExpectedDim =
4425 &S, TheCall->
getArg(NextIdx),
4431 assert(ResourceTy->hasContainedType() &&
4432 "Expecting a contained type for resource with a dimension "
4434 QualType ReturnType = ResourceTy->getContainedType();
4437 IsCmp ?
"GatherCmp" :
"Gather"))
4442 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4448 ReturnType = VecTy->getElementType();
4461 [](
const HLSLAttributedResourceType *ResType) {
4462 return ResType->getAttrs().ResourceDimension ==
4463 llvm::dxil::ResourceDimension::Unknown;
4473 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4480 unsigned ResourceDim =
4482 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4498 TheCall->
setType(ResourceTy->getContainedType());
4508 [](
const HLSLAttributedResourceType *ResType) {
4509 return !ResType->isMultiSampled();
4518 unsigned ResourceDim =
4520 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4538 TheCall->
setType(ResourceTy->getContainedType());
4543 unsigned MinArgs, MaxArgs;
4571 const HLSLAttributedResourceType *ResourceTy =
4573 unsigned ExpectedDim =
4576 unsigned NextIdx = 3;
4601 &S, TheCall->
getArg(NextIdx),
4614 assert(ResourceTy->hasContainedType() &&
4615 "Expecting a contained type for resource with a dimension "
4617 QualType ReturnType = ResourceTy->getContainedType();
4628 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4645 unsigned MinArgs,
unsigned MaxArgs,
4647 bool ReportsOriginalValue) {
4648 if (MinArgs == MaxArgs) {
4651 }
else if (TheCall->
getNumArgs() < MinArgs) {
4652 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4662 const bool DestIsOK =
4668 diag::err_builtin_invalid_arg_type)
4682 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4698 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4704 const unsigned NumArgs = TheCall->
getNumArgs();
4705 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4716 switch (BuiltinID) {
4717 case Builtin::BI__builtin_hlsl_barrier: {
4718 if (
SemaRef.checkArgCount(TheCall, 2))
4721 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4722 llvm::Triple::dxil) {
4730 std::optional<llvm::APSInt> MemoryFlags =
4734 diag::err_constant_integer_arg_type)
4738 if ((MemoryFlags->getZExtValue() &
4739 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4741 diag::err_hlsl_invalid_barrier_memory_flags);
4745 const HLSLAttributedResourceType *ResTy =
4746 HLSLAttributedResourceType::findHandleTypeOnResource(
4750 diag::err_typecheck_expect_hlsl_resource)
4754 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4756 diag::err_invalid_hlsl_resource_type)
4763 std::optional<llvm::APSInt> SemanticFlags =
4765 if (!SemanticFlags) {
4767 diag::err_constant_integer_arg_type)
4771 if ((SemanticFlags->getZExtValue() &
4772 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4774 diag::err_hlsl_invalid_barrier_semantic_flags);
4781 case Builtin::BI__builtin_hlsl_adduint64: {
4782 if (
SemaRef.checkArgCount(TheCall, 2))
4796 if (NumElementsArg != 2 && NumElementsArg != 4) {
4798 << 1 << 64 << NumElementsArg * 32;
4812 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4813 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4820 QualType ContainedTy = ResourceTy->getContainedType();
4821 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4824 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4829 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4830 if (
SemaRef.checkArgCount(TheCall, 3) ||
4837 "expected pointer type for second argument");
4844 diag::err_invalid_use_of_array_type);
4848 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4851 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4856 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4857 if (
SemaRef.checkArgCount(TheCall, 2) ||
4859 SemaRef.getASTContext().IntTy))
4866 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4867 if (
SemaRef.checkArgCount(TheCall, 3) ||
4870 SemaRef.getASTContext().UnsignedIntTy) ||
4872 SemaRef.getASTContext().UnsignedIntTy) ||
4878 QualType ReturnType = ResourceTy->getContainedType();
4883 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4884 if (
SemaRef.checkArgCount(TheCall, 4) ||
4887 SemaRef.getASTContext().UnsignedIntTy) ||
4889 SemaRef.getASTContext().UnsignedIntTy) ||
4895 "expected pointer type for second argument");
4902 diag::err_invalid_use_of_array_type);
4908 case Builtin::BI__builtin_hlsl_resource_load_level:
4910 case Builtin::BI__builtin_hlsl_resource_load_ms:
4912 case Builtin::BI__builtin_hlsl_resource_sample:
4914 case Builtin::BI__builtin_hlsl_resource_sample_bias:
4916 case Builtin::BI__builtin_hlsl_resource_sample_grad:
4918 case Builtin::BI__builtin_hlsl_resource_sample_level:
4920 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
4922 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
4924 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
4925 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
4927 case Builtin::BI__builtin_hlsl_resource_gather:
4929 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
4931 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
4932 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
4938 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
4939 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4945 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
4946 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
4952 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
4953 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
4959 TheCall->
setType(CounterHandleTy);
4962 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
4963 if (
SemaRef.checkArgCount(TheCall, 2) ||
4966 SemaRef.getASTContext().UnsignedIntTy))
4974 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
4975 if (
SemaRef.checkArgCount(TheCall, 1) ||
4983 TheCall->
setType(CounterHandleTy);
4986 case Builtin::BI__builtin_hlsl_and:
4987 case Builtin::BI__builtin_hlsl_or: {
4988 if (
SemaRef.checkArgCount(TheCall, 2))
5002 case Builtin::BI__builtin_hlsl_asdouble: {
5003 if (
SemaRef.checkArgCount(TheCall, 2))
5007 SemaRef.Context.UnsignedIntTy,
5012 SemaRef.Context.UnsignedIntTy,
5021 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
5022 if (
SemaRef.BuiltinElementwiseTernaryMath(
5028 case Builtin::BI__builtin_hlsl_dot: {
5030 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
5036 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
5037 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
5038 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5048 EltTy = VecTy->getElementType();
5049 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
5062 case Builtin::BI__builtin_hlsl_select: {
5063 if (
SemaRef.checkArgCount(TheCall, 3))
5072 if (VTy && VTy->getElementType()->isBooleanType() &&
5076 if (MTy && MTy->getElementType()->isBooleanType() &&
5081 case Builtin::BI__builtin_hlsl_elementwise_saturate:
5082 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
5083 if (
SemaRef.checkArgCount(TheCall, 1))
5089 diag::err_builtin_invalid_arg_type)
5092 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5096 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
5097 case Builtin::BI__builtin_hlsl_elementwise_frac:
5098 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
5099 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
5100 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
5101 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
5102 if (
SemaRef.checkArgCount(TheCall, 1))
5107 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5111 case Builtin::BI__builtin_hlsl_elementwise_isfinite:
5112 case Builtin::BI__builtin_hlsl_elementwise_isinf:
5113 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
5114 if (
SemaRef.checkArgCount(TheCall, 1))
5119 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5124 case Builtin::BI__builtin_hlsl_mad: {
5125 if (
SemaRef.BuiltinElementwiseTernaryMath(
5131 case Builtin::BI__builtin_hlsl_mul: {
5132 if (
SemaRef.checkArgCount(TheCall, 2))
5142 return VTy->getElementType();
5144 return MTy->getElementType();
5148 QualType EltTy0 = getElemType(Ty0);
5157 if (IsVec0 && IsMat1) {
5160 }
else if (IsMat0 && IsVec1) {
5164 assert(IsMat0 && IsMat1);
5174 case Builtin::BI__builtin_elementwise_fma: {
5175 if (
SemaRef.checkArgCount(TheCall, 3) ||
5190 case Builtin::BI__builtin_hlsl_transpose: {
5191 if (
SemaRef.checkArgCount(TheCall, 1))
5200 << 1 << 3 << 0 << 0 << ArgTy;
5205 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
5209 case Builtin::BI__builtin_hlsl_elementwise_sign: {
5210 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5218 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5219 if (
SemaRef.checkArgCount(TheCall, 1))
5233 unsigned NumElts = VecTy->getNumElements();
5243 case Builtin::BI__builtin_hlsl_wave_active_max:
5244 case Builtin::BI__builtin_hlsl_wave_active_min:
5245 case Builtin::BI__builtin_hlsl_wave_active_sum:
5246 case Builtin::BI__builtin_hlsl_wave_active_product: {
5247 if (
SemaRef.checkArgCount(TheCall, 1))
5260 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5261 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5262 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5263 if (
SemaRef.checkArgCount(TheCall, 1))
5278 (VTy && VTy->getElementType()->isIntegerType()))) {
5280 diag::err_builtin_invalid_arg_type)
5281 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5289 case Builtin::BI__builtin_hlsl_interlocked_add:
5290 case Builtin::BI__builtin_hlsl_interlocked_and:
5291 case Builtin::BI__builtin_hlsl_interlocked_max:
5292 case Builtin::BI__builtin_hlsl_interlocked_min:
5293 case Builtin::BI__builtin_hlsl_interlocked_or:
5294 case Builtin::BI__builtin_hlsl_interlocked_xor:
5300 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5306 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5312 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5318 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5324 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5332 case Builtin::BI__builtin_elementwise_bitreverse: {
5340 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits:
5341 case Builtin::BI__builtin_hlsl_wave_multi_prefix_count_bits: {
5342 bool IsMultiPrefix =
5343 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_count_bits;
5344 if (
SemaRef.checkArgCount(TheCall, IsMultiPrefix ? 2 : 1))
5349 if (!(
ArgType->isScalarType())) {
5351 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5356 if (!(
ArgType->isBooleanType())) {
5358 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5363 if (IsMultiPrefix) {
5371 diag::err_builtin_target_unsupported)
5379 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5380 if (
SemaRef.checkArgCount(TheCall, 2))
5388 diag::err_typecheck_convert_incompatible)
5389 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5402 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5403 if (
SemaRef.checkArgCount(TheCall, 1))
5412 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5413 if (
SemaRef.checkArgCount(TheCall, 0))
5417 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5418 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5419 if (
SemaRef.checkArgCount(TheCall, 1))
5432 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_and:
5433 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_or:
5434 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_xor:
5435 case Builtin::BI__builtin_hlsl_wave_multi_prefix_product:
5436 case Builtin::BI__builtin_hlsl_wave_multi_prefix_sum: {
5437 if (
SemaRef.checkArgCount(TheCall, 2))
5447 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_product ||
5448 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_sum;
5453 diag::err_builtin_invalid_arg_type)
5454 << 1 << (ValueTy->
isMatrixType() ? 3 : 5) << 1 << IsArithmetic
5465 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5466 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5467 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5468 if (
SemaRef.checkArgCount(TheCall, 1))
5480 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5481 if (
SemaRef.checkArgCount(TheCall, 3))
5487 SemaRef.Context.UnsignedIntTy, 1) ||
5489 SemaRef.Context.UnsignedIntTy, 2))
5497 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5498 if (
SemaRef.checkArgCount(TheCall, 1))
5505 case Builtin::BI__builtin_elementwise_acos:
5506 case Builtin::BI__builtin_elementwise_asin:
5507 case Builtin::BI__builtin_elementwise_atan:
5508 case Builtin::BI__builtin_elementwise_atan2:
5509 case Builtin::BI__builtin_elementwise_ceil:
5510 case Builtin::BI__builtin_elementwise_cos:
5511 case Builtin::BI__builtin_elementwise_cosh:
5512 case Builtin::BI__builtin_elementwise_exp:
5513 case Builtin::BI__builtin_elementwise_exp2:
5514 case Builtin::BI__builtin_elementwise_exp10:
5515 case Builtin::BI__builtin_elementwise_floor:
5516 case Builtin::BI__builtin_elementwise_fmod:
5517 case Builtin::BI__builtin_elementwise_log:
5518 case Builtin::BI__builtin_elementwise_log2:
5519 case Builtin::BI__builtin_elementwise_log10:
5520 case Builtin::BI__builtin_elementwise_pow:
5521 case Builtin::BI__builtin_elementwise_roundeven:
5522 case Builtin::BI__builtin_elementwise_sin:
5523 case Builtin::BI__builtin_elementwise_sinh:
5524 case Builtin::BI__builtin_elementwise_sqrt:
5525 case Builtin::BI__builtin_elementwise_tan:
5526 case Builtin::BI__builtin_elementwise_tanh:
5527 case Builtin::BI__builtin_elementwise_trunc: {
5533 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5534 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5535 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5536 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5537 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5542 std::optional<llvm::APSInt> Offset =
5544 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5546 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5552 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5553 if (
SemaRef.checkArgCount(TheCall, 1))
5564 ArgTy = VTy->getElementType();
5567 diag::err_builtin_invalid_arg_type)
5576 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5577 if (
SemaRef.checkArgCount(TheCall, 1))
5592 WorkList.push_back(BaseTy);
5593 while (!WorkList.empty()) {
5595 T =
T.getCanonicalType().getUnqualifiedType();
5596 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5604 for (
uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5605 llvm::append_range(List, ElementFields);
5610 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5611 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5614 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5615 List.insert(List.end(), MT->getNumElementsFlattened(),
5616 MT->getElementType());
5619 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5620 if (RD->isStandardLayout())
5621 RD = RD->getStandardLayoutBaseWithFields();
5625 if (RD->
isUnion() || !RD->isAggregate()) {
5631 for (
const auto *FD : RD->
fields())
5632 if (!FD->isUnnamedBitField())
5633 FieldTypes.push_back(FD->
getType());
5635 std::reverse(FieldTypes.begin(), FieldTypes.end());
5636 llvm::append_range(WorkList, FieldTypes);
5640 if (!RD->isStandardLayout()) {
5642 for (
const auto &
Base : RD->bases())
5643 FieldTypes.push_back(
Base.getType());
5644 std::reverse(FieldTypes.begin(), FieldTypes.end());
5645 llvm::append_range(WorkList, FieldTypes);
5680 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5686 int ArraySize = VT->getNumElements();
5691 QualType ElTy = VT->getElementType();
5695 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5711 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5720 return llvm::equal(T1Types, T2Types,
5722 return SemaRef.IsLayoutCompatible(LHS, RHS);
5731 bool HadError =
false;
5733 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5741 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5742 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5743 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5744 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5746 if (NSpellingIdx != OSpellingIdx) {
5748 diag::err_hlsl_param_qualifier_mismatch)
5749 << NDAttr << NewParam;
5765 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5780 llvm_unreachable(
"HLSL doesn't support pointers.");
5783 llvm_unreachable(
"HLSL doesn't support complex types.");
5785 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5787 llvm_unreachable(
"Should have returned before this");
5797 llvm_unreachable(
"HLSL doesn't support complex types.");
5799 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5804 llvm_unreachable(
"HLSL doesn't support pointers.");
5806 llvm_unreachable(
"Should have returned before this");
5812 llvm_unreachable(
"HLSL doesn't support pointers.");
5815 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5819 llvm_unreachable(
"HLSL doesn't support complex types.");
5822 llvm_unreachable(
"Unhandled scalar cast");
5843 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5849 SrcTy = SrcMatTy->getElementType();
5854 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5855 if (DestTypes[I]->isUnionType())
5887 if (SrcTypes.size() < DestTypes.size())
5890 unsigned SrcSize = SrcTypes.size();
5891 unsigned DstSize = DestTypes.size();
5893 for (I = 0; I < DstSize && I < SrcSize; I++) {
5894 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5902 for (; I < SrcSize; I++) {
5903 if (SrcTypes[I]->isUnionType())
5946 tok::equal, ArgOpV, OpV);
5958 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
5959 "We should not get here without a parameter modifier expression");
5960 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
5967 << Arg << (IsInOut ? 1 : 0);
5971 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
5978 << Arg << (IsInOut ? 1 : 0);
5986 Param->getBeginLoc(), IsInOut);
5994 "Pointer and reference types cannot be inout or out parameters");
5995 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
6011 for (
const auto *FD : RD->
fields()) {
6015 assert(RD->getNumBases() <= 1 &&
6016 "HLSL doesn't support multiple inheritance");
6017 return RD->getNumBases()
6022 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
6023 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
6035 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
6040 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
6046 if (
Decl->getType().hasAddressSpace())
6049 if (
Decl->getType()->isDependentType())
6061 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
6075 llvm::Triple::Vulkan;
6076 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
6077 if (HasDeclaredAPushConstant)
6083 HasDeclaredAPushConstant =
true;
6110class StructBindingContext {
6113 HLSLResourceBindingAttr *RegBindingsAttrs[4];
6114 unsigned RegBindingOffset[4];
6117 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
6118 static_cast<unsigned>(RegisterType::UAV) == 1 &&
6119 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
6120 static_cast<unsigned>(RegisterType::Sampler) == 3,
6121 "unexpected register type values");
6124 HLSLVkBindingAttr *VkBindingAttr;
6125 unsigned VkBindingOffset;
6130 StructBindingContext(
VarDecl *VD) {
6131 for (
unsigned i = 0; i < 4; ++i) {
6132 RegBindingsAttrs[i] =
nullptr;
6133 RegBindingOffset[i] = 0;
6135 VkBindingAttr =
nullptr;
6136 VkBindingOffset = 0;
6142 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
6144 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
6147 RegBindingsAttrs[RegTypeIdx] = RBA;
6152 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
6153 VkBindingAttr = VBA;
6160 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
6161 unsigned Range,
bool HasCounter) {
6162 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
6164 if (VkBindingAttr) {
6165 unsigned Offset = VkBindingOffset;
6166 VkBindingOffset +=
Range;
6167 return HLSLVkBindingAttr::CreateImplicit(
6168 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
6169 VkBindingAttr->getRange());
6172 HLSLResourceBindingAttr *RBA =
6173 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6174 HLSLResourceBindingAttr *NewAttr =
nullptr;
6176 if (RBA && RBA->hasRegisterSlot()) {
6179 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6180 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6182 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6183 StringRef NewSlotNumberStr =
6185 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6186 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6187 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6191 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6192 NewAttr->setBinding(RegType, std::nullopt,
6193 RBA ? RBA->getSpaceNumber() : 0);
6197 NewAttr->setImplicitCounterBindingOrderID(
6206static void createGlobalResourceDeclForStruct(
6208 QualType ResTy, StructBindingContext &BindingCtx) {
6210 "expected resource type or array of resources");
6221 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6222 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6227 const HLSLAttributedResourceType *ResHandleTy =
6228 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6232 Attr *BindingAttr = BindingCtx.createBindingAttr(
6234 ResDecl->
addAttr(BindingAttr);
6235 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6244 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6251static void handleArrayOfStructWithResources(
6253 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6258static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6260 EmbeddedResourceNameBuilder &NameBuilder,
6261 StructBindingContext &BindingCtx) {
6264 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6271 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6285 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6288 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6290 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6292 "resource arrays should have been already handled");
6293 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6302handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6304 EmbeddedResourceNameBuilder &NameBuilder,
6305 StructBindingContext &BindingCtx) {
6313 if (!SubCAT && !ElementRD)
6316 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6319 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6322 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6335void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6336 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6337 StructBindingContext BindingCtx(VD);
6341 "Expected non-resource struct or array type");
6344 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6348 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6349 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6357 if (
SemaRef.RequireCompleteType(
6360 diag::err_typecheck_decl_incomplete_type)) {
6374 DefaultCBufferDecls.push_back(VD);
6379 collectResourceBindingsOnVarDecl(VD);
6381 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6393 processExplicitBindingsOnDecl(VD);
6430 handleGlobalStructOrArrayOfWithResources(VD);
6434 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6443 "expected resource record type");
6459 const char *CreateMethodName;
6461 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6462 :
"__createFromBinding";
6464 CreateMethodName = HasCounter
6465 ?
"__createFromImplicitBindingWithImplicitCounter"
6466 :
"__createFromImplicitBinding";
6471 if (!CreateMethod) {
6476 "create method lookup should always succeed for built-in resource "
6485 Args.push_back(RegSlot);
6493 Args.push_back(OrderId);
6499 Args.push_back(Space);
6503 Args.push_back(RangeSize);
6507 Args.push_back(Index);
6509 StringRef VarName = VD->
getName();
6517 Args.push_back(NameCast);
6525 Args.push_back(CounterId);
6548 SemaRef.CheckCompleteVariableDeclaration(VD);
6554 "expected array of resource records");
6575 lookupMethod(
SemaRef, ResourceDecl,
6576 HasCounter ?
"__createFromBindingWithImplicitCounter"
6577 :
"__createFromBinding",
6581 CreateMethod = lookupMethod(
6583 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6584 :
"__createFromImplicitBinding",
6627std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6628 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6629 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6630 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6631 if (!TrueInfo || !FalseInfo)
6632 return std::nullopt;
6633 if (*TrueInfo != *FalseInfo)
6634 return std::nullopt;
6638 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6647 if (
const auto *AttrResType =
6648 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6650 return Bindings.getDeclBindingInfo(VD, RC);
6657void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6658 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6661 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6666 if (*ExprBinding ==
nullptr)
6669 auto PrevBinding = Assigns.find(VD);
6670 if (PrevBinding == Assigns.end()) {
6672 Assigns.insert({VD, *ExprBinding});
6677 if (*ExprBinding != PrevBinding->second) {
6679 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6681 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6692 "expected LHS to be a resource record or array of resource records");
6693 if (Opc != BO_Assign)
6698 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6706 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6711 trackLocalResource(VD, RHSExpr);
6728void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6730 "expected global variable that contains HLSL resource");
6733 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6734 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6735 ? ResourceClass::CBuffer
6736 : ResourceClass::SRV);
6749 if (
const HLSLAttributedResourceType *AttrResType =
6750 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6751 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6756 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6757 collectResourceBindingsOnUserRecordDecl(VD, RT);
6763void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6766 bool HasBinding =
false;
6767 for (Attr *A : VD->
attrs()) {
6770 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6771 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6774 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6775 if (!RBA || !RBA->hasRegisterSlot())
6780 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6781 "never have an attribute created");
6783 if (RT == RegisterType::C) {
6784 if (Bindings.hasBindingInfoForDecl(VD))
6786 diag::warn_hlsl_user_defined_type_missing_member)
6787 <<
static_cast<int>(RT);
6795 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6800 diag::warn_hlsl_user_defined_type_missing_member)
6801 <<
static_cast<int>(RT);
6809class InitListTransformer {
6813 QualType *DstIt =
nullptr;
6814 Expr **ArgIt =
nullptr;
6820 bool castInitializer(Expr *E) {
6821 assert(DstIt &&
"This should always be something!");
6822 if (DstIt == DestTypes.end()) {
6824 ArgExprs.push_back(E);
6829 DstIt = DestTypes.begin();
6832 Ctx, *DstIt,
false);
6837 ArgExprs.push_back(
Init);
6842 bool buildInitializerListImpl(Expr *E) {
6844 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6845 for (
auto *SubInit :
Init->inits())
6846 if (!buildInitializerListImpl(SubInit))
6856 return castInitializer(E);
6870 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6877 SizeTy, SourceLocation());
6883 if (!castInitializer(ElExpr.
get()))
6888 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6889 unsigned Rows = MTy->getNumRows();
6890 unsigned Cols = MTy->getNumColumns();
6891 QualType ElemTy = MTy->getElementType();
6893 for (
unsigned R = 0;
R < Rows; ++
R) {
6894 for (
unsigned C = 0;
C < Cols; ++
C) {
6907 if (!castInitializer(ElExpr.
get()))
6915 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
6921 SizeTy, SourceLocation());
6926 if (!buildInitializerListImpl(ElExpr.
get()))
6933 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6934 RecordDecls.push_back(RD);
6935 while (RecordDecls.back()->getNumBases()) {
6936 CXXRecordDecl *D = RecordDecls.back();
6938 "HLSL doesn't support multiple inheritance");
6939 RecordDecls.push_back(
6942 while (!RecordDecls.empty()) {
6943 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6944 for (
auto *FD : RD->
fields()) {
6945 if (FD->isUnnamedBitField())
6953 if (!buildInitializerListImpl(Res.
get()))
6961 Expr *generateInitListsImpl(QualType Ty) {
6963 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
6968 llvm::SmallVector<Expr *>
Inits;
6973 if (
auto *ATy = Ty->
getAs<VectorType>()) {
6974 ElTy = ATy->getElementType();
6975 Size = ATy->getNumElements();
6976 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
6977 ElTy = CMTy->getElementType();
6978 Size = CMTy->getNumElementsFlattened();
6981 ElTy = VTy->getElementType();
6982 Size = VTy->getZExtSize();
6985 Inits.push_back(generateInitListsImpl(ElTy));
6988 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
6989 RecordDecls.push_back(RD);
6990 while (RecordDecls.back()->getNumBases()) {
6991 CXXRecordDecl *D = RecordDecls.back();
6993 "HLSL doesn't support multiple inheritance");
6994 RecordDecls.push_back(
6997 while (!RecordDecls.empty()) {
6998 CXXRecordDecl *RD = RecordDecls.pop_back_val();
6999 for (
auto *FD : RD->
fields())
7000 if (!FD->isUnnamedBitField())
7005 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
7006 Inits.back()->getEndLoc(),
false);
7007 NewInit->setType(Ty);
7012 llvm::SmallVector<QualType, 16> DestTypes;
7013 llvm::SmallVector<Expr *, 16> ArgExprs;
7014 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
7015 : S(SemaRef), Ctx(SemaRef.getASTContext()),
7016 Wrap(Entity.
getType()->isIncompleteArrayType()) {
7017 InitTy = Entity.
getType().getNonReferenceType();
7027 DstIt = DestTypes.begin();
7030 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
7032 Expr *generateInitLists() {
7033 assert(!ArgExprs.empty() &&
7034 "Call buildInitializerList to generate argument expressions.");
7035 ArgIt = ArgExprs.begin();
7037 return generateInitListsImpl(InitTy);
7038 llvm::SmallVector<Expr *>
Inits;
7039 while (ArgIt != ArgExprs.end())
7040 Inits.push_back(generateInitListsImpl(InitTy));
7043 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
7044 Inits.back()->getEndLoc(),
false);
7045 llvm::APInt ArySize(64,
Inits.size());
7047 ArraySizeModifier::Normal, 0));
7059 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
7066 if (
const auto *RT = Ty->
getAs<RecordType>()) {
7070 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
7090 if (
Init->getType()->isScalarType())
7093 InitListTransformer ILT(
SemaRef, Entity);
7095 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
7103 Init->setInit(I, E);
7105 if (!ILT.buildInitializerList(E))
7108 size_t ExpectedSize = ILT.DestTypes.size();
7109 size_t ActualSize = ILT.ArgExprs.size();
7110 if (ExpectedSize == 0 && ActualSize == 0)
7117 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7119 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7120 << (int)(ExpectedSize < ActualSize) << InitTy
7121 << ExpectedSize << ActualSize;
7131 assert(ExpectedSize > 0 &&
7132 "The expected size of an incomplete array type must be at least 1.");
7134 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
7142 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7143 if (ExpectedSize != ActualSize) {
7144 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
7145 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7146 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
7153 Init->resizeInits(Ctx, NewInit->getNumInits());
7154 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
7155 Init->updateInit(Ctx, I, NewInit->getInit(I));
7163 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7173 StringRef AccessorName = CompName->
getName();
7174 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7176 unsigned Rows = MT->getNumRows();
7177 unsigned Cols = MT->getNumColumns();
7178 bool IsZeroBasedAccessor =
false;
7179 unsigned ChunkLen = 0;
7180 if (AccessorName.size() < 2)
7182 "length 4 for zero based: \'_mRC\' or "
7183 "length 3 for one-based: \'_RC\' accessor",
7186 if (AccessorName[0] ==
'_') {
7187 if (AccessorName[1] ==
'm') {
7188 IsZeroBasedAccessor =
true;
7195 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7198 if (AccessorName.size() % ChunkLen != 0) {
7199 const llvm::StringRef
Expected = IsZeroBasedAccessor
7200 ?
"zero based: '_mRC' accessor"
7201 :
"one-based: '_RC' accessor";
7206 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7207 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7208 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7210 bool HasRepeated =
false;
7212 unsigned NumComponents = 0;
7213 const char *Begin = AccessorName.data();
7215 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7216 const char *Chunk = Begin + I;
7217 char RowChar = 0, ColChar = 0;
7218 if (IsZeroBasedAccessor) {
7220 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7221 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7223 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7230 if (Chunk[0] !=
'_')
7232 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7239 bool IsDigitsError =
false;
7241 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7245 IsDigitsError =
true;
7249 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7253 IsDigitsError =
true;
7258 unsigned Row = RowChar -
'0';
7259 unsigned Col = ColChar -
'0';
7261 bool HasIndexingError =
false;
7262 if (IsZeroBasedAccessor) {
7264 if (!isZeroBasedIndex(Row)) {
7265 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7267 HasIndexingError =
true;
7269 if (!isZeroBasedIndex(Col)) {
7270 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7272 HasIndexingError =
true;
7276 if (!isOneBasedIndex(Row)) {
7277 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7279 HasIndexingError =
true;
7281 if (!isOneBasedIndex(Col)) {
7282 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7284 HasIndexingError =
true;
7291 if (HasIndexingError)
7297 bool HasBoundsError =
false;
7299 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7301 HasBoundsError =
true;
7304 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7306 HasBoundsError =
true;
7311 unsigned FlatIndex = Row * Cols + Col;
7312 if (Seen[FlatIndex])
7314 Seen[FlatIndex] =
true;
7317 if (NumComponents == 0 || NumComponents > 4) {
7318 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7323 QualType ElemTy = MT->getElementType();
7324 if (NumComponents == 1)
7330 for (Sema::ExtVectorDeclsType::iterator
7334 if ((*I)->getUnderlyingType() == VT)
7345 trackLocalResource(VDecl,
Init);
7347 const HLSLVkConstantIdAttr *ConstIdAttr =
7348 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7355 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7365 int ConstantID = ConstIdAttr->getId();
7366 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7368 ConstIdAttr->getLocation());
7372 if (
C->getType()->getCanonicalTypeUnqualified() !=
7376 Context.getTrivialTypeSourceInfo(
7377 Init->getType(),
Init->getExprLoc()),
7396 if (!Params || Params->
size() != 1)
7409 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7410 if (TTP->hasDefaultArgument()) {
7411 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7414 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7415 if (NTTP->hasDefaultArgument()) {
7416 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7419 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7420 if (TTPD->hasDefaultArgument()) {
7421 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7428 return SemaRef.CheckTemplateIdType(
7430 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.
static StringRef getTriple(const Command &Job)
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 CheckWaveMultiPrefixMask(Sema *S, CallExpr *TheCall)
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)
void handleVkBuiltInAttr(Decl *D, const ParsedAttr &AL)
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.
bool isStructOrArrayOfWithResources(QualType Ty)
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_riscv_nclipru_u32 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