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");
991 HLSLAppliedSemanticAttr *Semantic,
994 if (D->
hasAttr<HLSLVkBuiltInAttr>())
1000 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1001 assert(ShaderAttr &&
"Entry point has no shader attribute");
1002 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1003 SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
1006 case SemanticKind::Position:
1010 return (ST == llvm::Triple::Vertex && !IsInput) ||
1011 (ST == llvm::Triple::Pixel && IsInput);
1012 case SemanticKind::VertexID:
1014 case SemanticKind::InstanceID:
1015 return ST == llvm::Triple::Vertex && IsInput;
1016 case SemanticKind::IsFrontFace:
1017 return ST == llvm::Triple::Pixel && IsInput;
1018 case SemanticKind::ShadingRate:
1023 return (ST == llvm::Triple::Pixel && IsInput) ||
1024 (ST == llvm::Triple::Vertex && !IsInput);
1025 case SemanticKind::Barycentrics:
1026 case SemanticKind::SampleIndex:
1027 case SemanticKind::PrimitiveID:
1028 return ST == llvm::Triple::Pixel && IsInput;
1029 case SemanticKind::StartVertexLocation:
1030 case SemanticKind::StartInstanceLocation:
1031 return ST == llvm::Triple::Vertex && IsInput;
1032 case SemanticKind::ViewID:
1041 const HLSLVkBuiltInAttr *
Attr,
1042 IOType CurrentIOType) {
1047 StringRef BuiltIn =
Attr->getBuiltIn();
1051 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1052 assert(ShaderAttr &&
"Entry point has no shader attribute");
1053 llvm::Triple::EnvironmentType Stage = ShaderAttr->getType();
1054 bool IsIn =
any(CurrentIOType & IOType::In);
1055 bool IsOut =
any(CurrentIOType & IOType::Out);
1057 if (BuiltIn ==
"PointSize") {
1061 bool Is32BitFloat =
T->isSpecificBuiltinType(BuiltinType::Float) ||
1062 (
T->isSpecificBuiltinType(BuiltinType::Half) &&
1071 bool IsPatchConstantOrPrimitive =
1072 any(CurrentIOType & IOType::PatchConstantOrPrimitive);
1074 !IsPatchConstantOrPrimitive &&
1075 ((Stage == llvm::Triple::Vertex && IsOut) ||
1076 Stage == llvm::Triple::Hull || Stage == llvm::Triple::Domain ||
1077 Stage == llvm::Triple::Geometry ||
1078 (Stage == llvm::Triple::Mesh && IsOut));
1080 StringRef IOTypeName = (IsIn && IsOut) ?
"inputs and outputs"
1084 << BuiltIn << llvm::Triple::getEnvironmentTypeName(Stage)
1090bool SemaHLSL::determineActiveSemanticOnScalar(
FunctionDecl *FD,
1093 SemanticInfo &ActiveSemantic,
1094 SemaHLSL::SemanticContext &SC) {
1095 if (ActiveSemantic.Semantic ==
nullptr) {
1096 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1097 if (ActiveSemantic.Semantic)
1098 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1101 if (!ActiveSemantic.Semantic) {
1107 HLSLAppliedSemanticAttr(
getASTContext(), *ActiveSemantic.Semantic,
1108 ActiveSemantic.Semantic->getAttrName()->getName(),
1109 ActiveSemantic.Index.value_or(0));
1114 QualType
T = D == FD ? FD->getReturnType() : D->
getType();
1115 const ConstantArrayType *AT =
1118 Diag(A->getLoc(), diag::err_hlsl_semantic_zero_sized_array)
1119 << A->getAttrName();
1127 if (
const auto *MT = BaseTy->
getAs<ConstantMatrixType>())
1130 : MT->getNumColumns();
1132 checkSemanticAnnotation(FD, D, A, SC, ElementCount);
1135 unsigned Location = ActiveSemantic.Index.value_or(0);
1138 any(SC.CurrentIOType & IOType::In));
1140 if (
const auto *BuiltInAttr = D->
getAttr<HLSLVkBuiltInAttr>())
1145 bool HasVkLocation =
false;
1146 if (
auto *A = D->
getAttr<HLSLVkLocationAttr>()) {
1147 HasVkLocation =
true;
1148 Location = A->getLocation();
1151 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
1152 Diag(D->
getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
1155 SC.UsesExplicitVkLocations = HasVkLocation;
1158 ActiveSemantic.Index = Location + ElementCount;
1160 StringRef BaseName = ActiveSemantic.Semantic->getAttrName()->getName();
1161 std::string LowerName = BaseName.lower();
1162 for (
unsigned I = 0; I < ElementCount; ++I) {
1163 auto [It, Inserted] = SC.ActiveSemantics.try_emplace(
1164 (Twine(LowerName) + Twine(Location + I)).str(), D->
getLocation());
1167 << (BaseName + Twine(Location + I)).str();
1168 Diag(It->second, diag::note_previous_use);
1176bool SemaHLSL::determineActiveSemantic(
FunctionDecl *FD,
1179 SemanticInfo &ActiveSemantic,
1180 SemaHLSL::SemanticContext &SC) {
1181 if (ActiveSemantic.Semantic ==
nullptr) {
1182 ActiveSemantic.Semantic = D->
getAttr<HLSLParsedSemanticAttr>();
1183 if (ActiveSemantic.Semantic)
1184 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1190 const RecordType *RT = dyn_cast<RecordType>(
T);
1192 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
1195 const RecordDecl *RD = RT->getDecl();
1196 for (FieldDecl *Field : RD->
fields()) {
1197 SemanticInfo Info = ActiveSemantic;
1198 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
1199 Diag(
Field->getLocation(), diag::note_hlsl_semantic_used_here) <<
Field;
1202 if (ActiveSemantic.Semantic)
1203 ActiveSemantic = Info;
1210 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1211 assert(ShaderAttr &&
"Entry point has no shader attribute");
1212 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1216 case llvm::Triple::Pixel:
1217 case llvm::Triple::Vertex:
1218 case llvm::Triple::Geometry:
1219 case llvm::Triple::Hull:
1220 case llvm::Triple::Domain:
1221 case llvm::Triple::RayGeneration:
1222 case llvm::Triple::Intersection:
1223 case llvm::Triple::AnyHit:
1224 case llvm::Triple::ClosestHit:
1225 case llvm::Triple::Miss:
1226 case llvm::Triple::Callable:
1227 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
1228 diagnoseAttrStageMismatch(NT, ST,
1229 {llvm::Triple::Compute,
1230 llvm::Triple::Amplification,
1231 llvm::Triple::Mesh});
1234 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1235 diagnoseAttrStageMismatch(WS, ST,
1236 {llvm::Triple::Compute,
1237 llvm::Triple::Amplification,
1238 llvm::Triple::Mesh});
1243 case llvm::Triple::Compute:
1244 case llvm::Triple::Amplification:
1245 case llvm::Triple::Mesh:
1246 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
1248 << llvm::Triple::getEnvironmentTypeName(ST);
1251 if (
const auto *WS = FD->
getAttr<HLSLWaveSizeAttr>()) {
1253 Diag(WS->getLocation(), diag::warn_hlsl_wavesize_unsupported_spirv);
1254 }
else if (Ver < VersionTuple(6, 6)) {
1255 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
1258 }
else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
1261 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
1262 << WS << WS->getSpelledArgsCount() <<
"6.8";
1267 case llvm::Triple::RootSignature:
1268 llvm_unreachable(
"rootsig environment has no function entry point");
1270 llvm_unreachable(
"Unhandled environment in triple");
1273 SemaHLSL::SemanticContext InputSC = {};
1274 InputSC.CurrentIOType = IOType::In;
1275 SemaHLSL::SemanticContext OutputSC = {};
1276 OutputSC.CurrentIOType = IOType::Out;
1279 SemanticInfo ActiveSemantic;
1280 ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();
1281 if (ActiveSemantic.Semantic)
1282 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1286 const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
1287 SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
1291 if (((ST == llvm::Triple::Pixel && (!MA || MA->isAnyIn())) ||
1292 (ST == llvm::Triple::Vertex && MA && MA->isAnyOut())) &&
1293 !checkInterpolationModifiers(Param,
nullptr,
nullptr))
1296 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
1297 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
1302 SemanticInfo ActiveSemantic;
1303 ActiveSemantic.Semantic = FD->
getAttr<HLSLParsedSemanticAttr>();
1304 if (ActiveSemantic.Semantic)
1305 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
1307 if (ST == llvm::Triple::Vertex &&
1308 !checkInterpolationModifiers(FD,
nullptr,
nullptr))
1310 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
1314void SemaHLSL::checkSemanticAnnotation(
1316 const HLSLAppliedSemanticAttr *SemanticAttr,
const SemanticContext &SC,
1317 unsigned ElementCount) {
1318 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
1319 assert(ShaderAttr &&
"Entry point has no shader attribute");
1320 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1323 llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
1324 llvm::hlsl::SemanticInterpretation Interpretation =
1325 llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
1326 if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid) {
1327 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
1333 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary) {
1334 diagnoseSemanticType(Param, SemanticAttr, SemanticKind::Arbitrary);
1338 diagnoseSystemSemanticIndex(SemanticAttr, Kind, ElementCount);
1339 diagnoseSemanticType(Param, SemanticAttr, Kind);
1340 diagnoseSemanticShaderModel(SemanticAttr, Kind);
1343void SemaHLSL::diagnoseSemanticShaderModel(
const HLSLAppliedSemanticAttr *A,
1346 if (!Triple.isDXIL())
1350 case SemanticKind::Barycentrics:
1351 case SemanticKind::ViewID:
1352 if (Triple.getOSVersion() < VersionTuple(6, 1))
1353 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1354 << A->getAttrName() <<
"6.1";
1356 case SemanticKind::ShadingRate:
1357 if (Triple.getOSVersion() < VersionTuple(6, 4))
1358 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1359 << A->getAttrName() <<
"6.4";
1361 case SemanticKind::StartVertexLocation:
1362 case SemanticKind::StartInstanceLocation:
1363 if (Triple.getOSVersion() < VersionTuple(6, 8))
1364 Diag(A->getLoc(), diag::err_hlsl_semantic_in_wrong_shader_model)
1365 << A->getAttrName() <<
"6.8";
1372void SemaHLSL::diagnoseSystemSemanticIndex(
const HLSLAppliedSemanticAttr *A,
1374 unsigned ElementCount) {
1375 assert(Kind != SemanticKind::Invalid && Kind != SemanticKind::Arbitrary &&
1376 "expected a recognized system semantic");
1377 assert(ElementCount > 0 &&
"a semantic covers at least one element");
1380 uint32_t FirstIndex = A->getSemanticIndex();
1382 constexpr uint32_t MaxSemanticIndex = std::numeric_limits<uint32_t>::max();
1383 if (LastIndex > MaxSemanticIndex) {
1384 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1385 << A->getAttrName() << LastIndex << MaxSemanticIndex;
1393 case SemanticKind::ClipDistance:
1394 case SemanticKind::CullDistance:
1396 case SemanticKind::Target: {
1397 constexpr unsigned MaxTargetIndex = 7;
1398 if (LastIndex > MaxTargetIndex)
1399 Diag(A->getLoc(), diag::err_hlsl_semantic_index_out_of_range)
1400 << A->getAttrName() << LastIndex << MaxTargetIndex;
1404 Diag(A->getLoc(), diag::err_hlsl_semantic_indexing_not_supported)
1405 << A->getAttrName();
1412 return VT->getElementType();
1415 return MT->getElementType();
1421 return VT->getNumElements();
1442void SemaHLSL::diagnoseSemanticType(
const Decl *D,
1443 const HLSLAppliedSemanticAttr *A,
1445 assert(Kind != SemanticKind::Invalid &&
"expected a valid semantic");
1449 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
1455 T =
T.getNonReferenceType();
1458 QualType DeclaredTy =
T;
1460 T = AT->getElementType();
1468 case SemanticKind::Barycentrics:
1470 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1471 << A->getAttrName() << 2 << 3
1474 case SemanticKind::DispatchThreadID:
1475 case SemanticKind::GroupID:
1476 case SemanticKind::GroupThreadID:
1478 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1479 << A->getAttrName() << 1 << 3
1482 case SemanticKind::StartVertexLocation:
1483 case SemanticKind::StartInstanceLocation:
1484 case SemanticKind::ViewID:
1487 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1488 << A->getAttrName() << 0 << 1 << 1
1491 case SemanticKind::GroupIndex:
1493 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1494 << A->getAttrName() << 0 << 1 << 1
1497 case SemanticKind::VertexID:
1499 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1500 << A->getAttrName() << 0 << 1
1503 case SemanticKind::Position:
1504 case SemanticKind::Target:
1506 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1507 << A->getAttrName() << 1 << 4
1510 case SemanticKind::SampleIndex:
1511 case SemanticKind::PrimitiveID:
1515 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1516 << A->getAttrName() << 0 << 1
1519 case SemanticKind::InstanceID:
1520 case SemanticKind::ShadingRate:
1527 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1528 << A->getAttrName() << 0 << 1
1530 (IsSPIRV ? 4 : 3) << DeclaredTy;
1532 case SemanticKind::IsFrontFace:
1537 Diag(A->getLoc(), diag::err_hlsl_semantic_invalid_type)
1538 << A->getAttrName() << 0 << 1
1552 Diag(A->getLoc(), diag::err_hlsl_semantic_64bit_type)
1553 << A->getAttrName() << DeclaredTy;
1556void SemaHLSL::diagnoseAttrStageMismatch(
1557 const Attr *A, llvm::Triple::EnvironmentType Stage,
1558 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {
1559 SmallVector<StringRef, 8> StageStrings;
1560 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1561 [](llvm::Triple::EnvironmentType ST) {
1563 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1565 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1566 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1567 << (AllowedStages.size() != 1) <<
join(StageStrings,
", ");
1570void SemaHLSL::diagnoseSemanticStageMismatch(
1571 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1574 ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
1575 auto It = llvm::find_if(Allowed, [&Stage](
const SemanticStageInfo &Info) {
1576 return Info.Stage == Stage;
1579 StringRef CurrentIOTypeName =
"patch constants or primitives";
1580 if (
any(CurrentIOType & IOType::In))
1581 CurrentIOTypeName =
"inputs";
1582 else if (
any(CurrentIOType & IOType::Out))
1583 CurrentIOTypeName =
"outputs";
1586 if (It == Allowed.end()) {
1587 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1588 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1589 << CurrentIOTypeName;
1593 IOType AllowedIOTypes = It->AllowedIOTypesMask;
1594 if (!(AllowedIOTypes & CurrentIOType)) {
1595 Diag(A->
getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1596 << A->
getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1597 << CurrentIOTypeName;
1602template <CastKind Kind>
1605 Ty = VTy->getElementType();
1610template <CastKind Kind>
1622 if (LHSFloat && RHSFloat) {
1650 if (LHSSigned == RHSSigned) {
1651 if (IsCompAssign || IntOrder >= 0)
1659 if (IntOrder != (LHSSigned ? 1 : -1)) {
1660 if (IsCompAssign || RHSSigned)
1669 if (IsCompAssign || LHSSigned)
1696 return CK_FloatingCast;
1698 return CK_IntegralCast;
1700 return CK_IntegralToFloating;
1702 return CK_FloatingToIntegral;
1708 bool IsCompAssign) {
1715 if (!LVecTy && IsCompAssign) {
1717 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), RElTy, CK_HLSLVectorTruncation);
1719 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1721 RHS =
SemaRef.ImpCastExprToType(RHS.
get(), LHSType,
1726 unsigned EndSz = std::numeric_limits<unsigned>::max();
1729 LSz = EndSz = LVecTy->getNumElements();
1732 assert(EndSz != std::numeric_limits<unsigned>::max() &&
1733 "one of the above should have had a value");
1737 if (IsCompAssign && LSz != EndSz) {
1739 diag::err_hlsl_vector_compound_assignment_truncation)
1740 << LHSType << RHSType;
1746 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1751 if (!IsCompAssign && !LVecTy)
1755 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1756 return Ctx.getCommonSugaredType(LHSType, RHSType);
1764 LElTy, RElTy, IsCompAssign);
1767 "HLSL Vectors can only contain integer or floating point types");
1769 LElTy, RElTy, IsCompAssign);
1774 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1775 "Called with non-logical operator");
1777 llvm::raw_svector_ostream OS(Buff);
1779 StringRef NewFnName = Opc == BO_LOr ?
"or" :
"and";
1780 OS << NewFnName <<
"(";
1790std::pair<IdentifierInfo *, bool>
1793 std::string IdStr =
"__hlsl_rootsig_decl_" + std::to_string(Hash);
1800 return {DeclIdent,
Found};
1811 for (
auto &RootSigElement : RootElements)
1812 Elements.push_back(RootSigElement.getElement());
1816 DeclIdent,
SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1818 SignatureDecl->setImplicit();
1824 if (RootSigOverrideIdent) {
1827 if (
SemaRef.LookupQualifiedName(R, DC))
1828 return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());
1836struct PerVisibilityBindingChecker {
1839 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1843 llvm::dxbc::ShaderVisibility Vis;
1848 PerVisibilityBindingChecker(
SemaHLSL *S) : S(S) {}
1850 void trackBinding(llvm::dxbc::ShaderVisibility
Visibility,
1851 llvm::dxil::ResourceClass RC,
uint32_t Space,
1853 const hlsl::RootSignatureElement *Elem) {
1855 assert(BuilderIndex < Builders.size() &&
1856 "Not enough builders for visibility type");
1857 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1858 static_cast<const void *
>(Elem));
1860 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1861 "'All' visibility must come first");
1862 if (
Visibility == llvm::dxbc::ShaderVisibility::All)
1863 for (
size_t I = 1, E = Builders.size(); I < E; ++I)
1864 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1865 static_cast<const void *
>(Elem));
1867 ElemInfoMap.push_back({Elem,
Visibility,
false});
1870 ElemInfo &
getInfo(
const hlsl::RootSignatureElement *Elem) {
1871 auto It = llvm::lower_bound(
1873 [](
const auto &LHS,
const auto &RHS) {
return LHS.Elem < RHS; });
1874 assert(It->Elem == Elem &&
"Element not in map");
1878 bool checkOverlap() {
1879 llvm::sort(ElemInfoMap, [](
const auto &LHS,
const auto &RHS) {
1880 return LHS.Elem < RHS.Elem;
1883 bool HadOverlap =
false;
1885 using llvm::hlsl::BindingInfoBuilder;
1886 auto ReportOverlap = [
this,
1887 &HadOverlap](
const BindingInfoBuilder &Builder,
1888 const llvm::hlsl::Binding &Reported) {
1892 static_cast<const hlsl::RootSignatureElement *
>(Reported.Cookie);
1893 const llvm::hlsl::Binding &
Previous = Builder.findOverlapping(Reported);
1894 const auto *PrevElem =
1895 static_cast<const hlsl::RootSignatureElement *
>(
Previous.Cookie);
1897 ElemInfo &Info =
getInfo(Elem);
1902 Info.Diagnosed =
true;
1904 ElemInfo &PrevInfo =
getInfo(PrevElem);
1905 llvm::dxbc::ShaderVisibility CommonVis =
1906 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1909 this->S->
Diag(Elem->
getLocation(), diag::err_hlsl_resource_range_overlap)
1910 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1911 << Reported.isUnbounded() << Reported.UpperBound
1916 this->S->
Diag(PrevElem->getLocation(),
1917 diag::note_hlsl_resource_range_here);
1920 for (BindingInfoBuilder &Builder : Builders)
1921 Builder.calculateBindingInfo(ReportOverlap);
1941 bool HadError =
false;
1942 auto ReportError = [
this, &HadError](
SourceLocation Loc, uint32_t LowerBound,
1943 uint32_t UpperBound) {
1945 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1946 << LowerBound << UpperBound;
1953 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1954 << llvm::formatv(
"{0:f}", LowerBound).sstr<6>()
1955 << llvm::formatv(
"{0:f}", UpperBound).sstr<6>();
1958 auto VerifyRegister = [ReportError](
SourceLocation Loc, uint32_t Register) {
1959 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1960 ReportError(Loc, 0, 0xfffffffe);
1963 auto VerifySpace = [ReportError](
SourceLocation Loc, uint32_t Space) {
1964 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1965 ReportError(Loc, 0, 0xffffffef);
1968 const uint32_t Version =
1969 llvm::to_underlying(
SemaRef.getLangOpts().HLSLRootSigVer);
1970 const uint32_t VersionEnum = Version - 1;
1971 auto ReportFlagError = [
this, &HadError, VersionEnum](
SourceLocation Loc) {
1973 this->
Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1980 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
1981 if (
const auto *Descriptor =
1982 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
1983 VerifyRegister(Loc, Descriptor->Reg.Number);
1984 VerifySpace(Loc, Descriptor->Space);
1986 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1988 ReportFlagError(Loc);
1989 }
else if (
const auto *Constants =
1990 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
1991 VerifyRegister(Loc, Constants->Reg.Number);
1992 VerifySpace(Loc, Constants->Space);
1993 }
else if (
const auto *Sampler =
1994 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
1995 VerifyRegister(Loc, Sampler->Reg.Number);
1996 VerifySpace(Loc, Sampler->Space);
1999 "By construction, parseFloatParam can't produce a NaN from a "
2000 "float_literal token");
2002 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
2003 ReportError(Loc, 0, 16);
2004 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
2005 ReportFloatError(Loc, -16.f, 15.99f);
2006 }
else if (
const auto *Clause =
2007 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
2009 VerifyRegister(Loc, Clause->Reg.Number);
2010 VerifySpace(Loc, Clause->Space);
2012 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
2016 ReportError(Loc, 1, 0xfffffffe);
2019 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
2021 ReportFlagError(Loc);
2025 PerVisibilityBindingChecker BindingChecker(
this);
2026 SmallVector<std::pair<
const llvm::hlsl::rootsig::DescriptorTableClause *,
2031 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.
getElement();
2032 if (
const auto *Descriptor =
2033 std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
2034 uint32_t LowerBound(Descriptor->Reg.Number);
2035 uint32_t UpperBound(LowerBound);
2037 BindingChecker.trackBinding(
2038 Descriptor->Visibility,
2039 static_cast<llvm::dxil::ResourceClass
>(Descriptor->Type),
2040 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
2041 }
else if (
const auto *Constants =
2042 std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
2043 uint32_t LowerBound(Constants->Reg.Number);
2044 uint32_t UpperBound(LowerBound);
2046 BindingChecker.trackBinding(
2047 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
2048 Constants->Space, LowerBound, UpperBound, &RootSigElem);
2049 }
else if (
const auto *Sampler =
2050 std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
2051 uint32_t LowerBound(Sampler->Reg.Number);
2052 uint32_t UpperBound(LowerBound);
2054 BindingChecker.trackBinding(
2055 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
2056 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
2057 }
else if (
const auto *Clause =
2058 std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
2061 UnboundClauses.emplace_back(Clause, &RootSigElem);
2062 }
else if (
const auto *Table =
2063 std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
2064 assert(UnboundClauses.size() == Table->NumClauses &&
2065 "Number of unbound elements must match the number of clauses");
2066 bool HasAnySampler =
false;
2067 bool HasAnyNonSampler =
false;
2068 uint64_t Offset = 0;
2069 bool IsPrevUnbound =
false;
2070 for (
const auto &[Clause, ClauseElem] : UnboundClauses) {
2072 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
2073 HasAnySampler =
true;
2075 HasAnyNonSampler =
true;
2077 if (HasAnySampler && HasAnyNonSampler)
2078 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
2083 if (Clause->NumDescriptors == 0)
2087 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
2089 Offset = Clause->Offset;
2091 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
2092 Offset, Clause->NumDescriptors);
2094 if (IsPrevUnbound && IsAppending)
2095 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
2096 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
2097 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
2100 Offset = RangeBound + 1;
2101 IsPrevUnbound = Clause->NumDescriptors ==
2102 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
2105 uint32_t LowerBound(Clause->Reg.Number);
2106 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
2107 LowerBound, Clause->NumDescriptors);
2109 BindingChecker.trackBinding(
2111 static_cast<llvm::dxil::ResourceClass
>(Clause->Type), Clause->Space,
2112 LowerBound, UpperBound, ClauseElem);
2114 UnboundClauses.clear();
2118 return BindingChecker.checkOverlap();
2123 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2128 if (
auto *RS = D->
getAttr<RootSignatureAttr>()) {
2129 if (RS->getSignatureIdent() != Ident) {
2130 Diag(AL.
getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
2134 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact) << RS;
2140 if (
auto *SignatureDecl =
2141 dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
2148 llvm::VersionTuple SMVersion =
2153 uint32_t ZMax = 1024;
2154 uint32_t ThreadMax = 1024;
2155 if (IsDXIL && SMVersion.getMajor() <= 4) {
2158 }
else if (IsDXIL && SMVersion.getMajor() == 5) {
2168 diag::err_hlsl_numthreads_argument_oor)
2177 diag::err_hlsl_numthreads_argument_oor)
2186 diag::err_hlsl_numthreads_argument_oor)
2191 if (
X * Y * Z > ThreadMax) {
2192 Diag(AL.
getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
2209 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
2217 if (SpelledArgsCount > 1 &&
2221 uint32_t Preferred = 0;
2222 if (SpelledArgsCount > 2 &&
2226 if (SpelledArgsCount > 2) {
2229 diag::err_attribute_power_of_two_in_range)
2230 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
2235 if (Preferred < Min || Preferred >
Max) {
2237 diag::err_attribute_power_of_two_in_range)
2238 << AL <<
Min <<
Max << Preferred;
2241 }
else if (SpelledArgsCount > 1) {
2244 diag::err_attribute_power_of_two_in_range)
2245 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Max;
2249 Diag(AL.
getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
2252 Diag(AL.
getLoc(), diag::warn_attr_min_eq_max) << AL;
2257 diag::err_attribute_power_of_two_in_range)
2258 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize <<
Min;
2263 HLSLWaveSizeAttr *NewAttr =
2300 uint32_t Binding = 0;
2318 if (
const auto *BuiltIn = D->
getAttr<HLSLVkBuiltInAttr>()) {
2319 Diag(AL.
getLoc(), diag::err_attributes_are_not_compatible)
2322 BuiltIn->isRegularKeywordAttribute());
2323 Diag(BuiltIn->getLocation(), diag::note_conflicting_attribute);
2333 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, BuiltIn, &ArgLoc))
2336 static constexpr StringRef SupportedBuiltIns[] = {
2341 if (!llvm::is_contained(SupportedBuiltIns, BuiltIn)) {
2343 llvm::raw_string_ostream OS(Quoted);
2344 llvm::interleaveComma(SupportedBuiltIns, OS,
2345 [&](StringRef S) { OS <<
"'" << S <<
"'"; });
2346 Diag(ArgLoc, diag::err_hlsl_vk_builtin_unsupported_value)
2347 << BuiltIn << Quoted;
2352 if (
const auto *Location = D->
getAttr<HLSLVkLocationAttr>()) {
2353 Diag(AL.
getLoc(), diag::err_attributes_are_not_compatible)
2356 Location->isRegularKeywordAttribute());
2357 Diag(Location->getLoc(), diag::note_conflicting_attribute);
2365 uint32_t IndexValue(0), ExplicitIndex(0);
2368 assert(0 &&
"HLSLUnparsedSemantic is expected to have 2 int arguments.");
2370 assert(IndexValue > 0 ? ExplicitIndex :
true);
2373 if (Kind == SemanticKind::Invalid) {
2374 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2380 case SemanticKind::RenderTargetArrayIndex:
2381 case SemanticKind::ViewPortArrayIndex:
2382 case SemanticKind::ClipDistance:
2383 case SemanticKind::CullDistance:
2384 case SemanticKind::OutputControlPointID:
2385 case SemanticKind::DomainLocation:
2386 case SemanticKind::GSInstanceID:
2387 case SemanticKind::Coverage:
2388 case SemanticKind::InnerCoverage:
2389 case SemanticKind::Depth:
2390 case SemanticKind::DepthLessEqual:
2391 case SemanticKind::DepthGreaterEqual:
2392 case SemanticKind::StencilRef:
2393 case SemanticKind::TessFactor:
2394 case SemanticKind::InsideTessFactor:
2395 case SemanticKind::CullPrimitive:
2396 Diag(AL.
getLoc(), diag::err_hlsl_unknown_semantic) << AL;
2402 D->
addAttr(HLSLParsedSemanticAttr::Create(
2408 Diag(AL.
getLoc(), diag::err_hlsl_attr_invalid_ast_node)
2409 << AL <<
"shader constant in a constant buffer";
2413 uint32_t SubComponent;
2423 bool IsAggregateTy = (
T->isArrayType() ||
T->isStructureType());
2428 if (IsAggregateTy) {
2429 Diag(AL.
getLoc(), diag::err_hlsl_invalid_register_or_packoffset);
2433 if ((Component * 32 + Size) > 128) {
2434 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
2439 EltTy = VT->getElementType();
2441 if (Align > 32 && Component == 1) {
2444 Diag(AL.
getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
2458 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
2461 llvm::Triple::EnvironmentType ShaderType;
2462 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
2463 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
2464 << AL << Str << ArgLoc;
2478 Expr *SampleCountExpr) {
2479 assert(AttrList.size() &&
"expected list of resource attributes");
2486 HLSLAttributedResourceType::Attributes ResAttrs;
2488 bool HasResourceClass =
false;
2489 bool HasResourceDimension =
false;
2490 for (
const Attr *A : AttrList) {
2495 case attr::HLSLResourceClass: {
2497 if (HasResourceClass) {
2499 ? diag::warn_duplicate_attribute_exact
2500 : diag::warn_duplicate_attribute)
2504 ResAttrs.ResourceClass = RC;
2505 HasResourceClass =
true;
2508 case attr::HLSLResourceDimension: {
2509 llvm::dxil::ResourceDimension RD =
2511 if (HasResourceDimension) {
2513 ? diag::warn_duplicate_attribute_exact
2514 : diag::warn_duplicate_attribute)
2518 ResAttrs.ResourceDimension = RD;
2519 HasResourceDimension =
true;
2522 case attr::HLSLIsROV:
2523 if (ResAttrs.IsROV) {
2527 ResAttrs.IsROV =
true;
2529 case attr::HLSLRawBuffer:
2530 if (ResAttrs.RawBuffer) {
2534 ResAttrs.RawBuffer =
true;
2536 case attr::HLSLIsArray:
2537 if (ResAttrs.IsArray) {
2541 ResAttrs.IsArray =
true;
2543 case attr::HLSLIsMultiSampled:
2544 if (ResAttrs.SampleCountExpr) {
2550 ResAttrs.SampleCountExpr =
2556 case attr::HLSLIsCounter:
2557 if (ResAttrs.IsCounter) {
2561 ResAttrs.IsCounter =
true;
2563 case attr::HLSLContainedType: {
2566 if (!ContainedTy.
isNull()) {
2568 ? diag::warn_duplicate_attribute_exact
2569 : diag::warn_duplicate_attribute)
2578 llvm_unreachable(
"unhandled resource attribute type");
2582 if (!HasResourceClass) {
2583 S.
Diag(AttrList.back()->getRange().getEnd(),
2584 diag::err_hlsl_missing_resource_class);
2589 Wrapped, ContainedTy, ResAttrs);
2591 if (LocInfo && ContainedTyInfo) {
2604 if (!
T->isHLSLResourceType()) {
2605 Diag(AL.
getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2620 AttributeCommonInfo::AS_CXX11, 0, false ,
2625 case ParsedAttr::AT_HLSLResourceClass: {
2626 StringRef Identifier;
2628 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2633 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2634 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2635 <<
"ResourceClass" << Identifier;
2638 A = HLSLResourceClassAttr::Create(
getASTContext(), RC, ACI);
2642 case ParsedAttr::AT_HLSLResourceDimension: {
2643 StringRef Identifier;
2645 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Identifier, &ArgLoc))
2649 llvm::dxil::ResourceDimension RD;
2650 if (!HLSLResourceDimensionAttr::ConvertStrToResourceDimension(Identifier,
2652 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2653 <<
"ResourceDimension" << Identifier;
2656 A = HLSLResourceDimensionAttr::Create(
getASTContext(), RD, ACI);
2660 case ParsedAttr::AT_HLSLIsROV:
2664 case ParsedAttr::AT_HLSLRawBuffer:
2668 case ParsedAttr::AT_HLSLIsCounter:
2672 case ParsedAttr::AT_HLSLIsArray:
2676 case ParsedAttr::AT_HLSLIsMultiSampled:
2680 case ParsedAttr::AT_HLSLContainedType: {
2682 Diag(AL.
getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2688 assert(TSI &&
"no type source info for attribute argument");
2690 diag::err_incomplete_type))
2692 A = HLSLContainedTypeAttr::Create(
getASTContext(), TSI, ACI);
2697 llvm_unreachable(
"unhandled HLSL attribute");
2700 HLSLResourcesTypeAttrs.emplace_back(A);
2706 if (!HLSLResourcesTypeAttrs.size())
2712 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2713 const HLSLAttributedResourceType *RT =
2720 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2722 HLSLResourcesTypeAttrs.clear();
2730 auto I = LocsForHLSLAttributedResources.find(RT);
2731 if (I != LocsForHLSLAttributedResources.end()) {
2732 LocInfo = I->second;
2733 LocsForHLSLAttributedResources.erase(I);
2742void SemaHLSL::collectResourceBindingsOnUserRecordDecl(
const VarDecl *VD,
2743 const RecordType *RT) {
2751 "incomplete arrays inside user defined types are not supported");
2760 if (
const HLSLAttributedResourceType *AttrResType =
2761 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2766 Bindings.addDeclBindingInfo(VD, RC);
2767 }
else if (
const RecordType *RT = dyn_cast<RecordType>(Ty)) {
2773 collectResourceBindingsOnUserRecordDecl(VD, RT);
2785 bool SpecifiedSpace) {
2786 int RegTypeNum =
static_cast<int>(RegType);
2789 if (D->
hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
2790 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2795 if (
HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {
2796 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2797 : ResourceClass::SRV;
2807 assert(
isa<VarDecl>(D) &&
"D is expected to be VarDecl or HLSLBufferDecl");
2811 if (
const HLSLAttributedResourceType *AttrResType =
2812 HLSLAttributedResourceType::findHandleTypeOnResource(
2829 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2830 S.
Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2835 if (RegType == RegisterType::CBuffer)
2836 S.
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2837 else if (RegType != RegisterType::C)
2838 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2842 if (RegType == RegisterType::C)
2843 S.
Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2845 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2855 S.
Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2863 bool RegisterTypesDetected[5] = {
false};
2864 RegisterTypesDetected[
static_cast<int>(regType)] =
true;
2867 if (HLSLResourceBindingAttr *
attr =
2868 dyn_cast<HLSLResourceBindingAttr>(*it)) {
2871 if (RegisterTypesDetected[
static_cast<int>(otherRegType)]) {
2872 int otherRegTypeNum =
static_cast<int>(otherRegType);
2874 diag::err_hlsl_duplicate_register_annotation)
2878 RegisterTypesDetected[
static_cast<int>(otherRegType)] =
true;
2886 bool SpecifiedSpace) {
2891 "expecting VarDecl or HLSLBufferDecl");
2911 if (StartSlot > Limit)
2915 if (
const auto *AT = dyn_cast<ArrayType>(
T)) {
2918 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
2919 Count = CAT->
getSize().getZExtValue();
2921 QualType ElemTy = AT->getElementType();
2923 ArrayCount * Count);
2927 if (
auto ResTy = dyn_cast<HLSLAttributedResourceType>(
T)) {
2930 if (ResTy->getAttrs().ResourceClass != ResClass)
2934 uint64_t EndSlot = StartSlot + ArrayCount - 1;
2935 if (EndSlot > Limit)
2939 StartSlot = EndSlot + 1;
2944 if (
const auto *RT = dyn_cast<RecordType>(
T)) {
2947 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2950 ResClass, Ctx, ArrayCount))
2957 ResClass, Ctx, ArrayCount))
2972 if (SlotNum > Limit)
2977 if (RegTy == RegisterType::C || RegTy == RegisterType::I)
2980 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
2989 return (BaseSlot > Limit);
2996 return (SlotNum > Limit);
2999 llvm_unreachable(
"unexpected decl type");
3003 if (
VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {
3005 if (
const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))
3006 Ty = IAT->getElementType();
3008 diag::err_incomplete_type))
3012 StringRef Slot =
"";
3013 StringRef Space =
"";
3017 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
3027 Diag(AL.
getLoc(), diag::err_attribute_argument_type)
3033 SpaceLoc = Loc->
getLoc();
3036 if (Str.starts_with(
"space")) {
3038 SpaceLoc = Loc->
getLoc();
3047 std::optional<unsigned> SlotNum;
3048 unsigned SpaceNum = 0;
3051 if (!Slot.empty()) {
3053 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
3056 if (RegType == RegisterType::I) {
3057 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
3060 const StringRef SlotNumStr = Slot.substr(1);
3065 if (SlotNumStr.getAsInteger(10, N)) {
3066 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
3074 Diag(SlotLoc, diag::err_hlsl_register_number_too_large);
3079 SlotNum = (unsigned)N;
3083 if (!Space.starts_with(
"space")) {
3084 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
3087 StringRef SpaceNumStr = Space.substr(5);
3088 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
3089 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
3094 if (SlotNum.has_value())
3099 HLSLResourceBindingAttr *NewAttr =
3100 HLSLResourceBindingAttr::Create(
getASTContext(), Slot, Space, AL);
3102 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
3126 while (
const auto *AT = Cur->
getAs<AttributedType>()) {
3128 if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
3132 Cur = AT->getModifiedType();
3143 ? attr::HLSLRowMajor
3144 : attr::HLSLColumnMajor;
3148 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
3157 if (ExistingKind == AttrK) {
3158 Diag(AL.
getLoc(), diag::warn_duplicate_attribute_exact)
3160 Diag(AL.
getLoc(), diag::note_previous_attribute);
3164 ExistingKind == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3165 Diag(AL.
getLoc(), diag::err_hlsl_matrix_layout_conflict)
3167 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
3172 if (AttrK == attr::HLSLRowMajor)
3173 return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
3174 return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
3185 if (K != attr::HLSLRowMajor && K != attr::HLSLColumnMajor)
3187 if (
T.isNull() ||
T->isDependentType())
3192 K == attr::HLSLRowMajor ?
"row_major" :
"column_major");
3193 Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << II;
3201using llvm::dxil::BarrierMemoryTypeFlag;
3202using llvm::dxil::BarrierSemanticFlag;
3204template <
typename T>
constexpr uint64_t barrierFlagValue(
T Flag) {
3205 return llvm::to_underlying(Flag);
3219 bool DiagnoseAvailability;
3246 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
3250 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
3251 unsigned CurrentShaderStageBit;
3256 bool ReportOnlyShaderStageIssues;
3259 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
3260 static_assert(
sizeof(
unsigned) >= 4);
3261 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
3262 assert((
unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
3263 "ShaderType is too big for this bitmap");
3266 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
3267 CurrentShaderEnvironment = ShaderType;
3268 CurrentShaderStageBit = (1 << bitmapIndex);
3271 void SetUnknownShaderStageContext() {
3272 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
3273 CurrentShaderStageBit = (1 << 31);
3276 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment()
const {
3277 return CurrentShaderEnvironment;
3280 bool InUnknownShaderStageContext()
const {
3281 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
3285 void AddToScannedFunctions(
const FunctionDecl *FD) {
3286 unsigned &ScannedStages = ScannedDecls[FD];
3287 ScannedStages |= CurrentShaderStageBit;
3290 unsigned GetScannedStages(
const FunctionDecl *FD) {
return ScannedDecls[FD]; }
3292 bool WasAlreadyScannedInCurrentStage(
const FunctionDecl *FD) {
3293 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
3296 bool WasAlreadyScannedInCurrentStage(
unsigned ScannerStages) {
3297 return ScannerStages & CurrentShaderStageBit;
3300 static bool NeverBeenScanned(
unsigned ScannedStages) {
3301 return ScannedStages == 0;
3305 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
3306 void CheckDeclAvailability(NamedDecl *D,
const AvailabilityAttr *AA,
3308 const AvailabilityAttr *FindAvailabilityAttr(
const Decl *D);
3309 bool HasMatchingEnvironmentOrNone(
const AvailabilityAttr *AA);
3310 void DiagnoseBarrierCall(CallExpr *CE);
3312 bool HasVisibleGroup,
bool IsAllMemory);
3314 bool HasKnownStage,
bool IsAllMemory);
3315 void DiagnoseBarrierGroupSemantic(Expr *SemanticArg,
uint64_t SemanticFlags,
3316 bool HasVisibleGroup);
3317 void DiagnoseBarrierScope(Expr *SemanticArg,
uint64_t MemoryFlags,
3321 DiagnoseHLSLAvailability(Sema &SemaRef,
bool DiagnoseAvailability)
3322 : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
3323 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
3324 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(
false) {}
3327 void RunOnTranslationUnit(
const TranslationUnitDecl *TU);
3328 void RunOnFunction(
const FunctionDecl *FD);
3330 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3331 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->
getDecl());
3333 HandleFunctionOrMethodRef(FD, DRE);
3337 bool VisitMemberExpr(MemberExpr *ME)
override {
3338 FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->
getMemberDecl());
3340 HandleFunctionOrMethodRef(FD, ME);
3344 bool VisitCallExpr(CallExpr *CE)
override {
3345 DiagnoseBarrierCall(CE);
3350uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierGroupMemory(
3351 Expr *MemoryArg,
uint64_t MemoryFlags,
bool HasVisibleGroup,
3354 barrierFlagValue(BarrierMemoryTypeFlag::GroupSharedMemory);
3355 if (HasVisibleGroup || (MemoryFlags & GroupSharedMemory) == 0)
3360 diag::err_hlsl_barrier_flag_requires_group)
3365 return MemoryFlags & ~GroupSharedMemory;
3368uint64_t DiagnoseHLSLAvailability::DiagnoseBarrierNodeMemory(
3369 Expr *MemoryArg,
uint64_t MemoryFlags,
bool HasKnownStage,
3372 barrierFlagValue(BarrierMemoryTypeFlag::NodeMemory);
3373 if (!HasKnownStage || (MemoryFlags & NodeMemory) == 0)
3378 diag::err_hlsl_barrier_node_memory_requires_node);
3382 return MemoryFlags & ~NodeMemory;
3385void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
3386 Expr *SemanticArg,
uint64_t SemanticFlags,
bool HasVisibleGroup) {
3387 if (HasVisibleGroup ||
3388 (SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupFlags)) == 0)
3392 diag::err_hlsl_barrier_flag_requires_group)
3393 << ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupSync)) !=
3399void DiagnoseHLSLAvailability::DiagnoseBarrierScope(
Expr *SemanticArg,
3402 if (ReportOnlyShaderStageIssues)
3406 barrierFlagValue(BarrierMemoryTypeFlag::UAVMemory) |
3407 barrierFlagValue(BarrierMemoryTypeFlag::NodeInputMemory);
3408 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::DeviceScope)) !=
3410 (MemoryFlags & DeviceScopeMemory) == 0)
3412 diag::err_hlsl_barrier_scope_requires_memory)
3414 if ((SemanticFlags & barrierFlagValue(BarrierSemanticFlag::GroupScope)) !=
3418 diag::err_hlsl_barrier_scope_requires_memory)
3422void DiagnoseHLSLAvailability::DiagnoseBarrierCall(
CallExpr *CE) {
3424 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_hlsl_barrier)
3427 const llvm::Triple::EnvironmentType Stage = GetCurrentShaderEnvironment();
3428 const bool HasKnownStage = !InUnknownShaderStageContext();
3429 const bool HasVisibleGroup =
3430 !HasKnownStage || Stage == llvm::Triple::Compute ||
3431 Stage == llvm::Triple::Mesh || Stage == llvm::Triple::Amplification;
3433 uint64_t MemoryFlags = barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3436 std::optional<llvm::APSInt>
Value =
3440 MemoryFlags =
Value->getZExtValue();
3441 const bool IsAllMemory =
3442 MemoryFlags == barrierFlagValue(BarrierMemoryTypeFlag::ValidMask);
3444 MemoryFlags = DiagnoseBarrierGroupMemory(MemoryArg, MemoryFlags,
3445 HasVisibleGroup, IsAllMemory);
3446 MemoryFlags = DiagnoseBarrierNodeMemory(MemoryArg, MemoryFlags,
3447 HasKnownStage, IsAllMemory);
3448 }
else if (!HasVisibleGroup) {
3450 diag::err_hlsl_barrier_resource_requires_group);
3455 std::optional<llvm::APSInt>
Value =
3461 DiagnoseBarrierGroupSemantic(SemanticArg, SemanticFlags, HasVisibleGroup);
3464 DiagnoseBarrierScope(SemanticArg, MemoryFlags, SemanticFlags);
3467void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(
FunctionDecl *FD,
3470 "expected DeclRefExpr or MemberExpr");
3472 if (DiagnoseAvailability)
3473 if (
const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
3474 CheckDeclAvailability(
3479 if (FD->
hasBody(FDWithBody) && !WasAlreadyScannedInCurrentStage(FDWithBody))
3480 DeclsToScan.push_back(FDWithBody);
3483void DiagnoseHLSLAvailability::RunOnTranslationUnit(
3488 llvm::Triple::EnvironmentType::Library;
3497 DeclContextsToScan.push_back(TU);
3499 while (!DeclContextsToScan.empty()) {
3500 const DeclContext *DC = DeclContextsToScan.pop_back_val();
3501 for (
auto &D : DC->
decls()) {
3508 if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {
3509 DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));
3514 const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
3519 if (HLSLShaderAttr *ShaderAttr = FD->
getAttr<HLSLShaderAttr>()) {
3520 if (!IsLibraryShader && FD->
getName() == EntryName) {
3523 diag::err_hlsl_ambiguous_entry_point)
3525 SemaRef.
Diag(EntryLoc, diag::note_previous_declaration_as)
3531 SetShaderStageContext(ShaderAttr->getType());
3540 for (
const auto *Redecl : FD->
redecls()) {
3541 if (Redecl->isInExportDeclContext()) {
3548 SetUnknownShaderStageContext();
3555 if (!IsLibraryShader && EntryLoc.
isInvalid()) {
3562void DiagnoseHLSLAvailability::RunOnFunction(
const FunctionDecl *FD) {
3563 assert(DeclsToScan.empty() &&
"DeclsToScan should be empty");
3564 DeclsToScan.push_back(FD);
3566 while (!DeclsToScan.empty()) {
3574 const unsigned ScannedStages = GetScannedStages(FD);
3575 if (WasAlreadyScannedInCurrentStage(ScannedStages))
3578 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
3580 AddToScannedFunctions(FD);
3585bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
3586 const AvailabilityAttr *AA) {
3591 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
3592 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
3595 llvm::Triple::EnvironmentType AttrEnv =
3596 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
3598 return CurrentEnv == AttrEnv;
3601const AvailabilityAttr *
3602DiagnoseHLSLAvailability::FindAvailabilityAttr(
const Decl *D) {
3603 AvailabilityAttr
const *PartialMatch =
nullptr;
3607 for (
const auto *A : D->
attrs()) {
3608 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
3609 const AvailabilityAttr *EffectiveAvail = Avail->getEffectiveAttr();
3610 StringRef AttrPlatform = EffectiveAvail->getPlatform()->getName();
3611 StringRef TargetPlatform =
3615 if (AttrPlatform == TargetPlatform) {
3617 if (HasMatchingEnvironmentOrNone(EffectiveAvail))
3619 PartialMatch = Avail;
3623 return PartialMatch;
3628void DiagnoseHLSLAvailability::CheckDeclAvailability(
NamedDecl *D,
3629 const AvailabilityAttr *AA,
3648 if (ReportOnlyShaderStageIssues)
3654 if (InUnknownShaderStageContext())
3659 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
3660 VersionTuple Introduced = AA->getIntroduced();
3669 llvm::StringRef PlatformName(
3672 llvm::StringRef CurrentEnvStr =
3673 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
3675 llvm::StringRef AttrEnvStr =
3676 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
3677 bool UseEnvironment = !AttrEnvStr.empty();
3679 if (EnvironmentMatches) {
3680 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability)
3681 <<
Range << D << PlatformName << Introduced.getAsString()
3682 << UseEnvironment << CurrentEnvStr;
3684 SemaRef.
Diag(
Range.getBegin(), diag::warn_hlsl_availability_unavailable)
3688 SemaRef.
Diag(D->
getLocation(), diag::note_partial_availability_specified_here)
3689 << D << PlatformName << Introduced.getAsString()
3691 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
3698 if (!DefaultCBufferDecls.empty()) {
3701 DefaultCBufferDecls);
3704 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
3708 for (
const Decl *VD : DefaultCBufferDecls) {
3709 const HLSLResourceBindingAttr *RBA =
3710 VD->
getAttr<HLSLResourceBindingAttr>();
3711 if (RBA && RBA->hasRegisterSlot() &&
3712 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
3719 SemaRef.Consumer.HandleTopLevelDecl(DG);
3721 diagnoseAvailabilityViolations(TU);
3730 "expected member expr to have resource record type or array of them");
3736 const Expr *NonConstIndexExpr =
nullptr;
3739 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
3740 if (!NonConstIndexExpr)
3748 diag::err_hlsl_resource_member_array_access_not_constant);
3752 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
3753 const Expr *IdxExpr = ASE->getIdx();
3755 NonConstIndexExpr = IdxExpr;
3757 }
else if (
const auto *SubME = dyn_cast<MemberExpr>(E)) {
3758 E = SubME->getBase();
3759 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
3760 E = ICE->getSubExpr();
3764 llvm_unreachable(
"unexpected expr type in resource member access");
3773 SemaRef.Context.getCanonicalType(
SemaRef.Context.getAddrSpaceQualType(
3776 SemaRef.Context.getLValueReferenceType(AddrSpaceType));
3779 SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
3783 [[maybe_unused]]
bool LookupSucceeded =
3784 SemaRef.LookupQualifiedName(ConvR, RD);
3785 assert(LookupSucceeded);
3794std::optional<ExprResult>
3797 const HLSLAttributedResourceType *ResTy =
3798 HLSLAttributedResourceType::findHandleTypeOnResource(
3799 BaseType.getTypePtr());
3801 ResTy->getAttrs().ResourceClass != llvm::dxil::ResourceClass::CBuffer)
3802 return std::nullopt;
3804 QualType TemplateType = ResTy->getContainedType();
3808 assert(NamedConversionDecl &&
3809 "Could not find conversion function for ConstantBuffer.");
3810 auto *ConversionDecl =
3813 return SemaRef.BuildCXXMemberCallExpr(BaseExpr, NamedConversionDecl,
3823 const bool DiagnoseAvailability =
3825 TI.
getTriple().getEnvironment() == llvm::Triple::EnvironmentType::Library;
3826 DiagnoseHLSLAvailability(
SemaRef, DiagnoseAvailability)
3827 .RunOnTranslationUnit(TU);
3834 for (
unsigned I = 1, N = TheCall->
getNumArgs(); I < N; ++I) {
3837 S->
Diag(TheCall->
getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
3862 for (
unsigned I = 0; I < TheCall->
getNumArgs(); ++I) {
3875 if (!BaseType->isFloat32Type())
3876 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3877 << ArgOrdinal << 5 << 0
3887 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
3888 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3889 << ArgOrdinal << 5 << 0
3898 if (!BaseType->isDoubleType()) {
3901 return S->
Diag(Loc, diag::err_builtin_requires_double_type)
3902 << ArgOrdinal << PassedType;
3909 unsigned ArgIndex) {
3910 auto *Arg = TheCall->
getArg(ArgIndex);
3912 if (Arg->IgnoreCasts()->isModifiableLvalue(S->
Context, &OrigLoc) ==
3915 S->
Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
3929 << (ArgIndex + 1) << LValueTy;
3939 if (VecTy->getElementType()->isDoubleType())
3940 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3941 << ArgOrdinal << 1 << 0 << 1
3951 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3952 << ArgOrdinal << 5 << 1
3961 if (VecTy->getElementType()->isUnsignedIntegerType())
3964 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3965 << ArgOrdinal << 4 << 3 << 0
3974 return S->
Diag(Loc, diag::err_builtin_invalid_arg_type)
3975 << ArgOrdinal << 5 << 3
3981 unsigned ArgOrdinal,
unsigned Width) {
3984 ArgTy = VTy->getElementType();
3988 if (ElementBitCount != Width) {
3990 diag::err_integer_incorrect_bit_count)
3991 << Width << ElementBitCount;
4002 else if (
auto *MatTyA =
4005 ReturnType, MatTyA->getNumRows(), MatTyA->getNumColumns());
4011 unsigned ArgIndex) {
4020 diag::err_typecheck_expect_scalar_or_vector)
4021 << ArgType << Scalar;
4028 QualType Scalar,
unsigned ArgIndex) {
4039 if (
const auto *VTy = ArgType->getAs<
VectorType>()) {
4052 diag::err_typecheck_expect_scalar_or_vector_or_matrix)
4053 << ArgType << Scalar;
4058 unsigned ArgIndex) {
4063 if (!(ArgType->isScalarType() ||
4064 (VTy && VTy->getElementType()->isScalarType()))) {
4066 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4074 unsigned ArgIndex) {
4077 if (ArgType->isDependentType())
4081 if (
const auto *VectorTy = ArgType->getAs<
VectorType>())
4082 ElementType = VectorTy->getElementType();
4084 ElementType = MatrixTy->getElementType();
4086 if (ElementType->isBooleanType())
4089 if (ElementType->isIntegerType() || ElementType->isRealFloatingType()) {
4091 if (BitWidth == 16 || BitWidth == 32 || BitWidth == 64)
4096 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4104 unsigned ArgIndex) {
4106 assert(ArgIndex < TheCall->getNumArgs());
4114 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
4140 diag::err_typecheck_convert_incompatible)
4141 << MaskTy << UInt4Ty << 1 << 0 << 0;
4151 diag::err_typecheck_call_different_arg_types)
4170 Arg1ScalarTy = VTy->getElementType();
4174 Arg2ScalarTy = VTy->getElementType();
4177 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4178 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4188 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
4190 diag::err_typecheck_vector_lengths_not_equal)
4196 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
4198 diag::err_typecheck_vector_lengths_not_equal)
4218 Arg1ScalarTy = MTy->getElementType();
4222 Arg2ScalarTy = MTy->getElementType();
4225 S->
Diag(Arg1->
getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
4226 << 1 << TheCall->
getCallee() << Arg1Ty << Arg2Ty;
4231 unsigned Arg0Cols = Arg0MatTy->getNumColumns();
4233 for (
Expr *Arg : {Arg1, Arg2}) {
4236 (MTy->getNumRows() != Arg0Rows || MTy->getNumColumns() != Arg0Cols)) {
4238 diag::err_typecheck_vector_lengths_not_equal)
4240 << Arg->getSourceRange();
4256 unsigned ArgIndex) {
4261 assert(TheCall->
getNumArgs() > IndexArgIndex &&
"Index argument missing");
4264 unsigned int ActualDim = 1;
4266 ActualDim = VTy->getNumElements();
4267 IndexTy = VTy->getElementType();
4271 diag::err_typecheck_expect_int)
4277 const HLSLAttributedResourceType *ResTy =
4279 assert(ResTy &&
"Resource argument must be a resource");
4280 HLSLAttributedResourceType::Attributes ResAttrs = ResTy->getAttrs();
4282 unsigned int ExpectedDim = 1;
4283 if (ResAttrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
4285 (ResAttrs.IsArray ? 1 : 0);
4287 if (ActualDim != ExpectedDim) {
4289 diag::err_hlsl_builtin_resource_coordinate_dimension_mismatch)
4300 llvm::function_ref<
bool(
const HLSLAttributedResourceType *ResType)> Check =
4304 const HLSLAttributedResourceType *ResTy =
4308 diag::err_typecheck_expect_hlsl_resource)
4312 if (Check && Check(ResTy)) {
4314 diag::err_invalid_hlsl_resource_type)
4324 "expected resource handle type");
4325 auto *MainResType = MainHandleTy->
getAs<HLSLAttributedResourceType>();
4326 auto MainAttrs = MainResType->getAttrs();
4327 assert(!MainAttrs.IsCounter &&
"cannot create a counter from a counter");
4328 MainAttrs.IsCounter =
true;
4330 MainResType->getContainedType(),
4341 return "SampleBias";
4343 return "SampleGrad";
4345 return "SampleLevel";
4349 return "SampleCmpLevelZero";
4351 llvm_unreachable(
"Invalid SampleKind");
4361 if (!MD || !MD->getDeclName().isIdentifier())
4368 return MD->getName();
4376 StringRef DefaultName) {
4381 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_double_element_type)
4408 if (SMVersion >= VersionTuple(6, 7))
4411 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_sample_integer_element_type)
4413 << ContainedType << SMVersion.getAsString();
4418 bool IncludeArraySlice =
true) {
4421 [](
const HLSLAttributedResourceType *ResType) {
4422 return ResType->getAttrs().ResourceDimension ==
4423 llvm::dxil::ResourceDimension::Unknown;
4429 [](
const HLSLAttributedResourceType *ResType) {
4430 return ResType->getAttrs().ResourceClass !=
4431 llvm::hlsl::ResourceClass::Sampler;
4439 unsigned ExpectedDim =
4441 (IncludeArraySlice && ResourceTy->getAttrs().IsArray ? 1 : 0);
4470 unsigned NextIdx = 3;
4482 Expr *ComponentArg = TheCall->
getArg(NextIdx);
4486 std::optional<llvm::APSInt> ComponentOpt =
4489 int64_t ComponentVal = ComponentOpt->getSExtValue();
4490 if (ComponentVal != 0) {
4493 assert(ComponentVal >= 0 && ComponentVal <= 3 &&
4494 "The component is not in the expected range.");
4496 diag::err_hlsl_gathercmp_invalid_component)
4506 const HLSLAttributedResourceType *ResourceTy =
4509 unsigned ExpectedDim =
4512 &S, TheCall->
getArg(NextIdx),
4518 assert(ResourceTy->hasContainedType() &&
4519 "Expecting a contained type for resource with a dimension "
4521 QualType ReturnType = ResourceTy->getContainedType();
4524 IsCmp ?
"GatherCmp" :
"Gather"))
4529 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4535 ReturnType = VecTy->getElementType();
4548 [](
const HLSLAttributedResourceType *ResType) {
4549 return ResType->getAttrs().ResourceDimension ==
4550 llvm::dxil::ResourceDimension::Unknown;
4560 ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV;
4567 unsigned ResourceDim =
4569 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4585 TheCall->
setType(ResourceTy->getContainedType());
4595 [](
const HLSLAttributedResourceType *ResType) {
4596 return !ResType->isMultiSampled();
4605 unsigned ResourceDim =
4607 unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0);
4625 TheCall->
setType(ResourceTy->getContainedType());
4630 unsigned MinArgs, MaxArgs;
4658 const HLSLAttributedResourceType *ResourceTy =
4660 unsigned ExpectedDim =
4663 unsigned NextIdx = 3;
4688 &S, TheCall->
getArg(NextIdx),
4701 assert(ResourceTy->hasContainedType() &&
4702 "Expecting a contained type for resource with a dimension "
4704 QualType ReturnType = ResourceTy->getContainedType();
4715 S.
Diag(TheCall->
getBeginLoc(), diag::err_hlsl_samplecmp_requires_float);
4732 unsigned MinArgs,
unsigned MaxArgs,
4734 bool ReportsOriginalValue) {
4735 if (MinArgs == MaxArgs) {
4738 }
else if (TheCall->
getNumArgs() < MinArgs) {
4739 S.
Diag(TheCall->
getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
4749 const bool DestIsOK =
4755 diag::err_builtin_invalid_arg_type)
4769 TI.
getTriple().getArch() == llvm::Triple::dxil &&
4785 for (
unsigned I = 1, E = TheCall->
getNumArgs(); I != E; ++I)
4791 const unsigned NumArgs = TheCall->
getNumArgs();
4792 if (ReportsOriginalValue && NumArgs == MaxArgs &&
4803 switch (BuiltinID) {
4804 case Builtin::BI__builtin_hlsl_barrier: {
4805 if (
SemaRef.checkArgCount(TheCall, 2))
4808 if (
SemaRef.Context.getTargetInfo().getTriple().getArch() !=
4809 llvm::Triple::dxil) {
4817 std::optional<llvm::APSInt> MemoryFlags =
4821 diag::err_constant_integer_arg_type)
4825 if ((MemoryFlags->getZExtValue() &
4826 ~barrierFlagValue(BarrierMemoryTypeFlag::ValidMask)) != 0) {
4828 diag::err_hlsl_invalid_barrier_memory_flags);
4832 const HLSLAttributedResourceType *ResTy =
4833 HLSLAttributedResourceType::findHandleTypeOnResource(
4837 diag::err_typecheck_expect_hlsl_resource)
4841 if (ResTy->getAttrs().ResourceClass != ResourceClass::UAV) {
4843 diag::err_invalid_hlsl_resource_type)
4850 std::optional<llvm::APSInt> SemanticFlags =
4852 if (!SemanticFlags) {
4854 diag::err_constant_integer_arg_type)
4858 if ((SemanticFlags->getZExtValue() &
4859 ~barrierFlagValue(BarrierSemanticFlag::ValidMask)) != 0) {
4861 diag::err_hlsl_invalid_barrier_semantic_flags);
4868 case Builtin::BI__builtin_hlsl_adduint64: {
4869 if (
SemaRef.checkArgCount(TheCall, 2))
4883 if (NumElementsArg != 2 && NumElementsArg != 4) {
4885 << 1 << 64 << NumElementsArg * 32;
4899 case Builtin::BI__builtin_hlsl_resource_getpointer: {
4900 if (
SemaRef.checkArgCountRange(TheCall, 1, 2) ||
4907 QualType ContainedTy = ResourceTy->getContainedType();
4908 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4911 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4916 case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
4917 if (
SemaRef.checkArgCount(TheCall, 3) ||
4924 "expected pointer type for second argument");
4931 diag::err_invalid_use_of_array_type);
4935 auto ReturnType =
SemaRef.Context.getAddrSpaceQualType(
4938 ReturnType =
SemaRef.Context.getPointerType(ReturnType);
4943 case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
4944 if (
SemaRef.checkArgCount(TheCall, 2) ||
4946 SemaRef.getASTContext().IntTy))
4953 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
4954 if (
SemaRef.checkArgCount(TheCall, 3) ||
4957 SemaRef.getASTContext().UnsignedIntTy) ||
4959 SemaRef.getASTContext().UnsignedIntTy) ||
4965 QualType ReturnType = ResourceTy->getContainedType();
4970 case Builtin::BI__builtin_hlsl_resource_load_with_status_typed: {
4971 if (
SemaRef.checkArgCount(TheCall, 4) ||
4974 SemaRef.getASTContext().UnsignedIntTy) ||
4976 SemaRef.getASTContext().UnsignedIntTy) ||
4982 "expected pointer type for second argument");
4989 diag::err_invalid_use_of_array_type);
4995 case Builtin::BI__builtin_hlsl_resource_load_level:
4997 case Builtin::BI__builtin_hlsl_resource_load_ms:
4999 case Builtin::BI__builtin_hlsl_resource_sample:
5001 case Builtin::BI__builtin_hlsl_resource_sample_bias:
5003 case Builtin::BI__builtin_hlsl_resource_sample_grad:
5005 case Builtin::BI__builtin_hlsl_resource_sample_level:
5007 case Builtin::BI__builtin_hlsl_resource_sample_cmp:
5009 case Builtin::BI__builtin_hlsl_resource_sample_cmp_level_zero:
5011 case Builtin::BI__builtin_hlsl_resource_calculate_lod:
5012 case Builtin::BI__builtin_hlsl_resource_calculate_lod_unclamped:
5014 case Builtin::BI__builtin_hlsl_resource_gather:
5016 case Builtin::BI__builtin_hlsl_resource_gather_cmp:
5018 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
5019 assert(TheCall->
getNumArgs() == 1 &&
"expected 1 arg");
5025 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
5026 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
5032 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
5033 assert(TheCall->
getNumArgs() == 6 &&
"expected 6 args");
5039 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
5040 assert(TheCall->
getNumArgs() == 3 &&
"expected 3 args");
5046 TheCall->
setType(CounterHandleTy);
5049 case Builtin::BI__builtin_hlsl_resource_handlefromheap: {
5050 if (
SemaRef.checkArgCount(TheCall, 2) ||
5053 SemaRef.getASTContext().UnsignedIntTy))
5061 case Builtin::BI__builtin_hlsl_resource_counterhandlefromheap: {
5062 if (
SemaRef.checkArgCount(TheCall, 1) ||
5070 TheCall->
setType(CounterHandleTy);
5073 case Builtin::BI__builtin_hlsl_and:
5074 case Builtin::BI__builtin_hlsl_or: {
5075 if (
SemaRef.checkArgCount(TheCall, 2))
5089 case Builtin::BI__builtin_hlsl_asdouble: {
5090 if (
SemaRef.checkArgCount(TheCall, 2))
5094 SemaRef.Context.UnsignedIntTy,
5099 SemaRef.Context.UnsignedIntTy,
5108 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
5109 if (
SemaRef.BuiltinElementwiseTernaryMath(
5115 case Builtin::BI__builtin_hlsl_dot: {
5117 if (
SemaRef.BuiltinVectorToScalarMath(TheCall))
5123 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
5124 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
5125 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5135 EltTy = VecTy->getElementType();
5136 ResTy =
SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
5149 case Builtin::BI__builtin_hlsl_select: {
5150 if (
SemaRef.checkArgCount(TheCall, 3))
5159 if (VTy && VTy->getElementType()->isBooleanType() &&
5163 if (MTy && MTy->getElementType()->isBooleanType() &&
5168 case Builtin::BI__builtin_hlsl_elementwise_saturate:
5169 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
5170 if (
SemaRef.checkArgCount(TheCall, 1))
5176 diag::err_builtin_invalid_arg_type)
5179 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5183 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
5184 case Builtin::BI__builtin_hlsl_elementwise_frac:
5185 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
5186 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
5187 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
5188 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
5189 if (
SemaRef.checkArgCount(TheCall, 1))
5194 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5198 case Builtin::BI__builtin_hlsl_elementwise_isfinite:
5199 case Builtin::BI__builtin_hlsl_elementwise_isinf:
5200 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
5201 if (
SemaRef.checkArgCount(TheCall, 1))
5206 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5211 case Builtin::BI__builtin_hlsl_mad: {
5212 if (
SemaRef.BuiltinElementwiseTernaryMath(
5218 case Builtin::BI__builtin_hlsl_mul: {
5219 if (
SemaRef.checkArgCount(TheCall, 2))
5229 return VTy->getElementType();
5231 return MTy->getElementType();
5235 QualType EltTy0 = getElemType(Ty0);
5244 if (IsVec0 && IsMat1) {
5247 }
else if (IsMat0 && IsVec1) {
5251 assert(IsMat0 && IsMat1);
5261 case Builtin::BI__builtin_elementwise_fma: {
5262 if (
SemaRef.checkArgCount(TheCall, 3) ||
5277 case Builtin::BI__builtin_hlsl_transpose: {
5278 if (
SemaRef.checkArgCount(TheCall, 1))
5287 << 1 << 3 << 0 << 0 << ArgTy;
5292 MatTy->getElementType(), MatTy->getNumColumns(), MatTy->getNumRows());
5296 case Builtin::BI__builtin_hlsl_elementwise_sign: {
5297 if (
SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
5305 case Builtin::BI__builtin_hlsl_wave_active_all_equal: {
5306 if (
SemaRef.checkArgCount(TheCall, 1))
5320 unsigned NumElts = VecTy->getNumElements();
5330 case Builtin::BI__builtin_hlsl_wave_active_max:
5331 case Builtin::BI__builtin_hlsl_wave_active_min:
5332 case Builtin::BI__builtin_hlsl_wave_active_sum:
5333 case Builtin::BI__builtin_hlsl_wave_active_product: {
5334 if (
SemaRef.checkArgCount(TheCall, 1))
5347 case Builtin::BI__builtin_hlsl_wave_active_bit_or:
5348 case Builtin::BI__builtin_hlsl_wave_active_bit_xor:
5349 case Builtin::BI__builtin_hlsl_wave_active_bit_and: {
5350 if (
SemaRef.checkArgCount(TheCall, 1))
5365 (VTy && VTy->getElementType()->isIntegerType()))) {
5367 diag::err_builtin_invalid_arg_type)
5368 << ArgTyExpr <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5376 case Builtin::BI__builtin_hlsl_interlocked_add:
5377 case Builtin::BI__builtin_hlsl_interlocked_and:
5378 case Builtin::BI__builtin_hlsl_interlocked_max:
5379 case Builtin::BI__builtin_hlsl_interlocked_min:
5380 case Builtin::BI__builtin_hlsl_interlocked_or:
5381 case Builtin::BI__builtin_hlsl_interlocked_xor:
5387 case Builtin::BI__builtin_hlsl_interlocked_exchange:
5393 case Builtin::BI__builtin_hlsl_interlocked_compare_store:
5399 case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise:
5405 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange:
5411 case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise:
5419 case Builtin::BI__builtin_elementwise_bitreverse: {
5427 case Builtin::BI__builtin_hlsl_wave_prefix_count_bits:
5428 case Builtin::BI__builtin_hlsl_wave_multi_prefix_count_bits: {
5429 bool IsMultiPrefix =
5430 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_count_bits;
5431 if (
SemaRef.checkArgCount(TheCall, IsMultiPrefix ? 2 : 1))
5436 if (!(
ArgType->isScalarType())) {
5438 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5443 if (!(
ArgType->isBooleanType())) {
5445 diag::err_typecheck_expect_any_scalar_or_vector_or_matrix)
5450 if (IsMultiPrefix) {
5458 diag::err_builtin_target_unsupported)
5466 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
5467 if (
SemaRef.checkArgCount(TheCall, 2))
5475 diag::err_typecheck_convert_incompatible)
5476 << ArgTyIndex <<
SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
5489 case Builtin::BI__builtin_hlsl_wave_read_lane_first: {
5490 if (
SemaRef.checkArgCount(TheCall, 1))
5499 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
5500 if (
SemaRef.checkArgCount(TheCall, 0))
5504 case Builtin::BI__builtin_hlsl_wave_prefix_sum:
5505 case Builtin::BI__builtin_hlsl_wave_prefix_product: {
5506 if (
SemaRef.checkArgCount(TheCall, 1))
5519 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_and:
5520 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_or:
5521 case Builtin::BI__builtin_hlsl_wave_multi_prefix_bit_xor:
5522 case Builtin::BI__builtin_hlsl_wave_multi_prefix_product:
5523 case Builtin::BI__builtin_hlsl_wave_multi_prefix_sum: {
5524 if (
SemaRef.checkArgCount(TheCall, 2))
5534 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_product ||
5535 BuiltinID == Builtin::BI__builtin_hlsl_wave_multi_prefix_sum;
5540 diag::err_builtin_invalid_arg_type)
5541 << 1 << (ValueTy->
isMatrixType() ? 3 : 5) << 1 << IsArithmetic
5552 case Builtin::BI__builtin_hlsl_quad_read_across_x:
5553 case Builtin::BI__builtin_hlsl_quad_read_across_y:
5554 case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
5555 if (
SemaRef.checkArgCount(TheCall, 1))
5567 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
5568 if (
SemaRef.checkArgCount(TheCall, 3))
5574 SemaRef.Context.UnsignedIntTy, 1) ||
5576 SemaRef.Context.UnsignedIntTy, 2))
5584 case Builtin::BI__builtin_hlsl_elementwise_clip: {
5585 if (
SemaRef.checkArgCount(TheCall, 1))
5592 case Builtin::BI__builtin_elementwise_acos:
5593 case Builtin::BI__builtin_elementwise_asin:
5594 case Builtin::BI__builtin_elementwise_atan:
5595 case Builtin::BI__builtin_elementwise_atan2:
5596 case Builtin::BI__builtin_elementwise_ceil:
5597 case Builtin::BI__builtin_elementwise_cos:
5598 case Builtin::BI__builtin_elementwise_cosh:
5599 case Builtin::BI__builtin_elementwise_exp:
5600 case Builtin::BI__builtin_elementwise_exp2:
5601 case Builtin::BI__builtin_elementwise_exp10:
5602 case Builtin::BI__builtin_elementwise_floor:
5603 case Builtin::BI__builtin_elementwise_fmod:
5604 case Builtin::BI__builtin_elementwise_log:
5605 case Builtin::BI__builtin_elementwise_log2:
5606 case Builtin::BI__builtin_elementwise_log10:
5607 case Builtin::BI__builtin_elementwise_pow:
5608 case Builtin::BI__builtin_elementwise_roundeven:
5609 case Builtin::BI__builtin_elementwise_sin:
5610 case Builtin::BI__builtin_elementwise_sinh:
5611 case Builtin::BI__builtin_elementwise_sqrt:
5612 case Builtin::BI__builtin_elementwise_tan:
5613 case Builtin::BI__builtin_elementwise_tanh:
5614 case Builtin::BI__builtin_elementwise_trunc: {
5620 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
5621 assert(TheCall->
getNumArgs() == 2 &&
"expected 2 args");
5622 auto checkResTy = [](
const HLSLAttributedResourceType *ResTy) ->
bool {
5623 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
5624 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
5629 std::optional<llvm::APSInt> Offset =
5631 if (!Offset.has_value() ||
std::abs(Offset->getExtValue()) != 1) {
5633 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
5639 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
5640 if (
SemaRef.checkArgCount(TheCall, 1))
5651 ArgTy = VTy->getElementType();
5654 diag::err_builtin_invalid_arg_type)
5663 case Builtin::BI__builtin_hlsl_elementwise_f32tof16: {
5664 if (
SemaRef.checkArgCount(TheCall, 1))
5679 WorkList.push_back(BaseTy);
5680 while (!WorkList.empty()) {
5682 T =
T.getCanonicalType().getUnqualifiedType();
5683 if (
const auto *AT = dyn_cast<ConstantArrayType>(
T)) {
5691 for (
uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
5692 llvm::append_range(List, ElementFields);
5697 if (
const auto *VT = dyn_cast<VectorType>(
T)) {
5698 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
5701 if (
const auto *MT = dyn_cast<ConstantMatrixType>(
T)) {
5702 List.insert(List.end(), MT->getNumElementsFlattened(),
5703 MT->getElementType());
5706 if (
const auto *RD =
T->getAsCXXRecordDecl()) {
5707 if (RD->isStandardLayout())
5708 RD = RD->getStandardLayoutBaseWithFields();
5712 if (RD->
isUnion() || !RD->isAggregate()) {
5718 for (
const auto *FD : RD->
fields())
5719 if (!FD->isUnnamedBitField())
5720 FieldTypes.push_back(FD->
getType());
5722 std::reverse(FieldTypes.begin(), FieldTypes.end());
5723 llvm::append_range(WorkList, FieldTypes);
5727 if (!RD->isStandardLayout()) {
5729 for (
const auto &
Base : RD->bases())
5730 FieldTypes.push_back(
Base.getType());
5731 std::reverse(FieldTypes.begin(), FieldTypes.end());
5732 llvm::append_range(WorkList, FieldTypes);
5767 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5773 int ArraySize = VT->getNumElements();
5778 QualType ElTy = VT->getElementType();
5782 if (
SemaRef.Context.getTypeSize(QT) / 8 > 16)
5798 if (
SemaRef.getASTContext().hasSameType(T1, T2))
5807 return llvm::equal(T1Types, T2Types,
5809 return SemaRef.IsLayoutCompatible(LHS, RHS);
5818 bool HadError =
false;
5820 for (
unsigned i = 0, e =
New->getNumParams(); i != e; ++i) {
5828 const auto *NDAttr = NewParam->
getAttr<HLSLParamModifierAttr>();
5829 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
5830 const auto *ODAttr = OldParam->
getAttr<HLSLParamModifierAttr>();
5831 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
5833 if (NSpellingIdx != OSpellingIdx) {
5835 diag::err_hlsl_param_qualifier_mismatch)
5836 << NDAttr << NewParam;
5852 if (
SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
5867 llvm_unreachable(
"HLSL doesn't support pointers.");
5870 llvm_unreachable(
"HLSL doesn't support complex types.");
5872 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5874 llvm_unreachable(
"Should have returned before this");
5884 llvm_unreachable(
"HLSL doesn't support complex types.");
5886 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5891 llvm_unreachable(
"HLSL doesn't support pointers.");
5893 llvm_unreachable(
"Should have returned before this");
5899 llvm_unreachable(
"HLSL doesn't support pointers.");
5902 llvm_unreachable(
"HLSL doesn't support fixed point types.");
5906 llvm_unreachable(
"HLSL doesn't support complex types.");
5909 llvm_unreachable(
"Unhandled scalar cast");
5930 !(SrcMatTy && SrcMatTy->getNumElementsFlattened() == 1))
5936 SrcTy = SrcMatTy->getElementType();
5941 for (
unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
5942 if (DestTypes[I]->isUnionType())
5974 if (SrcTypes.size() < DestTypes.size())
5977 unsigned SrcSize = SrcTypes.size();
5978 unsigned DstSize = DestTypes.size();
5980 for (I = 0; I < DstSize && I < SrcSize; I++) {
5981 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
5989 for (; I < SrcSize; I++) {
5990 if (SrcTypes[I]->isUnionType())
6033 tok::equal, ArgOpV, OpV);
6045 assert(Param->hasAttr<HLSLParamModifierAttr>() &&
6046 "We should not get here without a parameter modifier expression");
6047 const auto *
Attr = Param->getAttr<HLSLParamModifierAttr>();
6054 << Arg << (IsInOut ? 1 : 0);
6058 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
6065 << Arg << (IsInOut ? 1 : 0);
6073 Param->getBeginLoc(), IsInOut);
6081 "Pointer and reference types cannot be inout or out parameters");
6082 Ty =
SemaRef.getASTContext().getLValueReferenceType(Ty);
6098 for (
const auto *FD : RD->
fields()) {
6102 assert(RD->getNumBases() <= 1 &&
6103 "HLSL doesn't support multiple inheritance");
6104 return RD->getNumBases()
6109 if (
const auto *AT = dyn_cast<ArrayType>(Ty)) {
6110 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
6122 bool IsVKPushConstant = IsVulkan && VD->
hasAttr<HLSLVkPushConstantAttr>();
6127 !VD->
hasAttr<HLSLVkConstantIdAttr>() && !IsVKPushConstant &&
6133 if (
Decl->getType().hasAddressSpace())
6136 if (
Decl->getType()->isDependentType())
6148 if (
Decl->
hasAttr<HLSLVkExtBuiltinOutputAttr>()) {
6162 llvm::Triple::Vulkan;
6163 if (IsVulkan &&
Decl->
hasAttr<HLSLVkPushConstantAttr>()) {
6164 if (HasDeclaredAPushConstant)
6170 HasDeclaredAPushConstant =
true;
6197class StructBindingContext {
6200 HLSLResourceBindingAttr *RegBindingsAttrs[4];
6201 unsigned RegBindingOffset[4];
6204 static_assert(
static_cast<unsigned>(RegisterType::SRV) == 0 &&
6205 static_cast<unsigned>(RegisterType::UAV) == 1 &&
6206 static_cast<unsigned>(RegisterType::CBuffer) == 2 &&
6207 static_cast<unsigned>(RegisterType::Sampler) == 3,
6208 "unexpected register type values");
6211 HLSLVkBindingAttr *VkBindingAttr;
6212 unsigned VkBindingOffset;
6217 StructBindingContext(
VarDecl *VD) {
6218 for (
unsigned i = 0; i < 4; ++i) {
6219 RegBindingsAttrs[i] =
nullptr;
6220 RegBindingOffset[i] = 0;
6222 VkBindingAttr =
nullptr;
6223 VkBindingOffset = 0;
6229 if (
auto *RBA = dyn_cast<HLSLResourceBindingAttr>(A)) {
6231 unsigned RegTypeIdx =
static_cast<unsigned>(RegType);
6234 RegBindingsAttrs[RegTypeIdx] = RBA;
6239 if (
auto *VBA = dyn_cast<HLSLVkBindingAttr>(A))
6240 VkBindingAttr = VBA;
6247 Attr *createBindingAttr(SemaHLSL &S, ASTContext &AST,
RegisterType RegType,
6248 unsigned Range,
bool HasCounter) {
6249 assert(
static_cast<unsigned>(RegType) < 4 &&
"unexpected register type");
6251 if (VkBindingAttr) {
6252 unsigned Offset = VkBindingOffset;
6253 VkBindingOffset +=
Range;
6254 return HLSLVkBindingAttr::CreateImplicit(
6255 AST, VkBindingAttr->getBinding() + Offset, VkBindingAttr->getSet(),
6256 VkBindingAttr->getRange());
6259 HLSLResourceBindingAttr *RBA =
6260 RegBindingsAttrs[
static_cast<unsigned>(RegType)];
6261 HLSLResourceBindingAttr *NewAttr =
nullptr;
6263 if (RBA && RBA->hasRegisterSlot()) {
6266 unsigned Offset = RegBindingOffset[
static_cast<unsigned>(RegType)];
6267 RegBindingOffset[
static_cast<unsigned>(RegType)] += Range;
6269 unsigned NewSlotNumber = RBA->getSlotNumber() + Offset;
6270 StringRef NewSlotNumberStr =
6272 NewAttr = HLSLResourceBindingAttr::CreateImplicit(
6273 AST, NewSlotNumberStr, RBA->getSpace(), RBA->getRange());
6274 NewAttr->setBinding(RegType, NewSlotNumber, RBA->getSpaceNumber());
6278 NewAttr = HLSLResourceBindingAttr::CreateImplicit(AST,
"",
"0", {});
6279 NewAttr->setBinding(RegType, std::nullopt,
6280 RBA ? RBA->getSpaceNumber() : 0);
6284 NewAttr->setImplicitCounterBindingOrderID(
6293static void createGlobalResourceDeclForStruct(
6295 QualType ResTy, StructBindingContext &BindingCtx) {
6297 "expected resource type or array of resources");
6308 while (
const auto *AT = dyn_cast<ArrayType>(SingleResTy)) {
6309 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
6314 const HLSLAttributedResourceType *ResHandleTy =
6315 HLSLAttributedResourceType::findHandleTypeOnResource(SingleResTy);
6319 Attr *BindingAttr = BindingCtx.createBindingAttr(
6321 ResDecl->
addAttr(BindingAttr);
6322 ResDecl->
addAttr(InternalLinkageAttr::CreateImplicit(AST));
6331 HLSLAssociatedResourceDeclAttr::CreateImplicit(AST, ResDecl));
6338static void handleArrayOfStructWithResources(
6340 EmbeddedResourceNameBuilder &NameBuilder, StructBindingContext &BindingCtx);
6345static void handleStructWithResources(
Sema &S,
VarDecl *ParentVD,
6347 EmbeddedResourceNameBuilder &NameBuilder,
6348 StructBindingContext &BindingCtx) {
6351 assert(RD->
getNumBases() <= 1 &&
"HLSL doesn't support multiple inheritance");
6358 handleStructWithResources(S, ParentVD, BaseRD, NameBuilder, BindingCtx);
6372 createGlobalResourceDeclForStruct(S, ParentVD, FD->
getLocation(), II,
6375 handleStructWithResources(S, ParentVD, RD, NameBuilder, BindingCtx);
6377 }
else if (
const auto *ArrayTy = dyn_cast<ConstantArrayType>(FDTy)) {
6379 "resource arrays should have been already handled");
6380 handleArrayOfStructWithResources(S, ParentVD, ArrayTy, NameBuilder,
6389handleArrayOfStructWithResources(
Sema &S,
VarDecl *ParentVD,
6391 EmbeddedResourceNameBuilder &NameBuilder,
6392 StructBindingContext &BindingCtx) {
6400 if (!SubCAT && !ElementRD)
6403 for (
unsigned I = 0, E = CAT->
getSize().getZExtValue(); I < E; ++I) {
6406 handleStructWithResources(S, ParentVD, ElementRD, NameBuilder,
6409 handleArrayOfStructWithResources(S, ParentVD, SubCAT, NameBuilder,
6422void SemaHLSL::handleGlobalStructOrArrayOfWithResources(
VarDecl *VD) {
6423 EmbeddedResourceNameBuilder NameBuilder(VD->
getName());
6424 StructBindingContext BindingCtx(VD);
6428 "Expected non-resource struct or array type");
6431 handleStructWithResources(
SemaRef, VD, RD, NameBuilder, BindingCtx);
6435 if (
const auto *CAT = dyn_cast<ConstantArrayType>(VDTy)) {
6436 handleArrayOfStructWithResources(
SemaRef, VD, CAT, NameBuilder, BindingCtx);
6444 if (
SemaRef.RequireCompleteType(
6447 diag::err_typecheck_decl_incomplete_type)) {
6461 DefaultCBufferDecls.push_back(VD);
6466 collectResourceBindingsOnVarDecl(VD);
6468 if (VD->
hasAttr<HLSLVkConstantIdAttr>())
6480 processExplicitBindingsOnDecl(VD);
6517 handleGlobalStructOrArrayOfWithResources(VD);
6521 if (VD->
hasAttr<HLSLGroupSharedAddressSpaceAttr>())
6530 "expected resource record type");
6546 const char *CreateMethodName;
6548 CreateMethodName = HasCounter ?
"__createFromBindingWithImplicitCounter"
6549 :
"__createFromBinding";
6551 CreateMethodName = HasCounter
6552 ?
"__createFromImplicitBindingWithImplicitCounter"
6553 :
"__createFromImplicitBinding";
6558 if (!CreateMethod) {
6563 "create method lookup should always succeed for built-in resource "
6572 Args.push_back(RegSlot);
6580 Args.push_back(OrderId);
6586 Args.push_back(Space);
6590 Args.push_back(RangeSize);
6594 Args.push_back(Index);
6596 StringRef VarName = VD->
getName();
6604 Args.push_back(NameCast);
6612 Args.push_back(CounterId);
6635 SemaRef.CheckCompleteVariableDeclaration(VD);
6641 "expected array of resource records");
6662 lookupMethod(
SemaRef, ResourceDecl,
6663 HasCounter ?
"__createFromBindingWithImplicitCounter"
6664 :
"__createFromBinding",
6668 CreateMethod = lookupMethod(
6670 HasCounter ?
"__createFromImplicitBindingWithImplicitCounter"
6671 :
"__createFromImplicitBinding",
6714std::optional<const DeclBindingInfo *> SemaHLSL::inferGlobalBinding(
Expr *E) {
6715 if (
auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
6716 auto TrueInfo = inferGlobalBinding(Ternary->getTrueExpr());
6717 auto FalseInfo = inferGlobalBinding(Ternary->getFalseExpr());
6718 if (!TrueInfo || !FalseInfo)
6719 return std::nullopt;
6720 if (*TrueInfo != *FalseInfo)
6721 return std::nullopt;
6725 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6734 if (
const auto *AttrResType =
6735 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6737 return Bindings.getDeclBindingInfo(VD, RC);
6744void SemaHLSL::trackLocalResource(
VarDecl *VD,
Expr *E) {
6745 std::optional<const DeclBindingInfo *> ExprBinding = inferGlobalBinding(E);
6748 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6753 if (*ExprBinding ==
nullptr)
6756 auto PrevBinding = Assigns.find(VD);
6757 if (PrevBinding == Assigns.end()) {
6759 Assigns.insert({VD, *ExprBinding});
6764 if (*ExprBinding != PrevBinding->second) {
6766 diag::warn_hlsl_assigning_local_resource_is_not_unique)
6768 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
6779 "expected LHS to be a resource record or array of resource records");
6780 if (Opc != BO_Assign)
6785 while (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
6793 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
6798 trackLocalResource(VD, RHSExpr);
6815void SemaHLSL::collectResourceBindingsOnVarDecl(
VarDecl *VD) {
6817 "expected global variable that contains HLSL resource");
6820 if (
const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {
6821 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
6822 ? ResourceClass::CBuffer
6823 : ResourceClass::SRV);
6836 if (
const HLSLAttributedResourceType *AttrResType =
6837 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
6838 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
6843 if (
const RecordType *RT = dyn_cast<RecordType>(Ty))
6844 collectResourceBindingsOnUserRecordDecl(VD, RT);
6850void SemaHLSL::processExplicitBindingsOnDecl(
VarDecl *VD) {
6853 bool HasBinding =
false;
6854 for (Attr *A : VD->
attrs()) {
6857 if (
auto PA = VD->
getAttr<HLSLVkPushConstantAttr>())
6858 Diag(PA->getLoc(), diag::err_hlsl_attr_incompatible) << A << PA;
6861 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
6862 if (!RBA || !RBA->hasRegisterSlot())
6867 assert(RT != RegisterType::I &&
"invalid or obsolete register type should "
6868 "never have an attribute created");
6870 if (RT == RegisterType::C) {
6871 if (Bindings.hasBindingInfoForDecl(VD))
6873 diag::warn_hlsl_user_defined_type_missing_member)
6874 <<
static_cast<int>(RT);
6882 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
6887 diag::warn_hlsl_user_defined_type_missing_member)
6888 <<
static_cast<int>(RT);
6896class InitListTransformer {
6900 QualType *DstIt =
nullptr;
6901 Expr **ArgIt =
nullptr;
6907 bool castInitializer(Expr *E) {
6908 assert(DstIt &&
"This should always be something!");
6909 if (DstIt == DestTypes.end()) {
6911 ArgExprs.push_back(E);
6916 DstIt = DestTypes.begin();
6919 Ctx, *DstIt,
false);
6924 ArgExprs.push_back(
Init);
6929 bool buildInitializerListImpl(Expr *E) {
6931 if (
auto *
Init = dyn_cast<InitListExpr>(E)) {
6932 for (
auto *SubInit :
Init->inits())
6933 if (!buildInitializerListImpl(SubInit))
6943 return castInitializer(E);
6957 if (
auto *VecTy = Ty->
getAs<VectorType>()) {
6964 SizeTy, SourceLocation());
6970 if (!castInitializer(ElExpr.
get()))
6975 if (
auto *MTy = Ty->
getAs<ConstantMatrixType>()) {
6976 unsigned Rows = MTy->getNumRows();
6977 unsigned Cols = MTy->getNumColumns();
6978 QualType ElemTy = MTy->getElementType();
6980 for (
unsigned R = 0;
R < Rows; ++
R) {
6981 for (
unsigned C = 0;
C < Cols; ++
C) {
6994 if (!castInitializer(ElExpr.
get()))
7002 if (
auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.
getTypePtr())) {
7008 SizeTy, SourceLocation());
7013 if (!buildInitializerListImpl(ElExpr.
get()))
7020 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
7021 RecordDecls.push_back(RD);
7022 while (RecordDecls.back()->getNumBases()) {
7023 CXXRecordDecl *D = RecordDecls.back();
7025 "HLSL doesn't support multiple inheritance");
7026 RecordDecls.push_back(
7029 while (!RecordDecls.empty()) {
7030 CXXRecordDecl *RD = RecordDecls.pop_back_val();
7031 for (
auto *FD : RD->
fields()) {
7032 if (FD->isUnnamedBitField())
7040 if (!buildInitializerListImpl(Res.
get()))
7048 Expr *generateInitListsImpl(QualType Ty) {
7050 assert(ArgIt != ArgExprs.end() &&
"Something is off in iteration!");
7055 llvm::SmallVector<Expr *>
Inits;
7060 if (
auto *ATy = Ty->
getAs<VectorType>()) {
7061 ElTy = ATy->getElementType();
7062 Size = ATy->getNumElements();
7063 }
else if (
auto *CMTy = Ty->
getAs<ConstantMatrixType>()) {
7064 ElTy = CMTy->getElementType();
7065 Size = CMTy->getNumElementsFlattened();
7068 ElTy = VTy->getElementType();
7069 Size = VTy->getZExtSize();
7072 Inits.push_back(generateInitListsImpl(ElTy));
7075 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
7076 RecordDecls.push_back(RD);
7077 while (RecordDecls.back()->getNumBases()) {
7078 CXXRecordDecl *D = RecordDecls.back();
7080 "HLSL doesn't support multiple inheritance");
7081 RecordDecls.push_back(
7084 while (!RecordDecls.empty()) {
7085 CXXRecordDecl *RD = RecordDecls.pop_back_val();
7086 for (
auto *FD : RD->
fields())
7087 if (!FD->isUnnamedBitField())
7092 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
7093 Inits.back()->getEndLoc(),
false);
7094 NewInit->setType(Ty);
7099 llvm::SmallVector<QualType, 16> DestTypes;
7100 llvm::SmallVector<Expr *, 16> ArgExprs;
7101 InitListTransformer(Sema &SemaRef,
const InitializedEntity &Entity)
7102 : S(SemaRef), Ctx(SemaRef.getASTContext()),
7103 Wrap(Entity.
getType()->isIncompleteArrayType()) {
7104 InitTy = Entity.
getType().getNonReferenceType();
7114 DstIt = DestTypes.begin();
7117 bool buildInitializerList(Expr *E) {
return buildInitializerListImpl(E); }
7119 Expr *generateInitLists() {
7120 assert(!ArgExprs.empty() &&
7121 "Call buildInitializerList to generate argument expressions.");
7122 ArgIt = ArgExprs.begin();
7124 return generateInitListsImpl(InitTy);
7125 llvm::SmallVector<Expr *>
Inits;
7126 while (ArgIt != ArgExprs.end())
7127 Inits.push_back(generateInitListsImpl(InitTy));
7130 new (Ctx) InitListExpr(Ctx,
Inits.front()->getBeginLoc(),
Inits,
7131 Inits.back()->getEndLoc(),
false);
7132 llvm::APInt ArySize(64,
Inits.size());
7134 ArraySizeModifier::Normal, 0));
7146 if (
const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
7153 if (
const auto *RT = Ty->
getAs<RecordType>()) {
7157 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
7177 if (
Init->getType()->isScalarType())
7180 InitListTransformer ILT(
SemaRef, Entity);
7182 for (
unsigned I = 0; I <
Init->getNumInits(); ++I) {
7190 Init->setInit(I, E);
7192 if (!ILT.buildInitializerList(E))
7195 size_t ExpectedSize = ILT.DestTypes.size();
7196 size_t ActualSize = ILT.ArgExprs.size();
7197 if (ExpectedSize == 0 && ActualSize == 0)
7204 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7206 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7207 << (int)(ExpectedSize < ActualSize) << InitTy
7208 << ExpectedSize << ActualSize;
7218 assert(ExpectedSize > 0 &&
7219 "The expected size of an incomplete array type must be at least 1.");
7221 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
7229 InitTy =
SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
7230 if (ExpectedSize != ActualSize) {
7231 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
7232 SemaRef.Diag(
Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
7233 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
7240 Init->resizeInits(Ctx, NewInit->getNumInits());
7241 for (
unsigned I = 0; I < NewInit->getNumInits(); ++I)
7242 Init->updateInit(Ctx, I, NewInit->getInit(I));
7250 S.
Diag(OpLoc, diag::err_builtin_matrix_invalid_member)
7260 StringRef AccessorName = CompName->
getName();
7261 assert(!AccessorName.empty() &&
"Matrix Accessor must have a name");
7263 unsigned Rows = MT->getNumRows();
7264 unsigned Cols = MT->getNumColumns();
7265 bool IsZeroBasedAccessor =
false;
7266 unsigned ChunkLen = 0;
7267 if (AccessorName.size() < 2)
7269 "length 4 for zero based: \'_mRC\' or "
7270 "length 3 for one-based: \'_RC\' accessor",
7273 if (AccessorName[0] ==
'_') {
7274 if (AccessorName[1] ==
'm') {
7275 IsZeroBasedAccessor =
true;
7282 S, AccessorName,
"zero based: \'_mRC\' or one-based: \'_RC\' accessor",
7285 if (AccessorName.size() % ChunkLen != 0) {
7286 const llvm::StringRef
Expected = IsZeroBasedAccessor
7287 ?
"zero based: '_mRC' accessor"
7288 :
"one-based: '_RC' accessor";
7293 auto isDigit = [](
char c) {
return c >=
'0' && c <=
'9'; };
7294 auto isZeroBasedIndex = [](
unsigned i) {
return i <= 3; };
7295 auto isOneBasedIndex = [](
unsigned i) {
return i >= 1 && i <= 4; };
7297 bool HasRepeated =
false;
7299 unsigned NumComponents = 0;
7300 const char *Begin = AccessorName.data();
7302 for (
unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) {
7303 const char *Chunk = Begin + I;
7304 char RowChar = 0, ColChar = 0;
7305 if (IsZeroBasedAccessor) {
7307 if (Chunk[0] !=
'_' || Chunk[1] !=
'm') {
7308 char Bad = (Chunk[0] !=
'_') ? Chunk[0] : Chunk[1];
7310 S, StringRef(&Bad, 1),
"\'_m\' prefix",
7317 if (Chunk[0] !=
'_')
7319 S, StringRef(&Chunk[0], 1),
"\'_\' prefix",
7326 bool IsDigitsError =
false;
7328 unsigned BadPos = IsZeroBasedAccessor ? 2 : 1;
7332 IsDigitsError =
true;
7336 unsigned BadPos = IsZeroBasedAccessor ? 3 : 2;
7340 IsDigitsError =
true;
7345 unsigned Row = RowChar -
'0';
7346 unsigned Col = ColChar -
'0';
7348 bool HasIndexingError =
false;
7349 if (IsZeroBasedAccessor) {
7351 if (!isZeroBasedIndex(Row)) {
7352 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7354 HasIndexingError =
true;
7356 if (!isZeroBasedIndex(Col)) {
7357 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7359 HasIndexingError =
true;
7363 if (!isOneBasedIndex(Row)) {
7364 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7366 HasIndexingError =
true;
7368 if (!isOneBasedIndex(Col)) {
7369 S.
Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds)
7371 HasIndexingError =
true;
7378 if (HasIndexingError)
7384 bool HasBoundsError =
false;
7386 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7388 HasBoundsError =
true;
7391 Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds)
7393 HasBoundsError =
true;
7398 unsigned FlatIndex = Row * Cols + Col;
7399 if (Seen[FlatIndex])
7401 Seen[FlatIndex] =
true;
7404 if (NumComponents == 0 || NumComponents > 4) {
7405 S.
Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length)
7410 QualType ElemTy = MT->getElementType();
7411 if (NumComponents == 1)
7417 for (Sema::ExtVectorDeclsType::iterator
7421 if ((*I)->getUnderlyingType() == VT)
7432 trackLocalResource(VDecl,
Init);
7434 const HLSLVkConstantIdAttr *ConstIdAttr =
7435 VDecl->
getAttr<HLSLVkConstantIdAttr>();
7442 if (!
Init->isCXX11ConstantExpr(Context, InitValue)) {
7452 int ConstantID = ConstIdAttr->getId();
7453 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
7455 ConstIdAttr->getLocation());
7459 if (
C->getType()->getCanonicalTypeUnqualified() !=
7463 Context.getTrivialTypeSourceInfo(
7464 Init->getType(),
Init->getExprLoc()),
7483 if (!Params || Params->
size() != 1)
7496 if (
auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
7497 if (TTP->hasDefaultArgument()) {
7498 TemplateArgs.
addArgument(TTP->getDefaultArgument());
7501 }
else if (
auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
7502 if (NTTP->hasDefaultArgument()) {
7503 TemplateArgs.
addArgument(NTTP->getDefaultArgument());
7506 }
else if (
auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P)) {
7507 if (TTPD->hasDefaultArgument()) {
7508 TemplateArgs.
addArgument(TTPD->getDefaultArgument());
7515 return SemaRef.CheckTemplateIdType(
7517 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 isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, const DeclaratorDecl *D, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
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 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 void validateVkBuiltinUsage(Sema &S, FunctionDecl *FD, const DeclaratorDecl *D, const HLSLVkBuiltInAttr *Attr, IOType CurrentIOType)
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.
const LangOptions & getLangOpts() const
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
bool isRegularKeywordAttribute() 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