clang: lib/Sema/SemaHLSL.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
15#include "clang/AST/Attrs.inc"
38#include "llvm/ADT/ArrayRef.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/SmallVector.h"
41#include "llvm/ADT/StringExtras.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ADT/Twine.h"
44#include "llvm/Frontend/HLSL/HLSLBinding.h"
45#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
46#include "llvm/Support/Casting.h"
47#include "llvm/Support/DXILABI.h"
48#include "llvm/Support/ErrorHandling.h"
49#include "llvm/Support/FormatVariadic.h"
50#include "llvm/TargetParser/Triple.h"
51#include
52#include
53#include
54#include
55
56using namespace clang;
58using RegisterType = HLSLResourceBindingAttr::RegisterType;
59
62
64 switch (RC) {
65 case ResourceClass::SRV:
66 return RegisterType::SRV;
67 case ResourceClass::UAV:
68 return RegisterType::UAV;
69 case ResourceClass::CBuffer:
70 return RegisterType::CBuffer;
71 case ResourceClass::Sampler:
72 return RegisterType::Sampler;
73 }
74 llvm_unreachable("unexpected ResourceClass value");
75}
76
80
81
82
84 assert(RT != nullptr);
85 switch (Slot[0]) {
86 case 't':
87 case 'T':
88 *RT = RegisterType::SRV;
89 return true;
90 case 'u':
91 case 'U':
92 *RT = RegisterType::UAV;
93 return true;
94 case 'b':
95 case 'B':
96 *RT = RegisterType::CBuffer;
97 return true;
98 case 's':
99 case 'S':
100 *RT = RegisterType::Sampler;
101 return true;
102 case 'c':
103 case 'C':
104 *RT = RegisterType::C;
105 return true;
106 case 'i':
107 case 'I':
108 *RT = RegisterType::I;
109 return true;
110 default:
111 return false;
112 }
113}
114
116 switch (RT) {
117 case RegisterType::SRV:
118 return ResourceClass::SRV;
119 case RegisterType::UAV:
120 return ResourceClass::UAV;
121 case RegisterType::CBuffer:
122 return ResourceClass::CBuffer;
123 case RegisterType::Sampler:
124 return ResourceClass::Sampler;
125 case RegisterType::C:
126 case RegisterType::I:
127
128 break;
129 }
130 llvm_unreachable("unexpected RegisterType value");
131}
132
134 const auto *BT = dyn_cast(Type);
135 if (!BT) {
138 return Builtin::BI__builtin_get_spirv_spec_constant_int;
139 }
140
141 switch (BT->getKind()) {
142 case BuiltinType::Bool:
143 return Builtin::BI__builtin_get_spirv_spec_constant_bool;
144 case BuiltinType::Short:
145 return Builtin::BI__builtin_get_spirv_spec_constant_short;
146 case BuiltinType::Int:
147 return Builtin::BI__builtin_get_spirv_spec_constant_int;
148 case BuiltinType::LongLong:
149 return Builtin::BI__builtin_get_spirv_spec_constant_longlong;
150 case BuiltinType::UShort:
151 return Builtin::BI__builtin_get_spirv_spec_constant_ushort;
152 case BuiltinType::UInt:
153 return Builtin::BI__builtin_get_spirv_spec_constant_uint;
154 case BuiltinType::ULongLong:
155 return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;
156 case BuiltinType::Half:
157 return Builtin::BI__builtin_get_spirv_spec_constant_half;
158 case BuiltinType::Float:
159 return Builtin::BI__builtin_get_spirv_spec_constant_float;
160 case BuiltinType::Double:
161 return Builtin::BI__builtin_get_spirv_spec_constant_double;
162 default:
164 }
165}
166
168 ResourceClass ResClass) {
170 "DeclBindingInfo already added");
172
173
174
175
176 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
177 return &BindingsList.emplace_back(VD, ResClass);
178}
179
181 ResourceClass ResClass) {
182 auto Entry = DeclToBindingListIndex.find(VD);
183 if (Entry != DeclToBindingListIndex.end()) {
184 for (unsigned Index = Entry->getSecond();
185 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
186 ++Index) {
187 if (BindingsList[Index].ResClass == ResClass)
188 return &BindingsList[Index];
189 }
190 }
191 return nullptr;
192}
193
195 return DeclToBindingListIndex.contains(VD);
196}
197
199
204
207 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
208
209
210 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
211 : llvm::hlsl::ResourceClass::SRV;
212 Result->addAttr(HLSLResourceClassAttr::CreateImplicit(getASTContext(), RC));
213
216
218}
219
222
223 if (T->isArrayType() || T->isStructureType())
224 return 16;
225
226
229
230 assert(Context.getTypeSize(T) <= 64 &&
231 "Scalar bit widths larger than 64 not supported");
232
233
234 return Context.getTypeSize(T) / 8;
235}
236
237
238
241 constexpr unsigned CBufferAlign = 16;
242 if (const auto *RD = T->getAsRecordDecl()) {
243 unsigned Size = 0;
244 for (const FieldDecl *Field : RD->fields()) {
245 QualType Ty = Field->getType();
248
249
250
251 unsigned AlignSize = llvm::alignTo(Size, FieldAlign);
252 if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {
253 FieldAlign = CBufferAlign;
254 }
255
256 Size = llvm::alignTo(Size, FieldAlign);
257 Size += FieldSize;
258 }
259 return Size;
260 }
261
262 if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
263 unsigned ElementCount = AT->getSize().getZExtValue();
264 if (ElementCount == 0)
265 return 0;
266
267 unsigned ElementSize =
269 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
270 return AlignedElementSize * (ElementCount - 1) + ElementSize;
271 }
272
274 unsigned ElementCount = VT->getNumElements();
275 unsigned ElementSize =
277 return ElementSize * ElementCount;
278 }
279
280 return Context.getTypeSize(T) / 8;
281}
282
283
284
285
288
289
290
291 bool HasPackOffset = false;
292 bool HasNonPackOffset = false;
293 for (auto *Field : BufDecl->buffer_decls()) {
294 VarDecl *Var = dyn_cast(Field);
295 if (!Var)
296 continue;
297 if (Field->hasAttr()) {
298 PackOffsetVec.emplace_back(Var, Field->getAttr());
299 HasPackOffset = true;
300 } else {
301 HasNonPackOffset = true;
302 }
303 }
304
305 if (!HasPackOffset)
306 return;
307
308 if (HasNonPackOffset)
309 S.Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);
310
311
312
313 bool IsValid = true;
315 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
316 [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
317 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
318 return LHS.second->getOffsetInBytes() <
319 RHS.second->getOffsetInBytes();
320 });
321 for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
322 VarDecl *Var = PackOffsetVec[i].first;
323 HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second;
325 unsigned Begin = Attr->getOffsetInBytes();
326 unsigned End = Begin + Size;
327 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
328 if (End > NextBegin) {
329 VarDecl *NextVar = PackOffsetVec[i + 1].first;
330 S.Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap)
331 << NextVar << Var;
332 IsValid = false;
333 }
334 }
336}
337
338
341 CAT = dyn_cast(
343 return CAT != nullptr;
344}
345
350
351static const HLSLAttributedResourceType *
354 "expected array of resource records");
356 while (const ArrayType *AT = dyn_cast(Ty))
358 return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);
359}
360
361
362
363
364
368 return true;
370 return RD->isEmpty();
373 return true;
375 return true;
376 return false;
377}
378
379
380
381
382
383
386 return true;
387
389 QualType Ty = Field->getType();
391 return true;
394 return true;
395 }
396
399 Base.getType()->castAsCXXRecordDecl()))
400 return true;
401 return false;
402}
403
410 assert(RD == nullptr &&
411 "there should be at most 1 record by a given name in a scope");
412 RD = FoundRD;
413 }
414 }
415 return RD;
416}
417
418
419
420
422 bool MustBeUnique) {
424
427 if (NameBaseII) {
428 Name.append(NameBaseII->getName());
429 } else {
430
431 Name.append("anon");
432 MustBeUnique = true;
433 }
434
435 size_t NameLength = Name.size();
437 if (!MustBeUnique)
438 return II;
439
440 unsigned suffix = 0;
441 while (true) {
442 if (suffix != 0) {
443 Name.append("_");
444 Name.append(llvm::Twine(suffix).str());
445 II = &AST.Idents.get(Name, tok::TokenKind::identifier);
446 }
448 return II;
449
450
451 suffix++;
452 Name.truncate(NameLength);
453 };
454}
455
456
457
462 return nullptr;
463
467 if (!RD)
468 return nullptr;
470 }
471 }
472
480 return Field;
481}
482
483
484
485
486
487
488
489
493 "struct is already HLSL buffer compatible");
494
498
499
501 return RD;
502
507 LS->addAttr(PackedAttr::CreateImplicit(AST));
509
510
511 if (unsigned NumBases = StructDecl->getNumBases()) {
512 assert(NumBases == 1 && "HLSL supports only one base type");
513 (void)NumBases;
518 if (BaseDecl) {
523 }
524 }
525 if (BaseDecl) {
528 }
529 }
530
531
537 }
539
541 return nullptr;
542
544 return LS;
545}
546
547
548
549
550
551
552
553
554
558
562 LS->addAttr(PackedAttr::CreateImplicit(AST));
565
567 VarDecl *VD = dyn_cast(D);
570 continue;
574
576
580 }
581 }
584}
585
587 uint32_t ImplicitBindingOrderID) {
589 HLSLResourceBindingAttr::CreateImplicit(S.getASTContext(), "", "0", {});
590 Attr->setBinding(RT, std::nullopt, 0);
591 Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);
593}
594
595
598 BufDecl->setRBraceLoc(RBrace);
599
601
603
604
608
609
610 uint32_t OrderID = getNextImplicitBindingOrderID();
613 else
615 BufDecl->isCBuffer() ? RegisterType::CBuffer
616 : RegisterType::SRV,
617 OrderID);
618 }
619
620 SemaRef.PopDeclContext();
621}
622
625 int X, int Y, int Z) {
626 if (HLSLNumThreadsAttr *NT = D->getAttr()) {
627 if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) {
628 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
629 Diag(AL.getLoc(), diag::note_conflicting_attribute);
630 }
631 return nullptr;
632 }
635}
636
639 int Min, int Max, int Preferred,
640 int SpelledArgsCount) {
641 if (HLSLWaveSizeAttr *WS = D->getAttr()) {
642 if (WS->getMin() != Min || WS->getMax() != Max ||
643 WS->getPreferred() != Preferred ||
644 WS->getSpelledArgsCount() != SpelledArgsCount) {
645 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
646 Diag(AL.getLoc(), diag::note_conflicting_attribute);
647 }
648 return nullptr;
649 }
652 Result->setSpelledArgsCount(SpelledArgsCount);
654}
655
656HLSLVkConstantIdAttr *
658 int Id) {
659
662 Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
663 return nullptr;
664 }
665
667
670 Diag(VD->getLocation(), diag::err_specialization_const);
671 return nullptr;
672 }
673
674 if (!VD->getType().isConstQualified()) {
675 Diag(VD->getLocation(), diag::err_specialization_const);
676 return nullptr;
677 }
678
679 if (HLSLVkConstantIdAttr *CI = D->getAttr()) {
680 if (CI->getId() != Id) {
681 Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
682 Diag(AL.getLoc(), diag::note_conflicting_attribute);
683 }
684 return nullptr;
685 }
686
687 HLSLVkConstantIdAttr *Result =
690}
691
692HLSLShaderAttr *
694 llvm::Triple::EnvironmentType ShaderType) {
695 if (HLSLShaderAttr *NT = D->getAttr()) {
696 if (NT->getType() != ShaderType) {
697 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
698 Diag(AL.getLoc(), diag::note_conflicting_attribute);
699 }
700 return nullptr;
701 }
702 return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL);
703}
704
705HLSLParamModifierAttr *
707 HLSLParamModifierAttr::Spelling Spelling) {
708
709
710 if (HLSLParamModifierAttr *PA = D->getAttr()) {
711 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
712 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
713 D->dropAttr();
715 return HLSLParamModifierAttr::Create(
716 getASTContext(), true, AdjustedRange,
717 HLSLParamModifierAttr::Keyword_inout);
718 }
719 Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
720 Diag(PA->getLocation(), diag::note_conflicting_attribute);
721 return nullptr;
722 }
723 return HLSLParamModifierAttr::Create(getASTContext(), AL);
724}
725
728
730 return;
731
732
733
736 if (SignatureDecl) {
737 FD->dropAttr();
738
740 SourceRange(), ParsedAttr::Form::Microsoft());
742 getASTContext(), AL, RootSigOverrideIdent, SignatureDecl));
743 }
744
745 llvm::Triple::EnvironmentType Env = TargetInfo.getTriple().getEnvironment();
746 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
747 if (const auto *Shader = FD->getAttr()) {
748
749
750 if (Shader->getType() != Env) {
751 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
752 << Shader;
754 }
755 } else {
756
757
760 }
761 } else {
762 switch (Env) {
763 case llvm::Triple::UnknownEnvironment:
764 case llvm::Triple::Library:
765 break;
766 case llvm::Triple::RootSignature:
767 llvm_unreachable("rootsig environment has no functions");
768 default:
769 llvm_unreachable("Unhandled environment in triple");
770 }
771 }
772}
773
775 HLSLAppliedSemanticAttr *Semantic,
776 bool IsInput) {
778 return false;
779
780 const auto *ShaderAttr = FD->getAttr();
781 assert(ShaderAttr && "Entry point has no shader attribute");
782 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
783 auto SemanticName = Semantic->getSemanticName().upper();
784
785
786
787
788 if (SemanticName == "SV_POSITION") {
789 return (ST == llvm::Triple::Vertex && !IsInput) ||
790 (ST == llvm::Triple::Pixel && IsInput);
791 }
792
793 return false;
794}
795
796bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD,
799 SemanticInfo &ActiveSemantic,
800 SemaHLSL::SemanticContext &SC) {
801 if (ActiveSemantic.Semantic == nullptr) {
802 ActiveSemantic.Semantic = D->getAttr();
803 if (ActiveSemantic.Semantic)
804 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
805 }
806
807 if (!ActiveSemantic.Semantic) {
808 Diag(D->getLocation(), diag::err_hlsl_missing_semantic_annotation);
809 return false;
810 }
811
813 HLSLAppliedSemanticAttr(getASTContext(), *ActiveSemantic.Semantic,
814 ActiveSemantic.Semantic->getAttrName()->getName(),
815 ActiveSemantic.Index.value_or(0));
816 if (!A)
818
819 checkSemanticAnnotation(FD, D, A, SC);
820 OutputDecl->addAttr(A);
821
822 unsigned Location = ActiveSemantic.Index.value_or(0);
823
825 SC.CurrentIOType & IOType::In)) {
826 bool HasVkLocation = false;
827 if (auto *A = D->getAttr()) {
828 HasVkLocation = true;
829 Location = A->getLocation();
830 }
831
832 if (SC.UsesExplicitVkLocations.value_or(HasVkLocation) != HasVkLocation) {
833 Diag(D->getLocation(), diag::err_hlsl_semantic_partial_explicit_indexing);
834 return false;
835 }
836 SC.UsesExplicitVkLocations = HasVkLocation;
837 }
838
839 const ConstantArrayType *AT = dyn_cast(D->getType());
840 unsigned ElementCount = AT ? AT->getZExtSize() : 1;
841 ActiveSemantic.Index = Location + ElementCount;
842
843 Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());
844 for (unsigned I = 0; I < ElementCount; ++I) {
845 Twine VariableName = BaseName.concat(Twine(Location + I));
846
847 auto [_, Inserted] = SC.ActiveSemantics.insert(VariableName.str());
848 if (!Inserted) {
849 Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
850 << VariableName.str();
851 return false;
852 }
853 }
854
855 return true;
856}
857
858bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,
861 SemanticInfo &ActiveSemantic,
862 SemaHLSL::SemanticContext &SC) {
863 if (ActiveSemantic.Semantic == nullptr) {
864 ActiveSemantic.Semantic = D->getAttr();
865 if (ActiveSemantic.Semantic)
866 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
867 }
868
871
872 const RecordType *RT = dyn_cast(T);
873 if (!RT)
874 return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
875 SC);
876
877 const RecordDecl *RD = RT->getDecl();
878 for (FieldDecl *Field : RD->fields()) {
879 SemanticInfo Info = ActiveSemantic;
880 if (!determineActiveSemantic(FD, OutputDecl, Field, Info, SC)) {
881 Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field;
882 return false;
883 }
884 if (ActiveSemantic.Semantic)
885 ActiveSemantic = Info;
886 }
887
888 return true;
889}
890
892 const auto *ShaderAttr = FD->getAttr();
893 assert(ShaderAttr && "Entry point has no shader attribute");
894 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
897 switch (ST) {
898 case llvm::Triple::Pixel:
899 case llvm::Triple::Vertex:
900 case llvm::Triple::Geometry:
901 case llvm::Triple::Hull:
902 case llvm::Triple::Domain:
903 case llvm::Triple::RayGeneration:
904 case llvm::Triple::Intersection:
905 case llvm::Triple::AnyHit:
906 case llvm::Triple::ClosestHit:
907 case llvm::Triple::Miss:
908 case llvm::Triple::Callable:
909 if (const auto *NT = FD->getAttr()) {
910 diagnoseAttrStageMismatch(NT, ST,
911 {llvm::Triple::Compute,
912 llvm::Triple::Amplification,
913 llvm::Triple::Mesh});
915 }
916 if (const auto *WS = FD->getAttr()) {
917 diagnoseAttrStageMismatch(WS, ST,
918 {llvm::Triple::Compute,
919 llvm::Triple::Amplification,
920 llvm::Triple::Mesh});
922 }
923 break;
924
925 case llvm::Triple::Compute:
926 case llvm::Triple::Amplification:
927 case llvm::Triple::Mesh:
928 if (!FD->hasAttr()) {
929 Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads)
930 << llvm::Triple::getEnvironmentTypeName(ST);
932 }
933 if (const auto *WS = FD->getAttr()) {
934 if (Ver < VersionTuple(6, 6)) {
935 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
936 << WS << "6.6";
938 } else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
940 WS->getLocation(),
941 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
942 << WS << WS->getSpelledArgsCount() << "6.8";
944 }
945 }
946 break;
947 case llvm::Triple::RootSignature:
948 llvm_unreachable("rootsig environment has no function entry point");
949 default:
950 llvm_unreachable("Unhandled environment in triple");
951 }
952
953 SemaHLSL::SemanticContext InputSC = {};
954 InputSC.CurrentIOType = IOType::In;
955
957 SemanticInfo ActiveSemantic;
958 ActiveSemantic.Semantic = Param->getAttr();
959 if (ActiveSemantic.Semantic)
960 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
961
962
963 if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, InputSC)) {
964 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
966 }
967 }
968
969 SemanticInfo ActiveSemantic;
970 SemaHLSL::SemanticContext OutputSC = {};
971 OutputSC.CurrentIOType = IOType::Out;
972 ActiveSemantic.Semantic = FD->getAttr();
973 if (ActiveSemantic.Semantic)
974 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
976 determineActiveSemantic(FD, FD, FD, ActiveSemantic, OutputSC);
977}
978
979void SemaHLSL::checkSemanticAnnotation(
981 const HLSLAppliedSemanticAttr *SemanticAttr, const SemanticContext &SC) {
982 auto *ShaderAttr = EntryPoint->getAttr();
983 assert(ShaderAttr && "Entry point has no shader attribute");
984 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
985
986 auto SemanticName = SemanticAttr->getSemanticName().upper();
987 if (SemanticName == "SV_DISPATCHTHREADID" ||
988 SemanticName == "SV_GROUPINDEX" || SemanticName == "SV_GROUPTHREADID" ||
989 SemanticName == "SV_GROUPID") {
990
991 if (ST != llvm::Triple::Compute)
992 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
993 {{llvm::Triple::Compute, IOType::In}});
994
995 if (SemanticAttr->getSemanticIndex() != 0) {
996 std::string PrettyName =
997 "'" + SemanticAttr->getSemanticName().str() + "'";
998 Diag(SemanticAttr->getLoc(),
999 diag::err_hlsl_semantic_indexing_not_supported)
1000 << PrettyName;
1001 }
1002 return;
1003 }
1004
1005 if (SemanticName == "SV_POSITION") {
1006
1007
1008 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1009 {{llvm::Triple::Vertex, IOType::InOut},
1010 {llvm::Triple::Pixel, IOType::In}});
1011 return;
1012 }
1013
1014 if (SemanticName == "SV_TARGET") {
1015 diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
1016 {{llvm::Triple::Pixel, IOType::Out}});
1017 return;
1018 }
1019
1020
1021
1022 if (SemanticAttr->getAttrName()->getName().starts_with_insensitive("SV_"))
1023 llvm_unreachable("Unknown SemanticAttr");
1024}
1025
1026void SemaHLSL::diagnoseAttrStageMismatch(
1027 const Attr *A, llvm::Triple::EnvironmentType Stage,
1028 std::initializer_listllvm::Triple::EnvironmentType AllowedStages) {
1029 SmallVector<StringRef, 8> StageStrings;
1030 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
1031 [](llvm::Triple::EnvironmentType ST) {
1032 return StringRef(
1033 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
1034 });
1035 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1036 << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1037 << (AllowedStages.size() != 1) << join(StageStrings, ", ");
1038}
1039
1040void SemaHLSL::diagnoseSemanticStageMismatch(
1041 const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
1042 std::initializer_list Allowed) {
1043
1044 for (auto &Case : Allowed) {
1045 if (Case.Stage != Stage)
1046 continue;
1047
1048 if (CurrentIOType & Case.AllowedIOTypesMask)
1049 return;
1050
1051 SmallVector<std::string, 8> ValidCases;
1052 llvm::transform(
1053 Allowed, std::back_inserter(ValidCases), [](SemanticStageInfo Case) {
1054 SmallVector<std::string, 2> ValidType;
1055 if (Case.AllowedIOTypesMask & IOType::In)
1056 ValidType.push_back("input");
1057 if (Case.AllowedIOTypesMask & IOType::Out)
1058 ValidType.push_back("output");
1059 return std::string(
1060 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage)) +
1061 " " + join(ValidType, "/");
1062 });
1063 Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
1064 << A->getAttrName() << (CurrentIOType & IOType::In ? "input" : "output")
1065 << llvm::Triple::getEnvironmentTypeName(Case.Stage)
1066 << join(ValidCases, ", ");
1067 return;
1068 }
1069
1070 SmallVector<StringRef, 8> StageStrings;
1071 llvm::transform(
1072 Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {
1073 return StringRef(
1074 HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
1075 });
1076
1077 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
1078 << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
1079 << (Allowed.size() != 1) << join(StageStrings, ", ");
1080}
1081
1082template
1085 Ty = VTy->getElementType();
1088}
1089
1090template
1095
1101
1102 if (LHSFloat && RHSFloat) {
1103 if (IsCompAssign ||
1106
1108 }
1109
1110 if (LHSFloat)
1112
1113 assert(RHSFloat);
1114 if (IsCompAssign)
1116
1118}
1119
1123
1128
1129
1130 if (LHSSigned == RHSSigned) {
1131 if (IsCompAssign || IntOrder >= 0)
1133
1135 }
1136
1137
1138
1139 if (IntOrder != (LHSSigned ? 1 : -1)) {
1140 if (IsCompAssign || RHSSigned)
1143 }
1144
1145
1146
1147
1148 if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
1149 if (IsCompAssign || LHSSigned)
1152 }
1153
1154
1155
1156
1157
1158
1159
1160
1161 if (IsCompAssign)
1163
1164
1165 QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);
1166 QualType NewTy = Ctx.getExtVectorType(
1169
1171}
1172
1176 return CK_FloatingCast;
1178 return CK_IntegralCast;
1180 return CK_IntegralToFloating;
1182 return CK_FloatingToIntegral;
1183}
1184
1188 bool IsCompAssign) {
1192
1193
1194
1195 if (!LVecTy && IsCompAssign) {
1197 RHS = SemaRef.ImpCastExprToType(RHS.get(), RElTy, CK_HLSLVectorTruncation);
1199 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1200 return LHSType;
1201 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSType,
1203 return LHSType;
1204 }
1205
1206 unsigned EndSz = std::numeric_limits::max();
1207 unsigned LSz = 0;
1208 if (LVecTy)
1209 LSz = EndSz = LVecTy->getNumElements();
1210 if (RVecTy)
1212 assert(EndSz != std::numeric_limits::max() &&
1213 "one of the above should have had a value");
1214
1215
1216
1217 if (IsCompAssign && LSz != EndSz) {
1219 diag::err_hlsl_vector_compound_assignment_truncation)
1220 << LHSType << RHSType;
1222 }
1223
1226 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
1228
1229 if (!RVecTy)
1231 if (!IsCompAssign && !LVecTy)
1233
1234
1235 if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))
1236 return Ctx.getCommonSugaredType(LHSType, RHSType);
1237
1240
1241
1244 LElTy, RElTy, IsCompAssign);
1245
1247 "HLSL Vectors can only contain integer or floating point types");
1249 LElTy, RElTy, IsCompAssign);
1250}
1251
1254 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
1255 "Called with non-logical operator");
1257 llvm::raw_svector_ostream OS(Buff);
1259 StringRef NewFnName = Opc == BO_LOr ? "or" : "and";
1260 OS << NewFnName << "(";
1262 OS << ", ";
1264 OS << ")";
1268}
1269
1270std::pair<IdentifierInfo *, bool>
1273 std::string IdStr = "__hlsl_rootsig_decl_" + std::to_string(Hash);
1275
1276
1280 return {DeclIdent, Found};
1281}
1282
1286
1288 return;
1289
1291 for (auto &RootSigElement : RootElements)
1292 Elements.push_back(RootSigElement.getElement());
1293
1295 SemaRef.getASTContext(), SemaRef.CurContext, Loc,
1296 DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements);
1297
1298 SignatureDecl->setImplicit();
1299 SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope());
1300}
1301
1304 if (RootSigOverrideIdent) {
1307 if (SemaRef.LookupQualifiedName(R, DC))
1308 return dyn_cast(R.getFoundDecl());
1309 }
1310
1311 return nullptr;
1312}
1313
1314namespace {
1315
1316struct PerVisibilityBindingChecker {
1318
1319 std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;
1320
1321 struct ElemInfo {
1323 llvm::dxbc::ShaderVisibility Vis;
1324 bool Diagnosed;
1325 };
1327
1328 PerVisibilityBindingChecker(SemaHLSL *S) : S(S) {}
1329
1330 void trackBinding(llvm::dxbc::ShaderVisibility Visibility,
1331 llvm::dxil::ResourceClass RC, uint32_t Space,
1332 uint32_t LowerBound, uint32_t UpperBound,
1333 const hlsl::RootSignatureElement *Elem) {
1335 assert(BuilderIndex < Builders.size() &&
1336 "Not enough builders for visibility type");
1337 Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,
1338 static_cast<const void *>(Elem));
1339
1340 static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,
1341 "'All' visibility must come first");
1342 if (Visibility == llvm::dxbc::ShaderVisibility::All)
1343 for (size_t I = 1, E = Builders.size(); I < E; ++I)
1344 Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,
1345 static_cast<const void *>(Elem));
1346
1347 ElemInfoMap.push_back({Elem, Visibility, false});
1348 }
1349
1350 ElemInfo &getInfo(const hlsl::RootSignatureElement *Elem) {
1351 auto It = llvm::lower_bound(
1352 ElemInfoMap, Elem,
1353 [](const auto &LHS, const auto &RHS) { return LHS.Elem < RHS; });
1354 assert(It->Elem == Elem && "Element not in map");
1355 return *It;
1356 }
1357
1358 bool checkOverlap() {
1359 llvm::sort(ElemInfoMap, [](const auto &LHS, const auto &RHS) {
1360 return LHS.Elem < RHS.Elem;
1361 });
1362
1363 bool HadOverlap = false;
1364
1365 using llvm::hlsl::BindingInfoBuilder;
1366 auto ReportOverlap = [this,
1367 &HadOverlap](const BindingInfoBuilder &Builder,
1368 const llvm::hlsl::Binding &Reported) {
1369 HadOverlap = true;
1370
1371 const auto *Elem =
1372 static_cast<const hlsl::RootSignatureElement *>(Reported.Cookie);
1373 const llvm::hlsl::Binding &Previous = Builder.findOverlapping(Reported);
1374 const auto *PrevElem =
1375 static_cast<const hlsl::RootSignatureElement *>(Previous.Cookie);
1376
1377 ElemInfo &Info = getInfo(Elem);
1378
1379
1380 if (Info.Diagnosed)
1381 return;
1382 Info.Diagnosed = true;
1383
1384 ElemInfo &PrevInfo = getInfo(PrevElem);
1385 llvm::dxbc::ShaderVisibility CommonVis =
1386 Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis
1387 : Info.Vis;
1388
1389 this->S->Diag(Elem->getLocation(), diag::err_hlsl_resource_range_overlap)
1390 << llvm::to_underlying(Reported.RC) << Reported.LowerBound
1391 << Reported.isUnbounded() << Reported.UpperBound
1393 << Previous.isUnbounded() << Previous.UpperBound << Reported.Space
1394 << CommonVis;
1395
1396 this->S->Diag(PrevElem->getLocation(),
1397 diag::note_hlsl_resource_range_here);
1398 };
1399
1400 for (BindingInfoBuilder &Builder : Builders)
1401 Builder.calculateBindingInfo(ReportOverlap);
1402
1403 return HadOverlap;
1404 }
1405};
1406
1412 return nullptr;
1414}
1415
1416}
1417
1420 return false;
1423 return false;
1424 const FieldDecl *SecondField = *It;
1425 if (const auto *ResTy =
1426 SecondField->getType()->getAs()) {
1427 return ResTy->getAttrs().IsCounter;
1428 }
1429 return false;
1430}
1431
1434
1435 bool HadError = false;
1436 auto ReportError = [this, &HadError](SourceLocation Loc, uint32_t LowerBound,
1437 uint32_t UpperBound) {
1438 HadError = true;
1439 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1440 << LowerBound << UpperBound;
1441 };
1442
1443 auto ReportFloatError = [this, &HadError](SourceLocation Loc,
1444 float LowerBound,
1445 float UpperBound) {
1446 HadError = true;
1447 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)
1448 << llvm::formatv("{0:f}", LowerBound).sstr<6>()
1449 << llvm::formatv("{0:f}", UpperBound).sstr<6>();
1450 };
1451
1452 auto VerifyRegister = [ReportError](SourceLocation Loc, uint32_t Register) {
1453 if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))
1454 ReportError(Loc, 0, 0xfffffffe);
1455 };
1456
1457 auto VerifySpace = [ReportError](SourceLocation Loc, uint32_t Space) {
1458 if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))
1459 ReportError(Loc, 0, 0xffffffef);
1460 };
1461
1462 const uint32_t Version =
1463 llvm::to_underlying(SemaRef.getLangOpts().HLSLRootSigVer);
1464 const uint32_t VersionEnum = Version - 1;
1465 auto ReportFlagError = [this, &HadError, VersionEnum](SourceLocation Loc) {
1466 HadError = true;
1467 this->Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)
1468 << VersionEnum;
1469 };
1470
1471
1474 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();
1475 if (const auto *Descriptor =
1476 std::get_ifllvm::hlsl::rootsig::RootDescriptor(&Elem)) {
1477 VerifyRegister(Loc, Descriptor->Reg.Number);
1478 VerifySpace(Loc, Descriptor->Space);
1479
1480 if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,
1481 Descriptor->Flags))
1482 ReportFlagError(Loc);
1483 } else if (const auto *Constants =
1484 std::get_ifllvm::hlsl::rootsig::RootConstants(&Elem)) {
1485 VerifyRegister(Loc, Constants->Reg.Number);
1486 VerifySpace(Loc, Constants->Space);
1487 } else if (const auto *Sampler =
1488 std::get_ifllvm::hlsl::rootsig::StaticSampler(&Elem)) {
1489 VerifyRegister(Loc, Sampler->Reg.Number);
1490 VerifySpace(Loc, Sampler->Space);
1491
1493 "By construction, parseFloatParam can't produce a NaN from a "
1494 "float_literal token");
1495
1496 if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))
1497 ReportError(Loc, 0, 16);
1498 if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))
1499 ReportFloatError(Loc, -16.f, 15.99f);
1500 } else if (const auto *Clause =
1501 std::get_ifllvm::hlsl::rootsig::DescriptorTableClause(
1502 &Elem)) {
1503 VerifyRegister(Loc, Clause->Reg.Number);
1504 VerifySpace(Loc, Clause->Space);
1505
1506 if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {
1507
1508
1509
1510 ReportError(Loc, 1, 0xfffffffe);
1511 }
1512
1513 if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,
1514 Clause->Flags))
1515 ReportFlagError(Loc);
1516 }
1517 }
1518
1519 PerVisibilityBindingChecker BindingChecker(this);
1520 SmallVector<std::pair<const llvm::hlsl::rootsig::DescriptorTableClause *,
1522 UnboundClauses;
1523
1525 const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();
1526 if (const auto *Descriptor =
1527 std::get_ifllvm::hlsl::rootsig::RootDescriptor(&Elem)) {
1528 uint32_t LowerBound(Descriptor->Reg.Number);
1529 uint32_t UpperBound(LowerBound);
1530
1531 BindingChecker.trackBinding(
1532 Descriptor->Visibility,
1533 static_castllvm::dxil::ResourceClass\(Descriptor->Type),
1534 Descriptor->Space, LowerBound, UpperBound, &RootSigElem);
1535 } else if (const auto *Constants =
1536 std::get_ifllvm::hlsl::rootsig::RootConstants(&Elem)) {
1537 uint32_t LowerBound(Constants->Reg.Number);
1538 uint32_t UpperBound(LowerBound);
1539
1540 BindingChecker.trackBinding(
1541 Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,
1542 Constants->Space, LowerBound, UpperBound, &RootSigElem);
1543 } else if (const auto *Sampler =
1544 std::get_ifllvm::hlsl::rootsig::StaticSampler(&Elem)) {
1545 uint32_t LowerBound(Sampler->Reg.Number);
1546 uint32_t UpperBound(LowerBound);
1547
1548 BindingChecker.trackBinding(
1549 Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,
1550 Sampler->Space, LowerBound, UpperBound, &RootSigElem);
1551 } else if (const auto *Clause =
1552 std::get_ifllvm::hlsl::rootsig::DescriptorTableClause(
1553 &Elem)) {
1554
1555 UnboundClauses.emplace_back(Clause, &RootSigElem);
1556 } else if (const auto *Table =
1557 std::get_ifllvm::hlsl::rootsig::DescriptorTable(&Elem)) {
1558 assert(UnboundClauses.size() == Table->NumClauses &&
1559 "Number of unbound elements must match the number of clauses");
1560 bool HasAnySampler = false;
1561 bool HasAnyNonSampler = false;
1562 uint64_t Offset = 0;
1563 bool IsPrevUnbound = false;
1564 for (const auto &[Clause, ClauseElem] : UnboundClauses) {
1566 if (Clause->Type == llvm::dxil::ResourceClass::Sampler)
1567 HasAnySampler = true;
1568 else
1569 HasAnyNonSampler = true;
1570
1571 if (HasAnySampler && HasAnyNonSampler)
1572 Diag(Loc, diag::err_hlsl_invalid_mixed_resources);
1573
1574
1575
1576
1577 if (Clause->NumDescriptors == 0)
1578 return true;
1579
1580 bool IsAppending =
1581 Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;
1582 if (!IsAppending)
1583 Offset = Clause->Offset;
1584
1585 uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(
1586 Offset, Clause->NumDescriptors);
1587
1588 if (IsPrevUnbound && IsAppending)
1589 Diag(Loc, diag::err_hlsl_appending_onto_unbound);
1590 else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))
1591 Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;
1592
1593
1594 Offset = RangeBound + 1;
1595 IsPrevUnbound = Clause->NumDescriptors ==
1596 llvm::hlsl::rootsig::NumDescriptorsUnbounded;
1597
1598
1599 uint32_t LowerBound(Clause->Reg.Number);
1600 uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(
1601 LowerBound, Clause->NumDescriptors);
1602
1603 BindingChecker.trackBinding(
1604 Table->Visibility,
1605 static_castllvm::dxil::ResourceClass\(Clause->Type), Clause->Space,
1606 LowerBound, UpperBound, ClauseElem);
1607 }
1608 UnboundClauses.clear();
1609 }
1610 }
1611
1612 return BindingChecker.checkOverlap();
1613}
1614
1617 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1618 return;
1619 }
1620
1622 if (auto *RS = D->getAttr()) {
1623 if (RS->getSignatureIdent() != Ident) {
1624 Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
1625 return;
1626 }
1627
1628 Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << RS;
1629 return;
1630 }
1631
1634 if (auto *SignatureDecl =
1635 dyn_cast(R.getFoundDecl())) {
1638 }
1639}
1640
1642 llvm::VersionTuple SMVersion =
1645 llvm::Triple::dxil;
1646
1647 uint32_t ZMax = 1024;
1648 uint32_t ThreadMax = 1024;
1649 if (IsDXIL && SMVersion.getMajor() <= 4) {
1650 ZMax = 1;
1651 ThreadMax = 768;
1652 } else if (IsDXIL && SMVersion.getMajor() == 5) {
1653 ZMax = 64;
1654 ThreadMax = 1024;
1655 }
1656
1657 uint32_t X;
1659 return;
1660 if (X > 1024) {
1662 diag::err_hlsl_numthreads_argument_oor)
1663 << 0 << 1024;
1664 return;
1665 }
1666 uint32_t Y;
1668 return;
1669 if (Y > 1024) {
1671 diag::err_hlsl_numthreads_argument_oor)
1672 << 1 << 1024;
1673 return;
1674 }
1675 uint32_t Z;
1677 return;
1678 if (Z > ZMax) {
1680 diag::err_hlsl_numthreads_argument_oor)
1681 << 2 << ZMax;
1682 return;
1683 }
1684
1685 if (X * Y * Z > ThreadMax) {
1686 Diag(AL.getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
1687 return;
1688 }
1689
1691 if (NewAttr)
1693}
1694
1696 return llvm::isPowerOf2_32(Value) && Value >= 4 && Value <= 128;
1697}
1698
1700
1701
1702 unsigned SpelledArgsCount = AL.getNumArgs();
1703 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
1704 return;
1705
1706 uint32_t Min;
1708 return;
1709
1710 uint32_t Max = 0;
1711 if (SpelledArgsCount > 1 &&
1713 return;
1714
1715 uint32_t Preferred = 0;
1716 if (SpelledArgsCount > 2 &&
1718 return;
1719
1720 if (SpelledArgsCount > 2) {
1723 diag::err_attribute_power_of_two_in_range)
1724 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
1725 << Preferred;
1726 return;
1727 }
1728
1729 if (Preferred < Min || Preferred > Max) {
1731 diag::err_attribute_power_of_two_in_range)
1732 << AL << Min << Max << Preferred;
1733 return;
1734 }
1735 } else if (SpelledArgsCount > 1) {
1738 diag::err_attribute_power_of_two_in_range)
1739 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Max;
1740 return;
1741 }
1743 Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
1744 return;
1746 Diag(AL.getLoc(), diag::warn_attr_min_eq_max) << AL;
1747 }
1748 } else {
1751 diag::err_attribute_power_of_two_in_range)
1752 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Min;
1753 return;
1754 }
1755 }
1756
1757 HLSLWaveSizeAttr *NewAttr =
1759 if (NewAttr)
1761}
1762
1764 uint32_t ID;
1766 return;
1768 HLSLVkExtBuiltinInputAttr(getASTContext(), AL, ID));
1769}
1770
1772 uint32_t Id;
1774 return;
1776 if (NewAttr)
1778}
1779
1781 uint32_t Binding = 0;
1783 return;
1784 uint32_t Set = 0;
1787 return;
1788
1791}
1792
1794 uint32_t Location;
1796 return;
1797
1799 HLSLVkLocationAttr(getASTContext(), AL, Location));
1800}
1801
1803 const auto *VT = T->getAs<VectorType>();
1804
1805 if (->hasUnsignedIntegerRepresentation() ||
1806 (VT && VT->getNumElements() > 3)) {
1807 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1808 << AL << "uint/uint2/uint3";
1809 return false;
1810 }
1811
1812 return true;
1813}
1814
1816 const auto *VT = T->getAs<VectorType>();
1817 if (->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
1818 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1819 << AL << "float/float1/float2/float3/float4";
1820 return false;
1821 }
1822
1823 return true;
1824}
1825
1827 std::optional Index) {
1829
1831 QualType ValueType = VD->getType();
1832 if (auto *FD = dyn_cast(D))
1834
1835 bool IsOutput = false;
1836 if (HLSLParamModifierAttr *MA = D->getAttr()) {
1837 if (MA->isOut()) {
1838 IsOutput = true;
1840 }
1841 }
1842
1843 if (SemanticName == "SV_DISPATCHTHREADID") {
1845 if (IsOutput)
1846 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1847 if (Index.has_value())
1848 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1850 return;
1851 }
1852
1853 if (SemanticName == "SV_GROUPINDEX") {
1854 if (IsOutput)
1855 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1856 if (Index.has_value())
1857 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1859 return;
1860 }
1861
1862 if (SemanticName == "SV_GROUPTHREADID") {
1864 if (IsOutput)
1865 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1866 if (Index.has_value())
1867 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1869 return;
1870 }
1871
1872 if (SemanticName == "SV_GROUPID") {
1874 if (IsOutput)
1875 Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
1876 if (Index.has_value())
1877 Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
1879 return;
1880 }
1881
1882 if (SemanticName == "SV_POSITION") {
1883 const auto *VT = ValueType->getAs<VectorType>();
1884 if (!ValueType->hasFloatingRepresentation() ||
1885 (VT && VT->getNumElements() > 4))
1886 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1887 << AL << "float/float1/float2/float3/float4";
1889 return;
1890 }
1891
1892 if (SemanticName == "SV_TARGET") {
1893 const auto *VT = ValueType->getAs<VectorType>();
1894 if (!ValueType->hasFloatingRepresentation() ||
1895 (VT && VT->getNumElements() > 4))
1896 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
1897 << AL << "float/float1/float2/float3/float4";
1899 return;
1900 }
1901
1902 Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
1903}
1904
1906 uint32_t IndexValue, ExplicitIndex;
1909 assert(IndexValue > 0 ? ExplicitIndex : true);
1910 std::optional Index =
1911 ExplicitIndex ? std::optional(IndexValue) : std::nullopt;
1912
1915 else
1917}
1918
1921 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)
1922 << AL << "shader constant in a constant buffer";
1923 return;
1924 }
1925
1926 uint32_t SubComponent;
1928 return;
1929 uint32_t Component;
1931 return;
1932
1934
1935
1936 bool IsAggregateTy = (T->isArrayType() || T->isStructureType());
1937
1938
1939 if (Component) {
1941 if (IsAggregateTy || Size > 128) {
1942 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1943 return;
1944 } else {
1945
1946 if ((Component * 32 + Size) > 128) {
1947 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
1948 return;
1949 }
1951 if (const auto *VT = T->getAs<VectorType>())
1952 EltTy = VT->getElementType();
1954 if (Align > 32 && Component == 1) {
1955
1956
1957 Diag(AL.getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
1958 << Align << EltTy;
1959 return;
1960 }
1961 }
1962 }
1963
1966}
1967
1969 StringRef Str;
1971 if (.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1972 return;
1973
1974 llvm::Triple::EnvironmentType ShaderType;
1975 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
1976 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1977 << AL << Str << ArgLoc;
1978 return;
1979 }
1980
1981
1982
1983 HLSLShaderAttr *NewAttr = mergeShaderAttr(D, AL, ShaderType);
1984 if (NewAttr)
1986}
1987
1991 assert(AttrList.size() && "expected list of resource attributes");
1992
1995 SourceLocation LocBegin = AttrList[0]->getRange().getBegin();
1996 SourceLocation LocEnd = AttrList[0]->getRange().getEnd();
1997
1998 HLSLAttributedResourceType::Attributes ResAttrs;
1999
2000 bool HasResourceClass = false;
2001 for (const Attr *A : AttrList) {
2002 if (!A)
2003 continue;
2006 case attr::HLSLResourceClass: {
2008 if (HasResourceClass) {
2010 ? diag::warn_duplicate_attribute_exact
2011 : diag::warn_duplicate_attribute)
2012 << A;
2013 return false;
2014 }
2015 ResAttrs.ResourceClass = RC;
2016 HasResourceClass = true;
2017 break;
2018 }
2019 case attr::HLSLROV:
2020 if (ResAttrs.IsROV) {
2021 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
2022 return false;
2023 }
2024 ResAttrs.IsROV = true;
2025 break;
2026 case attr::HLSLRawBuffer:
2027 if (ResAttrs.RawBuffer) {
2028 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
2029 return false;
2030 }
2031 ResAttrs.RawBuffer = true;
2032 break;
2033 case attr::HLSLIsCounter:
2034 if (ResAttrs.IsCounter) {
2035 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
2036 return false;
2037 }
2038 ResAttrs.IsCounter = true;
2039 break;
2040 case attr::HLSLContainedType: {
2042 QualType Ty = CTAttr->getType();
2043 if (!ContainedTy.isNull()) {
2045 ? diag::warn_duplicate_attribute_exact
2046 : diag::warn_duplicate_attribute)
2047 << A;
2048 return false;
2049 }
2050 ContainedTy = Ty;
2051 ContainedTyInfo = CTAttr->getTypeLoc();
2052 break;
2053 }
2054 default:
2055 llvm_unreachable("unhandled resource attribute type");
2056 }
2057 }
2058
2059 if (!HasResourceClass) {
2060 S.Diag(AttrList.back()->getRange().getEnd(),
2061 diag::err_hlsl_missing_resource_class);
2062 return false;
2063 }
2064
2066 Wrapped, ContainedTy, ResAttrs);
2067
2068 if (LocInfo && ContainedTyInfo) {
2071 }
2072 return true;
2073}
2074
2075
2076
2077
2078
2080
2081 if (->isHLSLResourceType()) {
2082 Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
2084 return false;
2085 }
2086
2087
2089 return false;
2090
2091 Attr *A = nullptr;
2092
2096 {
2097 AttributeCommonInfo::AS_CXX11, 0, false ,
2098 false
2099 });
2100
2102 case ParsedAttr::AT_HLSLResourceClass: {
2104 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2106 return false;
2107 }
2108
2112
2113
2114 ResourceClass RC;
2115 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
2116 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
2117 << "ResourceClass" << Identifier;
2118 return false;
2119 }
2120 A = HLSLResourceClassAttr::Create(getASTContext(), RC, ACI);
2121 break;
2122 }
2123
2124 case ParsedAttr::AT_HLSLROV:
2126 break;
2127
2128 case ParsedAttr::AT_HLSLRawBuffer:
2129 A = HLSLRawBufferAttr::Create(getASTContext(), ACI);
2130 break;
2131
2132 case ParsedAttr::AT_HLSLIsCounter:
2133 A = HLSLIsCounterAttr::Create(getASTContext(), ACI);
2134 break;
2135
2136 case ParsedAttr::AT_HLSLContainedType: {
2138 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
2139 return false;
2140 }
2141
2144 assert(TSI && "no type source info for attribute argument");
2146 diag::err_incomplete_type))
2147 return false;
2148 A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, ACI);
2149 break;
2150 }
2151
2152 default:
2153 llvm_unreachable("unhandled HLSL attribute");
2154 }
2155
2156 HLSLResourcesTypeAttrs.emplace_back(A);
2157 return true;
2158}
2159
2160
2162 if (!HLSLResourcesTypeAttrs.size())
2163 return CurrentType;
2164
2168 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
2169 const HLSLAttributedResourceType *RT =
2171
2172
2173
2174
2175
2176 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
2177 }
2178 HLSLResourcesTypeAttrs.clear();
2179 return QT;
2180}
2181
2182
2186 auto I = LocsForHLSLAttributedResources.find(RT);
2187 if (I != LocsForHLSLAttributedResources.end()) {
2188 LocInfo = I->second;
2189 LocsForHLSLAttributedResources.erase(I);
2190 return LocInfo;
2191 }
2193 return LocInfo;
2194}
2195
2196
2197
2198void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
2199 const RecordType *RT) {
2200 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
2203
2204
2205
2207 "incomplete arrays inside user defined types are not supported");
2211 }
2212
2214 continue;
2215
2216 if (const HLSLAttributedResourceType *AttrResType =
2217 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
2218
2219 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
2221 if (!DBI)
2222 Bindings.addDeclBindingInfo(VD, RC);
2223 } else if (const RecordType *RT = dyn_cast(Ty)) {
2224
2225
2226
2227
2228
2229 collectResourceBindingsOnUserRecordDecl(VD, RT);
2230 }
2231 }
2232}
2233
2234
2235
2236
2237
2238
2241 bool SpecifiedSpace) {
2242 int RegTypeNum = static_cast<int>(RegType);
2243
2244
2245 if (D->hasAttr()) {
2246 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2247 return false;
2248 }
2249
2250
2251 if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast(D)) {
2252 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
2253 : ResourceClass::SRV;
2255 return true;
2256
2257 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
2258 << RegTypeNum;
2259 return false;
2260 }
2261
2262
2263 assert(isa(D) && "D is expected to be VarDecl or HLSLBufferDecl");
2265
2266
2267 if (const HLSLAttributedResourceType *AttrResType =
2268 HLSLAttributedResourceType::findHandleTypeOnResource(
2271 return true;
2272
2273 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
2274 << RegTypeNum;
2275 return false;
2276 }
2277
2281
2282
2285 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
2286 S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
2287
2290
2291 if (RegType == RegisterType::CBuffer)
2292 S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
2293 else if (RegType != RegisterType::C)
2294 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2295 else
2296 return true;
2297 } else {
2298 if (RegType == RegisterType::C)
2299 S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
2300 else
2301 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2302 }
2303 return false;
2304 }
2306
2307
2308 return true;
2309
2310
2311 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
2312 return false;
2313}
2314
2317
2318
2319 bool RegisterTypesDetected[5] = {false};
2320 RegisterTypesDetected[static_cast<int>(regType)] = true;
2321
2322 for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {
2323 if (HLSLResourceBindingAttr *attr =
2324 dyn_cast(*it)) {
2325
2327 if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {
2328 int otherRegTypeNum = static_cast<int>(otherRegType);
2330 diag::err_hlsl_duplicate_register_annotation)
2331 << otherRegTypeNum;
2332 return false;
2333 }
2334 RegisterTypesDetected[static_cast<int>(otherRegType)] = true;
2335 }
2336 }
2337 return true;
2338}
2339
2342 bool SpecifiedSpace) {
2343
2344
2347 "expecting VarDecl or HLSLBufferDecl");
2348
2349
2351 return false;
2352
2353
2355}
2356
2358 if (VarDecl *VD = dyn_cast(TheDecl)) {
2360 if (const auto *IAT = dyn_cast(Ty))
2361 Ty = IAT->getElementType();
2363 diag::err_incomplete_type))
2364 return;
2365 }
2366
2367 StringRef Slot = "";
2368 StringRef Space = "";
2370
2372 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2374 return;
2375 }
2377
2380 SlotLoc = Loc->getLoc();
2382 Diag(AL.getLoc(), diag::err_attribute_argument_type)
2384 return;
2385 }
2388 SpaceLoc = Loc->getLoc();
2389 } else {
2391 if (Str.starts_with("space")) {
2392 Space = Str;
2393 SpaceLoc = Loc->getLoc();
2394 } else {
2395 Slot = Str;
2396 SlotLoc = Loc->getLoc();
2397 Space = "space0";
2398 }
2399 }
2400
2402 std::optional SlotNum;
2403 unsigned SpaceNum = 0;
2404
2405
2406 if (!Slot.empty()) {
2408 Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
2409 return;
2410 }
2411 if (RegType == RegisterType::I) {
2412 Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
2413 return;
2414 }
2415 StringRef SlotNumStr = Slot.substr(1);
2416 unsigned N;
2417 if (SlotNumStr.getAsInteger(10, N)) {
2418 Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
2419 return;
2420 }
2421 SlotNum = N;
2422 }
2423
2424
2425 if (!Space.starts_with("space")) {
2426 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2427 return;
2428 }
2429 StringRef SpaceNumStr = Space.substr(5);
2430 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
2431 Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
2432 return;
2433 }
2434
2435
2436 if (SlotNum.has_value())
2439 return;
2440
2441 HLSLResourceBindingAttr *NewAttr =
2442 HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);
2443 if (NewAttr) {
2444 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
2445 TheDecl->addAttr(NewAttr);
2446 }
2447}
2448
2451 D, AL,
2452 static_castHLSLParamModifierAttr::Spelling\(AL.getSemanticSpelling()));
2453 if (NewAttr)
2455}
2456
2457namespace {
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2472 Sema &SemaRef;
2473
2474
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
2500
2501
2502
2503 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
2504 unsigned CurrentShaderStageBit;
2505
2506
2507
2508
2509 bool ReportOnlyShaderStageIssues;
2510
2511
2512 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
2513 static_assert(sizeof(unsigned) >= 4);
2514 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
2515 assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
2516 "ShaderType is too big for this bitmap");
2517
2518
2519 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
2520 CurrentShaderEnvironment = ShaderType;
2521 CurrentShaderStageBit = (1 << bitmapIndex);
2522 }
2523
2524 void SetUnknownShaderStageContext() {
2525 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
2526 CurrentShaderStageBit = (1 << 31);
2527 }
2528
2529 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
2530 return CurrentShaderEnvironment;
2531 }
2532
2533 bool InUnknownShaderStageContext() const {
2534 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
2535 }
2536
2537
2538 void AddToScannedFunctions(const FunctionDecl *FD) {
2539 unsigned &ScannedStages = ScannedDecls[FD];
2540 ScannedStages |= CurrentShaderStageBit;
2541 }
2542
2543 unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }
2544
2545 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {
2546 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
2547 }
2548
2549 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {
2550 return ScannerStages & CurrentShaderStageBit;
2551 }
2552
2553 static bool NeverBeenScanned(unsigned ScannedStages) {
2554 return ScannedStages == 0;
2555 }
2556
2557
2558 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
2559 void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
2560 SourceRange Range);
2561 const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
2562 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
2563
2564public:
2565 DiagnoseHLSLAvailability(Sema &SemaRef)
2566 : SemaRef(SemaRef),
2567 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
2568 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}
2569
2570
2571 void RunOnTranslationUnit(const TranslationUnitDecl *TU);
2572 void RunOnFunction(const FunctionDecl *FD);
2573
2574 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
2575 FunctionDecl *FD = llvm::dyn_cast(DRE->getDecl());
2576 if (FD)
2577 HandleFunctionOrMethodRef(FD, DRE);
2578 return true;
2579 }
2580
2581 bool VisitMemberExpr(MemberExpr *ME) override {
2582 FunctionDecl *FD = llvm::dyn_cast(ME->getMemberDecl());
2583 if (FD)
2584 HandleFunctionOrMethodRef(FD, ME);
2585 return true;
2586 }
2587};
2588
2589void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
2590 Expr *RefExpr) {
2592 "expected DeclRefExpr or MemberExpr");
2593
2594
2596 if (FD->hasBody(FDWithBody)) {
2597 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
2598 DeclsToScan.push_back(FDWithBody);
2599 return;
2600 }
2601
2602
2603 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
2604 if (AA)
2605 CheckDeclAvailability(
2607}
2608
2609void DiagnoseHLSLAvailability::RunOnTranslationUnit(
2611
2612
2613
2614
2615
2616
2618 DeclContextsToScan.push_back(TU);
2619
2620 while (!DeclContextsToScan.empty()) {
2621 const DeclContext *DC = DeclContextsToScan.pop_back_val();
2622 for (auto &D : DC->decls()) {
2623
2625 continue;
2626
2627
2628
2629 if (llvm::dyn_cast(D) || llvm::dyn_cast(D)) {
2630 DeclContextsToScan.push_back(llvm::dyn_cast(D));
2631 continue;
2632 }
2633
2634
2635 const FunctionDecl *FD = llvm::dyn_cast(D);
2637 continue;
2638
2639
2640 if (HLSLShaderAttr *ShaderAttr = FD->getAttr()) {
2641 SetShaderStageContext(ShaderAttr->getType());
2642 RunOnFunction(FD);
2643 continue;
2644 }
2645
2646
2647
2649 if (!isExport) {
2650 for (const auto *Redecl : FD->redecls()) {
2651 if (Redecl->isInExportDeclContext()) {
2652 isExport = true;
2653 break;
2654 }
2655 }
2656 }
2657 if (isExport) {
2658 SetUnknownShaderStageContext();
2659 RunOnFunction(FD);
2660 continue;
2661 }
2662 }
2663 }
2664}
2665
2666void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
2667 assert(DeclsToScan.empty() && "DeclsToScan should be empty");
2668 DeclsToScan.push_back(FD);
2669
2670 while (!DeclsToScan.empty()) {
2671
2672
2673
2674
2675 const FunctionDecl *FD = DeclsToScan.pop_back_val();
2676
2677
2678 const unsigned ScannedStages = GetScannedStages(FD);
2679 if (WasAlreadyScannedInCurrentStage(ScannedStages))
2680 continue;
2681
2682 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
2683
2684 AddToScannedFunctions(FD);
2685 TraverseStmt(FD->getBody());
2686 }
2687}
2688
2689bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
2690 const AvailabilityAttr *AA) {
2691 IdentifierInfo *IIEnvironment = AA->getEnvironment();
2692 if (!IIEnvironment)
2693 return true;
2694
2695 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
2696 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
2697 return false;
2698
2699 llvm::Triple::EnvironmentType AttrEnv =
2700 AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
2701
2702 return CurrentEnv == AttrEnv;
2703}
2704
2705const AvailabilityAttr *
2706DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {
2707 AvailabilityAttr const *PartialMatch = nullptr;
2708
2709
2710
2711 for (const auto *A : D->attrs()) {
2712 if (const auto *Avail = dyn_cast(A)) {
2713 StringRef AttrPlatform = Avail->getPlatform()->getName();
2714 StringRef TargetPlatform =
2716
2717
2718 if (AttrPlatform == TargetPlatform) {
2719
2720 if (HasMatchingEnvironmentOrNone(Avail))
2721 return Avail;
2722 PartialMatch = Avail;
2723 }
2724 }
2725 }
2726 return PartialMatch;
2727}
2728
2729
2730
2731void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
2732 const AvailabilityAttr *AA,
2734
2736
2737 if (!IIEnv) {
2738
2739
2740
2741
2742
2743
2744
2745 if (SemaRef.getLangOpts().HLSLStrictAvailability)
2746 return;
2747
2748
2749
2750
2751 if (ReportOnlyShaderStageIssues)
2752 return;
2753
2754 } else {
2755
2756
2757 if (InUnknownShaderStageContext())
2758 return;
2759 }
2760
2761
2762 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
2763 VersionTuple Introduced = AA->getIntroduced();
2766
2767 if (TargetVersion >= Introduced && EnvironmentMatches)
2768 return;
2769
2770
2772 llvm::StringRef PlatformName(
2773 AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
2774
2775 llvm::StringRef CurrentEnvStr =
2776 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
2777
2778 llvm::StringRef AttrEnvStr =
2779 AA->getEnvironment() ? AA->getEnvironment()->getName() : "";
2780 bool UseEnvironment = !AttrEnvStr.empty();
2781
2782 if (EnvironmentMatches) {
2783 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)
2784 << Range << D << PlatformName << Introduced.getAsString()
2785 << UseEnvironment << CurrentEnvStr;
2786 } else {
2787 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)
2789 }
2790
2791 SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)
2792 << D << PlatformName << Introduced.getAsString()
2794 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
2795}
2796
2797}
2798
2800
2801 if (!DefaultCBufferDecls.empty()) {
2803 SemaRef.getASTContext(), SemaRef.getCurLexicalContext(),
2804 DefaultCBufferDecls);
2806 getNextImplicitBindingOrderID());
2807 SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
2809
2810
2811 for (const Decl *VD : DefaultCBufferDecls) {
2812 const HLSLResourceBindingAttr *RBA =
2813 VD->getAttr();
2814 if (RBA && RBA->hasRegisterSlot() &&
2815 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
2817 break;
2818 }
2819 }
2820
2822 SemaRef.Consumer.HandleTopLevelDecl(DG);
2823 }
2824 diagnoseAvailabilityViolations(TU);
2825}
2826
2828
2829
2830
2831
2834 TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
2835 return;
2836
2837 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);
2838}
2839
2843
2844 for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {
2847 S->Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
2848 << TheCall->getDirectCallee() << true
2851 return true;
2852 }
2853 }
2854 return false;
2855}
2856
2860 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
2862 return true;
2863 }
2864 return false;
2865}
2866
2869 llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,
2871 Check) {
2872 for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {
2875 return true;
2876 }
2877 return false;
2878}
2879
2881 int ArgOrdinal,
2886 : PassedType;
2887 if (!BaseType->isHalfType() && !BaseType->isFloat32Type())
2888 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2889 << ArgOrdinal << 5 << 0
2890 << 2 << PassedType;
2891 return false;
2892}
2893
2895 unsigned ArgIndex) {
2896 auto *Arg = TheCall->getArg(ArgIndex);
2898 if (Arg->IgnoreCasts()->isModifiableLvalue(S->Context, &OrigLoc) ==
2900 return false;
2901 S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
2902 return true;
2903}
2904
2908 if (!VecTy)
2909 return false;
2910
2911 if (VecTy->getElementType()->isDoubleType())
2912 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2913 << ArgOrdinal << 1 << 0 << 1
2914 << PassedType;
2915 return false;
2916}
2917
2919 int ArgOrdinal,
2923 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2924 << ArgOrdinal << 5 << 1
2925 << 1 << PassedType;
2926 return false;
2927}
2928
2930 int ArgOrdinal,
2933 if (VecTy->getElementType()->isUnsignedIntegerType())
2934 return false;
2935
2936 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2937 << ArgOrdinal << 4 << 3 << 0
2938 << PassedType;
2939}
2940
2941
2943 int ArgOrdinal,
2946 return S->Diag(Loc, diag::err_builtin_invalid_arg_type)
2947 << ArgOrdinal << 5 << 3
2948 << 0 << PassedType;
2949 return false;
2950}
2951
2953 unsigned ArgOrdinal, unsigned Width) {
2956 ArgTy = VTy->getElementType();
2957
2958 uint64_t ElementBitCount =
2960 if (ElementBitCount != Width) {
2962 diag::err_integer_incorrect_bit_count)
2963 << Width << ElementBitCount;
2964 return true;
2965 }
2966 return false;
2967}
2968
2972 if (VecTyA)
2973 ReturnType =
2975
2976 TheCall->setType(ReturnType);
2977}
2978
2980 unsigned ArgIndex) {
2981 assert(TheCall->getNumArgs() >= ArgIndex);
2984
2986 (VTy &&
2989 diag::err_typecheck_expect_scalar_or_vector)
2990 << ArgType << Scalar;
2991 return true;
2992 }
2993 return false;
2994}
2995
2997 unsigned ArgIndex) {
2998 assert(TheCall->getNumArgs() >= ArgIndex);
3001
3002 if (!(ArgType->isScalarType() ||
3003 (VTy && VTy->getElementType()->isScalarType()))) {
3005 diag::err_typecheck_expect_any_scalar_or_vector)
3006 << ArgType << 1;
3007 return true;
3008 }
3009 return false;
3010}
3011
3017
3019 (VTy &&
3022 diag::err_typecheck_expect_any_scalar_or_vector)
3023 << ArgType << 0;
3024 return true;
3025 }
3026 return false;
3027}
3028
3035 diag::err_typecheck_call_different_arg_types)
3038 return true;
3039 }
3040
3042 return false;
3043}
3044
3051
3052 QualType Arg1ScalarTy = Arg1Ty;
3054 Arg1ScalarTy = VTy->getElementType();
3055
3056 QualType Arg2ScalarTy = Arg2Ty;
3058 Arg2ScalarTy = VTy->getElementType();
3059
3061 S->Diag(Arg1->getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)
3062 << 1 << TheCall->getCallee() << Arg1Ty << Arg2Ty;
3063
3065 unsigned Arg0Length = Arg0Ty->getAs<VectorType>()->getNumElements();
3066 unsigned Arg1Length = Arg1Ty->isVectorType()
3068 : 0;
3069 unsigned Arg2Length = Arg2Ty->isVectorType()
3071 : 0;
3072 if (Arg1Length > 0 && Arg0Length != Arg1Length) {
3074 diag::err_typecheck_vector_lengths_not_equal)
3077 return true;
3078 }
3079
3080 if (Arg2Length > 0 && Arg0Length != Arg2Length) {
3082 diag::err_typecheck_vector_lengths_not_equal)
3085 return true;
3086 }
3087
3090 return false;
3091}
3092
3094 Sema *S, CallExpr *TheCall, unsigned ArgIndex,
3095 llvm::function_ref<bool(const HLSLAttributedResourceType *ResType)> Check =
3096 nullptr) {
3097 assert(TheCall->getNumArgs() >= ArgIndex);
3099 const HLSLAttributedResourceType *ResTy =
3100 ArgType.getTypePtr()->getAs();
3101 if (!ResTy) {
3103 diag::err_typecheck_expect_hlsl_resource)
3104 << ArgType;
3105 return true;
3106 }
3107 if (Check && Check(ResTy)) {
3109 diag::err_invalid_hlsl_resource_type)
3110 << ArgType;
3111 return true;
3112 }
3113 return false;
3114}
3115
3116
3117
3119 switch (BuiltinID) {
3120 case Builtin::BI__builtin_hlsl_adduint64: {
3121 if (SemaRef.checkArgCount(TheCall, 2))
3122 return true;
3123
3126 return true;
3127
3128
3130 return true;
3131
3132
3135 if (NumElementsArg != 2 && NumElementsArg != 4) {
3136 SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vector_incorrect_bit_count)
3137 << 1 << 64 << NumElementsArg * 32;
3138 return true;
3139 }
3140
3141
3143 return true;
3144
3147
3148 TheCall->setType(ArgTyA);
3149 break;
3150 }
3151 case Builtin::BI__builtin_hlsl_resource_getpointer: {
3152 if (SemaRef.checkArgCount(TheCall, 2) ||
3155 SemaRef.getASTContext().UnsignedIntTy))
3156 return true;
3157
3158 auto *ResourceTy =
3160 QualType ContainedTy = ResourceTy->getContainedType();
3161 auto ReturnType =
3163 ReturnType = SemaRef.Context.getPointerType(ReturnType);
3164 TheCall->setType(ReturnType);
3166
3167 break;
3168 }
3169 case Builtin::BI__builtin_hlsl_resource_load_with_status: {
3170 if (SemaRef.checkArgCount(TheCall, 3) ||
3173 SemaRef.getASTContext().UnsignedIntTy) ||
3175 SemaRef.getASTContext().UnsignedIntTy) ||
3177 return true;
3178
3179 auto *ResourceTy =
3181 QualType ReturnType = ResourceTy->getContainedType();
3182 TheCall->setType(ReturnType);
3183
3184 break;
3185 }
3186
3187 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
3188 assert(TheCall->getNumArgs() == 1 && "expected 1 arg");
3189
3191 TheCall->setType(ResourceTy);
3192 break;
3193 }
3194 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
3195 assert(TheCall->getNumArgs() == 6 && "expected 6 args");
3196
3198 TheCall->setType(ResourceTy);
3199 break;
3200 }
3201 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
3202 assert(TheCall->getNumArgs() == 6 && "expected 6 args");
3203
3205 TheCall->setType(ResourceTy);
3206 break;
3207 }
3208 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
3209 assert(TheCall->getNumArgs() == 3 && "expected 3 args");
3212 auto *MainResType = MainHandleTy->getAs();
3213 auto MainAttrs = MainResType->getAttrs();
3214 assert(!MainAttrs.IsCounter && "cannot create a counter from a counter");
3215 MainAttrs.IsCounter = true;
3217 MainResType->getWrappedType(), MainResType->getContainedType(),
3218 MainAttrs);
3219
3220
3221 TheCall->setType(CounterHandleTy);
3222 break;
3223 }
3224 case Builtin::BI__builtin_hlsl_and:
3225 case Builtin::BI__builtin_hlsl_or: {
3226 if (SemaRef.checkArgCount(TheCall, 2))
3227 return true;
3229 return true;
3231 return true;
3232
3235
3236 TheCall->setType(ArgTyA);
3237 break;
3238 }
3239 case Builtin::BI__builtin_hlsl_all:
3240 case Builtin::BI__builtin_hlsl_any: {
3241 if (SemaRef.checkArgCount(TheCall, 1))
3242 return true;
3244 return true;
3245 break;
3246 }
3247 case Builtin::BI__builtin_hlsl_asdouble: {
3248 if (SemaRef.checkArgCount(TheCall, 2))
3249 return true;
3252 SemaRef.Context.UnsignedIntTy,
3253 0))
3254 return true;
3257 SemaRef.Context.UnsignedIntTy,
3258 1))
3259 return true;
3261 return true;
3262
3264 break;
3265 }
3266 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
3267 if (SemaRef.BuiltinElementwiseTernaryMath(
3268 TheCall,
3270 return true;
3271 break;
3272 }
3273 case Builtin::BI__builtin_hlsl_dot: {
3274
3275 if (SemaRef.BuiltinVectorToScalarMath(TheCall))
3276 return true;
3278 return true;
3279 break;
3280 }
3281 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
3282 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
3283 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3284 return true;
3285
3286 const Expr *Arg = TheCall->getArg(0);
3289
3291
3293 EltTy = VecTy->getElementType();
3294 ResTy = SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());
3295 }
3296
3298 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
3299 << 1 << 5 << 1
3300 << 0 << ArgTy;
3301 return true;
3302 }
3303
3304 TheCall->setType(ResTy);
3305 break;
3306 }
3307 case Builtin::BI__builtin_hlsl_select: {
3308 if (SemaRef.checkArgCount(TheCall, 3))
3309 return true;
3311 return true;
3314 return true;
3316 if (VTy && VTy->getElementType()->isBooleanType() &&
3318 return true;
3319 break;
3320 }
3321 case Builtin::BI__builtin_hlsl_elementwise_saturate:
3322 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
3323 if (SemaRef.checkArgCount(TheCall, 1))
3324 return true;
3325 if (!TheCall->getArg(0)
3329 diag::err_builtin_invalid_arg_type)
3330 << 1 << 5 << 0
3332 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3333 return true;
3334 break;
3335 }
3336 case Builtin::BI__builtin_hlsl_elementwise_degrees:
3337 case Builtin::BI__builtin_hlsl_elementwise_radians:
3338 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
3339 case Builtin::BI__builtin_hlsl_elementwise_frac:
3340 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
3341 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
3342 if (SemaRef.checkArgCount(TheCall, 1))
3343 return true;
3346 return true;
3347 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3348 return true;
3349 break;
3350 }
3351 case Builtin::BI__builtin_hlsl_elementwise_isinf:
3352 case Builtin::BI__builtin_hlsl_elementwise_isnan: {
3353 if (SemaRef.checkArgCount(TheCall, 1))
3354 return true;
3357 return true;
3358 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3359 return true;
3361 break;
3362 }
3363 case Builtin::BI__builtin_hlsl_lerp: {
3364 if (SemaRef.checkArgCount(TheCall, 3))
3365 return true;
3368 return true;
3370 return true;
3371 if (SemaRef.BuiltinElementwiseTernaryMath(TheCall))
3372 return true;
3373 break;
3374 }
3375 case Builtin::BI__builtin_hlsl_mad: {
3376 if (SemaRef.BuiltinElementwiseTernaryMath(
3377 TheCall,
3379 return true;
3380 break;
3381 }
3382 case Builtin::BI__builtin_hlsl_normalize: {
3383 if (SemaRef.checkArgCount(TheCall, 1))
3384 return true;
3387 return true;
3390
3391 TheCall->setType(ArgTyA);
3392 break;
3393 }
3394 case Builtin::BI__builtin_hlsl_elementwise_sign: {
3395 if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
3396 return true;
3399 return true;
3401 break;
3402 }
3403 case Builtin::BI__builtin_hlsl_step: {
3404 if (SemaRef.checkArgCount(TheCall, 2))
3405 return true;
3408 return true;
3409
3412
3413 TheCall->setType(ArgTyA);
3414 break;
3415 }
3416 case Builtin::BI__builtin_hlsl_wave_active_max:
3417 case Builtin::BI__builtin_hlsl_wave_active_min:
3418 case Builtin::BI__builtin_hlsl_wave_active_sum: {
3419 if (SemaRef.checkArgCount(TheCall, 1))
3420 return true;
3421
3422
3424 return true;
3426 return true;
3429 TheCall->setType(ArgTyExpr);
3430 break;
3431 }
3432
3433
3434 case Builtin::BI__builtin_elementwise_bitreverse: {
3435
3436
3439 return true;
3440 break;
3441 }
3442 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
3443 if (SemaRef.checkArgCount(TheCall, 2))
3444 return true;
3445
3446
3451 diag::err_typecheck_convert_incompatible)
3452 << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;
3453 return true;
3454 }
3455
3456
3458 return true;
3459
3462 TheCall->setType(ArgTyExpr);
3463 break;
3464 }
3465 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
3466 if (SemaRef.checkArgCount(TheCall, 0))
3467 return true;
3468 break;
3469 }
3470 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
3471 if (SemaRef.checkArgCount(TheCall, 3))
3472 return true;
3473
3476 1) ||
3478 2))
3479 return true;
3480
3483 return true;
3484 break;
3485 }
3486 case Builtin::BI__builtin_hlsl_elementwise_clip: {
3487 if (SemaRef.checkArgCount(TheCall, 1))
3488 return true;
3489
3491 return true;
3492 break;
3493 }
3494 case Builtin::BI__builtin_elementwise_acos:
3495 case Builtin::BI__builtin_elementwise_asin:
3496 case Builtin::BI__builtin_elementwise_atan:
3497 case Builtin::BI__builtin_elementwise_atan2:
3498 case Builtin::BI__builtin_elementwise_ceil:
3499 case Builtin::BI__builtin_elementwise_cos:
3500 case Builtin::BI__builtin_elementwise_cosh:
3501 case Builtin::BI__builtin_elementwise_exp:
3502 case Builtin::BI__builtin_elementwise_exp2:
3503 case Builtin::BI__builtin_elementwise_exp10:
3504 case Builtin::BI__builtin_elementwise_floor:
3505 case Builtin::BI__builtin_elementwise_fmod:
3506 case Builtin::BI__builtin_elementwise_log:
3507 case Builtin::BI__builtin_elementwise_log2:
3508 case Builtin::BI__builtin_elementwise_log10:
3509 case Builtin::BI__builtin_elementwise_pow:
3510 case Builtin::BI__builtin_elementwise_roundeven:
3511 case Builtin::BI__builtin_elementwise_sin:
3512 case Builtin::BI__builtin_elementwise_sinh:
3513 case Builtin::BI__builtin_elementwise_sqrt:
3514 case Builtin::BI__builtin_elementwise_tan:
3515 case Builtin::BI__builtin_elementwise_tanh:
3516 case Builtin::BI__builtin_elementwise_trunc: {
3519 return true;
3520 break;
3521 }
3522 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
3523 assert(TheCall->getNumArgs() == 2 && "expected 2 args");
3524 auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {
3525 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
3526 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
3527 };
3529 return true;
3530 Expr *OffsetExpr = TheCall->getArg(1);
3531 std::optionalllvm::APSInt Offset =
3533 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {
3535 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
3536 << 1;
3537 return true;
3538 }
3539 break;
3540 }
3541 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {
3542 if (SemaRef.checkArgCount(TheCall, 1))
3543 return true;
3546 return true;
3547
3549 return true;
3550
3553 ArgTy = VTy->getElementType();
3556 diag::err_builtin_invalid_arg_type)
3557 << 1 << 5 << 3
3558 << 0 << TheCall->getArg(0)->getType();
3559 return true;
3560 }
3561
3563 break;
3564 }
3565 }
3566 return false;
3567}
3568
3572 WorkList.push_back(BaseTy);
3573 while (!WorkList.empty()) {
3574 QualType T = WorkList.pop_back_val();
3575 T = T.getCanonicalType().getUnqualifiedType();
3576 if (const auto *AT = dyn_cast(T)) {
3578
3579
3580
3581
3583
3584 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
3585 llvm::append_range(List, ElementFields);
3586 continue;
3587 }
3588
3589
3590 if (const auto *VT = dyn_cast(T)) {
3591 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
3592 continue;
3593 }
3594 if (const auto *MT = dyn_cast(T)) {
3595 List.insert(List.end(), MT->getNumElementsFlattened(),
3596 MT->getElementType());
3597 continue;
3598 }
3599 if (const auto *RD = T->getAsCXXRecordDecl()) {
3600 if (RD->isStandardLayout())
3601 RD = RD->getStandardLayoutBaseWithFields();
3602
3603
3604
3605 if (RD->isUnion() || !RD->isAggregate()) {
3606 List.push_back(T);
3607 continue;
3608 }
3609
3611 for (const auto *FD : RD->fields())
3612 if (!FD->isUnnamedBitField())
3613 FieldTypes.push_back(FD->getType());
3614
3615 std::reverse(FieldTypes.begin(), FieldTypes.end());
3616 llvm::append_range(WorkList, FieldTypes);
3617
3618
3619
3620 if (!RD->isStandardLayout()) {
3621 FieldTypes.clear();
3622 for (const auto &Base : RD->bases())
3623 FieldTypes.push_back(Base.getType());
3624 std::reverse(FieldTypes.begin(), FieldTypes.end());
3625 llvm::append_range(WorkList, FieldTypes);
3626 }
3627 continue;
3628 }
3629 List.push_back(T);
3630 }
3631}
3632
3634
3636 return false;
3637
3638
3640 return false;
3641
3643 return false;
3644
3645
3647 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3648 return false;
3649 return true;
3650 }
3651
3653 int ArraySize = VT->getNumElements();
3654
3655 if (ArraySize > 4)
3656 return false;
3657
3658 QualType ElTy = VT->getElementType();
3660 return false;
3661
3662 if (SemaRef.Context.getTypeSize(QT) / 8 > 16)
3663 return false;
3664 return true;
3665 }
3666
3667 return false;
3668}
3669
3672 return false;
3673
3676
3677
3678 if (SemaRef.getASTContext().hasSameType(T1, T2))
3679 return true;
3680
3685
3686
3687 return llvm::equal(T1Types, T2Types,
3689 return SemaRef.IsLayoutCompatible(LHS, RHS);
3690 });
3691}
3692
3696 return true;
3697
3698 bool HadError = false;
3699
3700 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
3703
3704
3705
3706
3707
3708 const auto *NDAttr = NewParam->getAttr();
3709 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
3710 const auto *ODAttr = OldParam->getAttr();
3711 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
3712
3713 if (NSpellingIdx != OSpellingIdx) {
3715 diag::err_hlsl_param_qualifier_mismatch)
3716 << NDAttr << NewParam;
3717 SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)
3718 << ODAttr;
3719 HadError = true;
3720 }
3721 }
3722 return HadError;
3723}
3724
3725
3726
3728
3730 return false;
3731
3732 if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
3733 return true;
3734
3736 case Type::STK_Bool:
3742 return true;
3747 llvm_unreachable("HLSL doesn't support pointers.");
3750 llvm_unreachable("HLSL doesn't support complex types.");
3752 llvm_unreachable("HLSL doesn't support fixed point types.");
3753 }
3754 llvm_unreachable("Should have returned before this");
3755
3761 return true;
3764 llvm_unreachable("HLSL doesn't support complex types.");
3766 llvm_unreachable("HLSL doesn't support fixed point types.");
3771 llvm_unreachable("HLSL doesn't support pointers.");
3772 }
3773 llvm_unreachable("Should have returned before this");
3774
3779 llvm_unreachable("HLSL doesn't support pointers.");
3780
3782 llvm_unreachable("HLSL doesn't support fixed point types.");
3783
3786 llvm_unreachable("HLSL doesn't support complex types.");
3787 }
3788
3789 llvm_unreachable("Unhandled scalar cast");
3790}
3791
3792
3793
3794
3796
3798
3799
3802 return false;
3803
3805
3806
3808 return false;
3809
3810 if (SrcVecTy)
3812
3815
3816 for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {
3817 if (DestTypes[I]->isUnionType())
3818 return false;
3820 return false;
3821 }
3822 return true;
3823}
3824
3825
3827
3828
3829
3831 if (SrcTy->isScalarType())
3832 return false;
3833
3836 return false;
3837
3840 return false;
3841
3846
3847
3848
3849 if (SrcTypes.size() < DestTypes.size())
3850 return false;
3851
3852 unsigned SrcSize = SrcTypes.size();
3853 unsigned DstSize = DestTypes.size();
3854 unsigned I;
3855 for (I = 0; I < DstSize && I < SrcSize; I++) {
3856 if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())
3857 return false;
3859 return false;
3860 }
3861 }
3862
3863
3864 for (; I < SrcSize; I++) {
3865 if (SrcTypes[I]->isUnionType())
3866 return false;
3867 }
3868 return true;
3869}
3870
3872 assert(Param->hasAttr() &&
3873 "We should not get here without a parameter modifier expression");
3874 const auto *Attr = Param->getAttr();
3877
3881 << Arg << (IsInOut ? 1 : 0);
3883 }
3884
3886
3887 QualType Ty = Param->getType().getNonLValueExprType(Ctx);
3888
3889
3890
3891
3893 SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)
3894 << Arg << (IsInOut ? 1 : 0);
3896 }
3897
3900
3901
3902
3906 SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
3910
3912 auto *OpV = new (Ctx)
3914
3915
3916
3917 Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Param->getBeginLoc(),
3918 tok::equal, ArgOpV, OpV);
3919
3922 Expr *Writeback = Res.get();
3923 auto *OutExpr =
3925
3927}
3928
3930
3931
3932
3934 "Pointer and reference types cannot be inout or out parameters");
3935 Ty = SemaRef.getASTContext().getLValueReferenceType(Ty);
3937 return Ty;
3938}
3939
3945 !VD->hasAttr() &&
3947}
3948
3950
3951 if (Decl->getType().hasAddressSpace())
3952 return;
3953
3954 if (Decl->getType()->isDependentType())
3955 return;
3956
3958
3961 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3963 return;
3964 }
3965
3967 return;
3968
3969
3971 return;
3972
3973
3974
3975 if (Decl->getStorageClass() != SC_Static && ->isStaticDataMember())
3976 return;
3977
3979 Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
3981}
3982
3985
3986 if (SemaRef.RequireCompleteType(
3988 SemaRef.getASTContext().getBaseElementType(VD->getType()),
3989 diag::err_typecheck_decl_incomplete_type)) {
3992 return;
3993 }
3994
3995
3996
3997
3999
4003 DefaultCBufferDecls.push_back(VD);
4004 }
4005
4006
4008 collectResourceBindingsOnVarDecl(VD);
4009
4010 if (VD->hasAttr())
4012
4015
4016
4017
4019 }
4020
4021
4022 processExplicitBindingsOnDecl(VD);
4023
4024
4027
4028
4029
4032 uint32_t OrderID = getNextImplicitBindingOrderID();
4035 else {
4038 OrderID);
4039
4041 }
4042 }
4043
4044
4046
4050 uint32_t OrderID = getNextImplicitBindingOrderID();
4052 }
4053 }
4054 }
4055 }
4056
4058}
4059
4060bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
4062 "expected resource record type");
4063
4067
4068
4070
4071
4076
4078 const char *CreateMethodName;
4079 if (Binding.isExplicit())
4080 CreateMethodName = HasCounter ? "__createFromBindingWithImplicitCounter"
4081 : "__createFromBinding";
4082 else
4083 CreateMethodName = HasCounter
4084 ? "__createFromImplicitBindingWithImplicitCounter"
4085 : "__createFromImplicitBinding";
4086
4087 CreateMethod =
4088 lookupMethod(SemaRef, ResourceDecl, CreateMethodName, VD->getLocation());
4089
4090 if (!CreateMethod)
4091
4092
4093
4094 return false;
4095
4096 if (Binding.isExplicit()) {
4100 Args.push_back(RegSlot);
4101 } else {
4102 uint32_t OrderID = (Binding.hasImplicitOrderID())
4103 ? Binding.getImplicitOrderID()
4104 : getNextImplicitBindingOrderID();
4108 Args.push_back(OrderId);
4109 }
4110
4111 IntegerLiteral *Space =
4114 Args.push_back(Space);
4115
4117 AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
4118 Args.push_back(RangeSize);
4119
4121 AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());
4122 Args.push_back(Index);
4123
4124 StringRef VarName = VD->getName();
4128 SourceLocation());
4131 Name, nullptr, VK_PRValue, FPOptionsOverride());
4132 Args.push_back(NameCast);
4133
4134 if (HasCounter) {
4135
4136 uint32_t CounterOrderID = getNextImplicitBindingOrderID();
4137 IntegerLiteral *CounterId =
4140 Args.push_back(CounterId);
4141 }
4142
4143
4145 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
4146 true);
4147
4148
4149
4151 AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,
4153
4156 CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());
4157
4158 CallExpr *InitExpr =
4160 SourceLocation(), FPOptionsOverride());
4163 SemaRef.CheckCompleteVariableDeclaration(VD);
4164 return true;
4165}
4166
4167bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {
4169 "expected array of resource records");
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180 ASTContext &AST = SemaRef.getASTContext();
4183 CXXMethodDecl *CreateMethod = nullptr;
4184
4186 ResourceBindingAttrs ResourceAttrs(VD);
4187 if (ResourceAttrs.isExplicit())
4188
4189 CreateMethod =
4190 lookupMethod(SemaRef, ResourceDecl,
4191 HasCounter ? "__createFromBindingWithImplicitCounter"
4192 : "__createFromBinding",
4194 else
4195
4196 CreateMethod = lookupMethod(
4198 HasCounter ? "__createFromImplicitBindingWithImplicitCounter"
4199 : "__createFromImplicitBinding",
4201
4202 if (!CreateMethod)
4203 return false;
4204
4205
4207 SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
4208 true);
4209 return true;
4210}
4211
4212
4213
4215
4216
4218 return true;
4219
4220
4224 return initGlobalResourceDecl(VD);
4226 return initGlobalResourceArrayDecl(VD);
4227 }
4228 return false;
4229}
4230
4231
4236 "expected LHS to be a resource record or array of resource records");
4237 if (Opc != BO_Assign)
4238 return true;
4239
4240
4241 Expr *E = LHSExpr;
4242 while (auto *ASE = dyn_cast(E))
4244
4245
4247 if (VarDecl *VD = dyn_cast(DRE->getDecl())) {
4249
4250 SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
4251 SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
4252 return false;
4253 }
4254 }
4255 }
4256 return true;
4257}
4258
4259
4260
4261void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {
4263 "expected global variable that contains HLSL resource");
4264
4265
4266 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast(VD)) {
4267 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
4268 ? ResourceClass::CBuffer
4269 : ResourceClass::SRV);
4270 return;
4271 }
4272
4273
4274
4279 }
4280
4281
4282 if (const HLSLAttributedResourceType *AttrResType =
4283 HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
4284 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
4285 return;
4286 }
4287
4288
4289 if (const RecordType *RT = dyn_cast(Ty))
4290 collectResourceBindingsOnUserRecordDecl(VD, RT);
4291}
4292
4293
4294
4295
4296void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
4297 assert(VD->hasGlobalStorage() && "expected global variable");
4298
4299 bool HasBinding = false;
4300 for (Attr *A : VD->attrs()) {
4302 HasBinding = true;
4303
4304 HLSLResourceBindingAttr *RBA = dyn_cast(A);
4305 if (!RBA || !RBA->hasRegisterSlot())
4306 continue;
4307 HasBinding = true;
4308
4310 assert(RT != RegisterType::I && "invalid or obsolete register type should "
4311 "never have an attribute created");
4312
4313 if (RT == RegisterType::C) {
4314 if (Bindings.hasBindingInfoForDecl(VD))
4316 diag::warn_hlsl_user_defined_type_missing_member)
4317 << static_cast<int>(RT);
4318 continue;
4319 }
4320
4321
4322
4323
4325 if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {
4326
4328 } else {
4330 diag::warn_hlsl_user_defined_type_missing_member)
4331 << static_cast<int>(RT);
4332 }
4333 }
4334
4337}
4338namespace {
4339class InitListTransformer {
4340 Sema &S;
4341 ASTContext &Ctx;
4342 QualType InitTy;
4343 QualType *DstIt = nullptr;
4344 Expr **ArgIt = nullptr;
4345
4346
4347
4348 bool Wrap;
4349
4350 bool castInitializer(Expr *E) {
4351 assert(DstIt && "This should always be something!");
4352 if (DstIt == DestTypes.end()) {
4353 if (!Wrap) {
4354 ArgExprs.push_back(E);
4355
4356
4357 return true;
4358 }
4359 DstIt = DestTypes.begin();
4360 }
4362 Ctx, *DstIt, false);
4365 return false;
4367 ArgExprs.push_back(Init);
4368 DstIt++;
4369 return true;
4370 }
4371
4372 bool buildInitializerListImpl(Expr *E) {
4373
4374 if (auto *Init = dyn_cast(E)) {
4375 for (auto *SubInit : Init->inits())
4376 if (!buildInitializerListImpl(SubInit))
4377 return false;
4378 return true;
4379 }
4380
4381
4382 QualType Ty = E->getType();
4383
4385 return castInitializer(E);
4386
4387 if (auto *VecTy = Ty->getAs()) {
4389
4392 for (uint64_t I = 0; I < Size; ++I) {
4394 SizeTy, SourceLocation());
4395
4399 return false;
4400 if (!castInitializer(ElExpr.get()))
4401 return false;
4402 }
4403 return true;
4404 }
4405 if (auto *MTy = Ty->getAs()) {
4406 unsigned Rows = MTy->getNumRows();
4407 unsigned Cols = MTy->getNumColumns();
4408 QualType ElemTy = MTy->getElementType();
4409
4410 for (unsigned C = 0; C < Cols; ++C) {
4411 for (unsigned R = 0; R < Rows; ++R) {
4412
4416
4421 E, RowIdx, ColIdx, E->getEndLoc());
4423 return false;
4424 if (!castInitializer(ElExpr.get()))
4425 return false;
4427 }
4428 }
4429 return true;
4430 }
4431
4432 if (auto *ArrTy = dyn_cast(Ty.getTypePtr())) {
4436 for (uint64_t I = 0; I < Size; ++I) {
4438 SizeTy, SourceLocation());
4442 return false;
4443 if (!buildInitializerListImpl(ElExpr.get()))
4444 return false;
4445 }
4446 return true;
4447 }
4448
4450 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4451 RecordDecls.push_back(RD);
4452 while (RecordDecls.back()->getNumBases()) {
4453 CXXRecordDecl *D = RecordDecls.back();
4455 "HLSL doesn't support multiple inheritance");
4456 RecordDecls.push_back(
4458 }
4459 while (!RecordDecls.empty()) {
4460 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4461 for (auto *FD : RD->fields()) {
4462 if (FD->isUnnamedBitField())
4463 continue;
4467 E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);
4469 return false;
4470 if (!buildInitializerListImpl(Res.get()))
4471 return false;
4472 }
4473 }
4474 }
4475 return true;
4476 }
4477
4478 Expr *generateInitListsImpl(QualType Ty) {
4479 assert(ArgIt != ArgExprs.end() && "Something is off in iteration!");
4481 return *(ArgIt++);
4482
4483 llvm::SmallVector<Expr *> Inits;
4487 QualType ElTy;
4489 if (auto *ATy = Ty->getAs()) {
4490 ElTy = ATy->getElementType();
4491 Size = ATy->getNumElements();
4492 } else if (auto *CMTy = Ty->getAs()) {
4493 ElTy = CMTy->getElementType();
4494 Size = CMTy->getNumElementsFlattened();
4495 } else {
4497 ElTy = VTy->getElementType();
4498 Size = VTy->getZExtSize();
4499 }
4500 for (uint64_t I = 0; I < Size; ++I)
4501 Inits.push_back(generateInitListsImpl(ElTy));
4502 }
4504 llvm::SmallVector<CXXRecordDecl *> RecordDecls;
4505 RecordDecls.push_back(RD);
4506 while (RecordDecls.back()->getNumBases()) {
4507 CXXRecordDecl *D = RecordDecls.back();
4509 "HLSL doesn't support multiple inheritance");
4510 RecordDecls.push_back(
4512 }
4513 while (!RecordDecls.empty()) {
4514 CXXRecordDecl *RD = RecordDecls.pop_back_val();
4515 for (auto *FD : RD->fields())
4516 if (!FD->isUnnamedBitField())
4517 Inits.push_back(generateInitListsImpl(FD->getType()));
4518 }
4519 }
4520 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4521 Inits, Inits.back()->getEndLoc());
4522 NewInit->setType(Ty);
4523 return NewInit;
4524 }
4525
4526public:
4527 llvm::SmallVector<QualType, 16> DestTypes;
4528 llvm::SmallVector<Expr *, 16> ArgExprs;
4529 InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)
4530 : S(SemaRef), Ctx(SemaRef.getASTContext()),
4531 Wrap(Entity.getType()->isIncompleteArrayType()) {
4532 InitTy = Entity.getType().getNonReferenceType();
4533
4534
4535
4536 if (Wrap) {
4540 }
4542 DstIt = DestTypes.begin();
4543 }
4544
4545 bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); }
4546
4547 Expr *generateInitLists() {
4548 assert(!ArgExprs.empty() &&
4549 "Call buildInitializerList to generate argument expressions.");
4550 ArgIt = ArgExprs.begin();
4551 if (!Wrap)
4552 return generateInitListsImpl(InitTy);
4553 llvm::SmallVector<Expr *> Inits;
4554 while (ArgIt != ArgExprs.end())
4555 Inits.push_back(generateInitListsImpl(InitTy));
4556
4557 auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
4558 Inits, Inits.back()->getEndLoc());
4559 llvm::APInt ArySize(64, Inits.size());
4561 ArraySizeModifier::Normal, 0));
4562 return NewInit;
4563 }
4564};
4565}
4566
4569
4570 if (Init->getType()->isScalarType())
4571 return true;
4573 InitListTransformer ILT(SemaRef, Entity);
4574
4575 for (unsigned I = 0; I < Init->getNumInits(); ++I) {
4583 Init->setInit(I, E);
4584 }
4585 if (!ILT.buildInitializerList(E))
4586 return false;
4587 }
4588 size_t ExpectedSize = ILT.DestTypes.size();
4589 size_t ActualSize = ILT.ArgExprs.size();
4590 if (ExpectedSize == 0 && ActualSize == 0)
4591 return true;
4592
4593
4594
4595
4596
4598 ExpectedSize =
4599 ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;
4600
4601
4602
4603
4606 InitTy = SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
4607 if (ExpectedSize != ActualSize) {
4608 int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;
4609 SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
4610 << TooManyOrFew << InitTy << ExpectedSize << ActualSize;
4611 return false;
4612 }
4613
4614
4615
4617 Init->resizeInits(Ctx, NewInit->getNumInits());
4618 for (unsigned I = 0; I < NewInit->getNumInits(); ++I)
4619 Init->updateInit(Ctx, I, NewInit->getInit(I));
4620 return true;
4621}
4622
4624 const HLSLVkConstantIdAttr *ConstIdAttr =
4625 VDecl->getAttr();
4626 if (!ConstIdAttr)
4627 return true;
4628
4630
4632 if (->isCXX11ConstantExpr(Context, &InitValue)) {
4633 Diag(VDecl->getLocation(), diag::err_specialization_const);
4635 return false;
4636 }
4637
4640
4641
4642 int ConstantID = ConstIdAttr->getId();
4643 llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);
4645 ConstIdAttr->getLocation());
4646
4648 Expr *C = SemaRef.BuildBuiltinCallExpr(Init->getExprLoc(), BID, Args);
4649 if (C->getType()->getCanonicalTypeUnqualified() !=
4653 Context.getTrivialTypeSourceInfo(
4654 Init->getType(), Init->getExprLoc()),
4656 .get();
4657 }
4659 return true;
4660}
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....
TokenType getType() const
Returns the token's type, e.g.
FormatToken * Previous
The previous token in the unwrapped line.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
Definition SemaHLSL.cpp:2857
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
Definition SemaHLSL.cpp:3569
static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition SemaHLSL.cpp:2942
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition SemaHLSL.cpp:1120
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
Definition SemaHLSL.cpp:83
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
Definition SemaHLSL.cpp:3012
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
Definition SemaHLSL.cpp:1083
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
Definition SemaHLSL.cpp:3029
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context, QualType T)
Definition SemaHLSL.cpp:220
static bool isZeroSizedArray(const ConstantArrayType *CAT)
Definition SemaHLSL.cpp:339
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
Definition SemaHLSL.cpp:2340
static FieldDecl * createFieldForHostLayoutStruct(Sema &S, const Type *Ty, IdentifierInfo *II, CXXRecordDecl *LayoutStruct)
Definition SemaHLSL.cpp:458
static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition SemaHLSL.cpp:2929
static bool isInvalidConstantBufferLeafElementType(const Type *Ty)
Definition SemaHLSL.cpp:365
static Builtin::ID getSpecConstBuiltinId(const Type *Type)
Definition SemaHLSL.cpp:133
static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition SemaHLSL.cpp:2918
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
Definition SemaHLSL.cpp:2996
static IdentifierInfo * getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl, bool MustBeUnique)
Definition SemaHLSL.cpp:421
static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT, uint32_t ImplicitBindingOrderID)
Definition SemaHLSL.cpp:586
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
Definition SemaHLSL.cpp:2969
static bool isResourceRecordTypeOrArrayOf(VarDecl *VD)
Definition SemaHLSL.cpp:346
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
Definition SemaHLSL.cpp:239
static const HLSLAttributedResourceType * getResourceArrayHandleType(VarDecl *VD)
Definition SemaHLSL.cpp:352
static RegisterType getRegisterType(ResourceClass RC)
Definition SemaHLSL.cpp:63
static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD, HLSLAppliedSemanticAttr *Semantic, bool IsInput)
Definition SemaHLSL.cpp:774
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
Definition SemaHLSL.cpp:2894
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
Definition SemaHLSL.cpp:1091
static CXXRecordDecl * findRecordDeclInContext(IdentifierInfo *II, DeclContext *DC)
Definition SemaHLSL.cpp:404
static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, unsigned ArgOrdinal, unsigned Width)
Definition SemaHLSL.cpp:2952
static bool hasCounterHandle(const CXXRecordDecl *RD)
Definition SemaHLSL.cpp:1418
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
Definition SemaHLSL.cpp:3045
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
Definition SemaHLSL.cpp:1096
static ResourceClass getResourceClass(RegisterType RT)
Definition SemaHLSL.cpp:115
static CXXRecordDecl * createHostLayoutStruct(Sema &S, CXXRecordDecl *StructDecl)
Definition SemaHLSL.cpp:490
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
Definition SemaHLSL.cpp:2979
void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl)
Definition SemaHLSL.cpp:555
static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD)
Definition SemaHLSL.cpp:384
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
Definition SemaHLSL.cpp:3093
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
Definition SemaHLSL.cpp:286
HLSLResourceBindingAttr::RegisterType RegisterType
Definition SemaHLSL.cpp:58
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
Definition SemaHLSL.cpp:1173
static bool isValidWaveSizeValue(unsigned Value)
Definition SemaHLSL.cpp:1695
static bool IsDefaultBufferConstantDecl(VarDecl *VD)
Definition SemaHLSL.cpp:3940
static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
Definition SemaHLSL.cpp:2905
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
Definition SemaHLSL.cpp:2315
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
Definition SemaHLSL.cpp:2239
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
static const TypeInfo & getInfo(unsigned id)
return(__x > > __y)|(__x<<(32 - __y))
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const IncompleteArrayType * getAsIncompleteArrayType(QualType T) const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const
Return a type for a constant array for a string literal of the specified element type and length.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getLocation() const
SourceLocation getScopeLoc() const
SourceRange getRange() const
const IdentifierInfo * getScopeName() const
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isHLSLIntangible() const
Returns true if the class contains HLSL intangible type, either as a field or in base class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
void completeDefinition() override
Indicates that the definition of this class is now complete.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
QualType withConst() const
Retrieves a version of this type with const applied.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Represents the canonical version of C arrays with a specified constant size.
bool isZeroSize() const
Return true if the size is zero.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Decl - This represents one declaration (or definition), e.g.
attr_iterator attr_end() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
attr_iterator attr_begin() const
SourceLocation getLocation() const
void setImplicit(bool I=true)
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
Represents a ValueDecl that came out of a declarator.
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
DeclarationNameInfo getNameInfo() const
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
void addLayoutStruct(CXXRecordDecl *LS)
void setHasValidPackoffset(bool PO)
static HLSLBufferDecl * CreateDefaultCBuffer(ASTContext &C, DeclContext *LexicalParent, ArrayRef< Decl * > DefaultCBufferDecls)
buffer_decl_range buffer_decls() const
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, llvm::dxbc::RootSignatureVersion Version, ArrayRef< llvm::hlsl::rootsig::RootElement > RootElements)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
SourceLocation getLoc() const
IdentifierInfo * getIdentifierInfo() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
QualType getType() const
Retrieve type being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Represents the results of name lookup.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
unsigned getMinArgs() const
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
bool hasParsedType() const
const ParsedType & getTypeArg() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
AttributeCommonInfo::Kind getKind() const
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
field_iterator field_begin() const
bool hasBindingInfoForDecl(const VarDecl *VD) const
Definition SemaHLSL.cpp:194
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Definition SemaHLSL.cpp:180
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Definition SemaHLSL.cpp:167
Scope - A scope is a transient data structure that is used while parsing the program.
ASTContext & getASTContext() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
Definition SemaHLSL.cpp:3871
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
Definition SemaHLSL.cpp:1303
bool CanPerformElementwiseCast(Expr *Src, QualType DestType)
Definition SemaHLSL.cpp:3826
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1699
void handleVkLocationAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1793
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
Definition SemaHLSL.cpp:2184
void handleSemanticAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1905
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy)
Definition SemaHLSL.cpp:3727
QualType ProcessResourceTypeAttributes(QualType Wrapped)
Definition SemaHLSL.cpp:2161
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1968
void CheckEntryPoint(FunctionDecl *FD)
Definition SemaHLSL.cpp:891
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
Definition SemaHLSL.cpp:1252
T * createSemanticAttr(const AttributeCommonInfo &ACI, std::optional< unsigned > Location)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
Definition SemaHLSL.cpp:2799
HLSLVkConstantIdAttr * mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id)
Definition SemaHLSL.cpp:657
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
Definition SemaHLSL.cpp:623
void deduceAddressSpace(VarDecl *Decl)
Definition SemaHLSL.cpp:3949
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
Definition SemaHLSL.cpp:1271
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1919
bool diagnosePositionType(QualType T, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1815
bool handleInitialization(VarDecl *VDecl, Expr *&Init)
Definition SemaHLSL.cpp:4623
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1802
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:2449
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, SourceLocation Loc)
Definition SemaHLSL.cpp:4232
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType)
Definition SemaHLSL.cpp:3795
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
Definition SemaHLSL.cpp:3670
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, std::optional< unsigned > Index)
Definition SemaHLSL.cpp:1826
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1615
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
Definition SemaHLSL.cpp:3693
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
Definition SemaHLSL.cpp:1185
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:2357
bool IsTypedResourceElementCompatible(QualType T1)
Definition SemaHLSL.cpp:3633
bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init)
Definition SemaHLSL.cpp:4567
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1641
bool ActOnUninitializedVarDecl(VarDecl *D)
Definition SemaHLSL.cpp:4214
void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1763
void ActOnTopLevelFunction(FunctionDecl *FD)
Definition SemaHLSL.cpp:726
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
Definition SemaHLSL.cpp:2079
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
Definition SemaHLSL.cpp:693
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
Definition SemaHLSL.cpp:596
void handleVkBindingAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1780
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
Definition SemaHLSL.cpp:706
QualType getInoutParameterType(QualType Ty)
Definition SemaHLSL.cpp:3929
SemaHLSL(Sema &S)
Definition SemaHLSL.cpp:198
void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL)
Definition SemaHLSL.cpp:1771
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
Definition SemaHLSL.cpp:200
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
Definition SemaHLSL.cpp:637
bool handleRootSignatureElements(ArrayRef< hlsl::RootSignatureElement > Elements)
Definition SemaHLSL.cpp:1432
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...
Definition SemaHLSL.cpp:1283
void ActOnVariableDeclarator(VarDecl *VD)
Definition SemaHLSL.cpp:3983
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaHLSL.cpp:3118
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
ASTContext & getASTContext() const
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
const LangOptions & getLangOpts() const
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo)
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, SourceLocation RBLoc)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
void startDefinition()
Starts the definition of this tag declaration.
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
The top declaration context.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
bool isBooleanType() const
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
CXXRecordDecl * castAsCXXRecordDecl() const
bool isArithmeticType() const
bool isConstantMatrixType() const
bool isHLSLBuiltinIntangibleType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs.
bool isReferenceType() const
bool isHLSLIntangibleType() const
bool isEnumeralType() const
bool isScalarType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
ScalarTypeKind getScalarTypeKind() const
Given that this is a scalar type, classify it.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isHLSLResourceRecord() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isHLSLAttributedResourceType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
void setType(QualType newType)
Represents a variable declaration or definition.
void setInitStyle(InitializationStyle Style)
@ CallInit
Call-style initialization (C++98)
void setStorageClass(StorageClass SC)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, int ArgOrdinal, clang::QualType PassedType)
@ ICIS_NoInit
No in-class initializer.
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, llvm::ArrayRef< llvm::function_ref< bool(Sema *, SourceLocation, int, QualType)> > Checks)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
const FunctionProtoType * T
llvm::Expected< QualType > ExpectedType
static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
Definition SemaHLSL.cpp:1988
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
Visibility
Describes the different kinds of visibility that a declaration may have.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
TypeSourceInfo * ContainedTyInfo
Describes how types, statements, expressions, and declarations should be printed.
void setCounterImplicitOrderID(unsigned Value) const
bool hasCounterImplicitOrderID() const
void setImplicitOrderID(unsigned Value) const
const SourceLocation & getLocation() const
const llvm::hlsl::rootsig::RootElement & getElement() const