clang: lib/Sema/SemaHLSL.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
14#include "clang/AST/Attrs.inc"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/SmallVector.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/ADT/StringRef.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/DXILABI.h"
37#include "llvm/Support/ErrorHandling.h"
38#include "llvm/TargetParser/Triple.h"
39#include
40#include
41
42using namespace clang;
43using RegisterType = HLSLResourceBindingAttr::RegisterType;
44
46 switch (RC) {
47 case ResourceClass::SRV:
48 return RegisterType::SRV;
49 case ResourceClass::UAV:
50 return RegisterType::UAV;
51 case ResourceClass::CBuffer:
52 return RegisterType::CBuffer;
53 case ResourceClass::Sampler:
54 return RegisterType::Sampler;
55 }
56 llvm_unreachable("unexpected ResourceClass value");
57}
58
59
60
62 assert(RT != nullptr);
63 switch (Slot[0]) {
64 case 't':
65 case 'T':
66 *RT = RegisterType::SRV;
67 return true;
68 case 'u':
69 case 'U':
70 *RT = RegisterType::UAV;
71 return true;
72 case 'b':
73 case 'B':
74 *RT = RegisterType::CBuffer;
75 return true;
76 case 's':
77 case 'S':
78 *RT = RegisterType::Sampler;
79 return true;
80 case 'c':
81 case 'C':
82 *RT = RegisterType::C;
83 return true;
84 case 'i':
85 case 'I':
86 *RT = RegisterType::I;
87 return true;
88 default:
89 return false;
90 }
91}
92
94 switch (RT) {
95 case RegisterType::SRV:
96 return ResourceClass::SRV;
97 case RegisterType::UAV:
98 return ResourceClass::UAV;
99 case RegisterType::CBuffer:
100 return ResourceClass::CBuffer;
101 case RegisterType::Sampler:
102 return ResourceClass::Sampler;
103 case RegisterType::C:
104 case RegisterType::I:
105
106 break;
107 }
108 llvm_unreachable("unexpected RegisterType value");
109}
110
112 ResourceClass ResClass) {
114 "DeclBindingInfo already added");
116
117
118
119
120 DeclToBindingListIndex.try_emplace(VD, BindingsList.size());
121 return &BindingsList.emplace_back(VD, ResClass);
122}
123
125 ResourceClass ResClass) {
126 auto Entry = DeclToBindingListIndex.find(VD);
127 if (Entry != DeclToBindingListIndex.end()) {
128 for (unsigned Index = Entry->getSecond();
129 Index < BindingsList.size() && BindingsList[Index].Decl == VD;
130 ++Index) {
131 if (BindingsList[Index].ResClass == ResClass)
132 return &BindingsList[Index];
133 }
134 }
135 return nullptr;
136}
137
139 return DeclToBindingListIndex.contains(VD);
140}
141
143
148
151 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
152
153
154 auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer
155 : llvm::hlsl::ResourceClass::SRV;
156 auto RK = CBuffer ? llvm::hlsl::ResourceKind::CBuffer
157 : llvm::hlsl::ResourceKind::TBuffer;
158 Result->addAttr(HLSLResourceClassAttr::CreateImplicit(getASTContext(), RC));
160
163
165}
166
167
168
171 unsigned Size = 0;
172 constexpr unsigned CBufferAlign = 16;
174 const RecordDecl *RD = RT->getDecl();
176 QualType Ty = Field->getType();
178
179
180 unsigned FieldAlign = 4;
182 FieldAlign = CBufferAlign;
183 Size = llvm::alignTo(Size, FieldAlign);
184 Size += FieldSize;
185 }
187 if (unsigned ElementCount = AT->getSize().getZExtValue()) {
188 unsigned ElementSize =
190 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
191 Size = AlignedElementSize * (ElementCount - 1) + ElementSize;
192 }
194 unsigned ElementCount = VT->getNumElements();
195 unsigned ElementSize =
197 Size = ElementSize * ElementCount;
198 } else {
200 }
201 return Size;
202}
203
204
205
206
209
210
211
212 bool HasPackOffset = false;
213 bool HasNonPackOffset = false;
214 for (auto *Field : BufDecl->decls()) {
215 VarDecl *Var = dyn_cast(Field);
216 if (!Var)
217 continue;
218 if (Field->hasAttr()) {
219 PackOffsetVec.emplace_back(Var, Field->getAttr());
220 HasPackOffset = true;
221 } else {
222 HasNonPackOffset = true;
223 }
224 }
225
226 if (!HasPackOffset)
227 return;
228
229 if (HasNonPackOffset)
230 S.Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);
231
232
233
235 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
236 [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
237 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
238 return LHS.second->getOffsetInBytes() <
239 RHS.second->getOffsetInBytes();
240 });
241 for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
242 VarDecl *Var = PackOffsetVec[i].first;
243 HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second;
245 unsigned Begin = Attr->getOffsetInBytes();
246 unsigned End = Begin + Size;
247 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
248 if (End > NextBegin) {
249 VarDecl *NextVar = PackOffsetVec[i + 1].first;
250 S.Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap)
251 << NextVar << Var;
252 }
253 }
254}
255
257 auto *BufDecl = cast(Dcl);
258 BufDecl->setRBraceLoc(RBrace);
259
261
263}
264
267 int X, int Y, int Z) {
268 if (HLSLNumThreadsAttr *NT = D->getAttr()) {
269 if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) {
270 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
271 Diag(AL.getLoc(), diag::note_conflicting_attribute);
272 }
273 return nullptr;
274 }
277}
278
281 int Min, int Max, int Preferred,
282 int SpelledArgsCount) {
283 if (HLSLWaveSizeAttr *WS = D->getAttr()) {
284 if (WS->getMin() != Min || WS->getMax() != Max ||
285 WS->getPreferred() != Preferred ||
286 WS->getSpelledArgsCount() != SpelledArgsCount) {
287 Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
288 Diag(AL.getLoc(), diag::note_conflicting_attribute);
289 }
290 return nullptr;
291 }
294 Result->setSpelledArgsCount(SpelledArgsCount);
296}
297
298HLSLShaderAttr *
300 llvm::Triple::EnvironmentType ShaderType) {
301 if (HLSLShaderAttr *NT = D->getAttr()) {
302 if (NT->getType() != ShaderType) {
303 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
304 Diag(AL.getLoc(), diag::note_conflicting_attribute);
305 }
306 return nullptr;
307 }
308 return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL);
309}
310
311HLSLParamModifierAttr *
313 HLSLParamModifierAttr::Spelling Spelling) {
314
315
316 if (HLSLParamModifierAttr *PA = D->getAttr()) {
317 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
318 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
321 return HLSLParamModifierAttr::Create(
322 getASTContext(), true, AdjustedRange,
323 HLSLParamModifierAttr::Keyword_inout);
324 }
325 Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
326 Diag(PA->getLocation(), diag::note_conflicting_attribute);
327 return nullptr;
328 }
329 return HLSLParamModifierAttr::Create(getASTContext(), AL);
330}
331
334
336 return;
337
339 if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {
340 if (const auto *Shader = FD->getAttr()) {
341
342
343 if (Shader->getType() != Env) {
344 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
345 << Shader;
347 }
348 } else {
349
350
353 }
354 } else {
355 switch (Env) {
356 case llvm::Triple::UnknownEnvironment:
357 case llvm::Triple::Library:
358 break;
359 default:
360 llvm_unreachable("Unhandled environment in triple");
361 }
362 }
363}
364
366 const auto *ShaderAttr = FD->getAttr();
367 assert(ShaderAttr && "Entry point has no shader attribute");
368 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
371 switch (ST) {
372 case llvm::Triple::Pixel:
373 case llvm::Triple::Vertex:
374 case llvm::Triple::Geometry:
375 case llvm::Triple::Hull:
376 case llvm::Triple::Domain:
377 case llvm::Triple::RayGeneration:
378 case llvm::Triple::Intersection:
379 case llvm::Triple::AnyHit:
380 case llvm::Triple::ClosestHit:
381 case llvm::Triple::Miss:
382 case llvm::Triple::Callable:
383 if (const auto *NT = FD->getAttr()) {
385 {llvm::Triple::Compute,
386 llvm::Triple::Amplification,
387 llvm::Triple::Mesh});
389 }
390 if (const auto *WS = FD->getAttr()) {
392 {llvm::Triple::Compute,
393 llvm::Triple::Amplification,
394 llvm::Triple::Mesh});
396 }
397 break;
398
399 case llvm::Triple::Compute:
400 case llvm::Triple::Amplification:
401 case llvm::Triple::Mesh:
402 if (!FD->hasAttr()) {
403 Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads)
404 << llvm::Triple::getEnvironmentTypeName(ST);
406 }
407 if (const auto *WS = FD->getAttr()) {
408 if (Ver < VersionTuple(6, 6)) {
409 Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)
410 << WS << "6.6";
412 } else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {
414 WS->getLocation(),
415 diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)
416 << WS << WS->getSpelledArgsCount() << "6.8";
418 }
419 }
420 break;
421 default:
422 llvm_unreachable("Unhandled environment in triple");
423 }
424
426 if (const auto *AnnotationAttr = Param->getAttr<HLSLAnnotationAttr>()) {
428 } else {
429
430
431 Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation);
432 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
434 }
435 }
436
437}
438
442 auto *ShaderAttr = EntryPoint->getAttr();
443 assert(ShaderAttr && "Entry point has no shader attribute");
444 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
445
446 switch (AnnotationAttr->getKind()) {
447 case attr::HLSLSV_DispatchThreadID:
448 case attr::HLSLSV_GroupIndex:
449 case attr::HLSLSV_GroupThreadID:
450 case attr::HLSLSV_GroupID:
451 if (ST == llvm::Triple::Compute)
452 return;
454 break;
455 default:
456 llvm_unreachable("Unknown HLSLAnnotationAttr");
457 }
458}
459
461 const Attr *A, llvm::Triple::EnvironmentType Stage,
462 std::initializer_listllvm::Triple::EnvironmentType AllowedStages) {
464 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
465 [](llvm::Triple::EnvironmentType ST) {
466 return StringRef(
467 HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));
468 });
469 Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
470 << A << llvm::Triple::getEnvironmentTypeName(Stage)
471 << (AllowedStages.size() != 1) << join(StageStrings, ", ");
472}
473
474template
477 Ty = VTy->getElementType();
480}
481
482template
485 return Ty;
486}
487
493
494 if (LHSFloat && RHSFloat) {
495 if (IsCompAssign ||
497 return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
498
499 return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
500 }
501
502 if (LHSFloat)
503 return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
504
505 assert(RHSFloat);
506 if (IsCompAssign)
507 return castElementclang::CK\_FloatingToIntegral(SemaRef, RHS, LHSType);
508
509 return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
510}
511
515
520
521
522 if (LHSSigned == RHSSigned) {
523 if (IsCompAssign || IntOrder >= 0)
524 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
525
526 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
527 }
528
529
530
531 if (IntOrder != (LHSSigned ? 1 : -1)) {
532 if (IsCompAssign || RHSSigned)
533 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
534 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
535 }
536
537
538
539
541 if (IsCompAssign || LHSSigned)
542 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
543 return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
544 }
545
546
547
548
549
550
551
552
553 if (IsCompAssign)
554 return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
555
556
560 (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
561
562 return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
563}
564
568 return CK_FloatingCast;
570 return CK_IntegralCast;
572 return CK_IntegralToFloating;
574 return CK_FloatingToIntegral;
575}
576
580 bool IsCompAssign) {
584
585
586
587 if (!LVecTy && IsCompAssign) {
592 return LHSType;
595 return LHSType;
596 }
597
598 unsigned EndSz = std::numeric_limits::max();
599 unsigned LSz = 0;
600 if (LVecTy)
601 LSz = EndSz = LVecTy->getNumElements();
602 if (RVecTy)
604 assert(EndSz != std::numeric_limits::max() &&
605 "one of the above should have had a value");
606
607
608
609 if (IsCompAssign && LSz != EndSz) {
611 diag::err_hlsl_vector_compound_assignment_truncation)
612 << LHSType << RHSType;
614 }
615
617 castVector<CK_HLSLVectorTruncation>(SemaRef, RHS, RHSType, EndSz);
618 if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)
619 castVector<CK_HLSLVectorTruncation>(SemaRef, LHS, LHSType, EndSz);
620
621 if (!RVecTy)
622 castVector<CK_VectorSplat>(SemaRef, RHS, RHSType, EndSz);
623 if (!IsCompAssign && !LVecTy)
624 castVector<CK_VectorSplat>(SemaRef, LHS, LHSType, EndSz);
625
626
629
632
633
636 LElTy, RElTy, IsCompAssign);
637
639 "HLSL Vectors can only contain integer or floating point types");
641 LElTy, RElTy, IsCompAssign);
642}
643
646 assert((Opc == BO_LOr || Opc == BO_LAnd) &&
647 "Called with non-logical operator");
649 llvm::raw_svector_ostream OS(Buff);
651 StringRef NewFnName = Opc == BO_LOr ? "or" : "and";
652 OS << NewFnName << "(";
654 OS << ", ";
656 OS << ")";
660}
661
663 llvm::VersionTuple SMVersion =
665 uint32_t ZMax = 1024;
666 uint32_t ThreadMax = 1024;
667 if (SMVersion.getMajor() <= 4) {
668 ZMax = 1;
669 ThreadMax = 768;
670 } else if (SMVersion.getMajor() == 5) {
671 ZMax = 64;
672 ThreadMax = 1024;
673 }
674
675 uint32_t X;
677 return;
678 if (X > 1024) {
680 diag::err_hlsl_numthreads_argument_oor)
681 << 0 << 1024;
682 return;
683 }
684 uint32_t Y;
686 return;
687 if (Y > 1024) {
689 diag::err_hlsl_numthreads_argument_oor)
690 << 1 << 1024;
691 return;
692 }
693 uint32_t Z;
695 return;
696 if (Z > ZMax) {
698 diag::err_hlsl_numthreads_argument_oor)
699 << 2 << ZMax;
700 return;
701 }
702
703 if (X * Y * Z > ThreadMax) {
704 Diag(AL.getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;
705 return;
706 }
707
709 if (NewAttr)
711}
712
714 return llvm::isPowerOf2_32(Value) && Value >= 4 && Value <= 128;
715}
716
718
719
720 unsigned SpelledArgsCount = AL.getNumArgs();
721 if (SpelledArgsCount == 0 || SpelledArgsCount > 3)
722 return;
723
724 uint32_t Min;
726 return;
727
728 uint32_t Max = 0;
729 if (SpelledArgsCount > 1 &&
731 return;
732
733 uint32_t Preferred = 0;
734 if (SpelledArgsCount > 2 &&
736 return;
737
738 if (SpelledArgsCount > 2) {
741 diag::err_attribute_power_of_two_in_range)
742 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize
743 << Preferred;
744 return;
745 }
746
747 if (Preferred < Min || Preferred > Max) {
749 diag::err_attribute_power_of_two_in_range)
750 << AL << Min << Max << Preferred;
751 return;
752 }
753 } else if (SpelledArgsCount > 1) {
756 diag::err_attribute_power_of_two_in_range)
757 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Max;
758 return;
759 }
761 Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
762 return;
764 Diag(AL.getLoc(), diag::warn_attr_min_eq_max) << AL;
765 }
766 } else {
769 diag::err_attribute_power_of_two_in_range)
770 << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Min;
771 return;
772 }
773 }
774
775 HLSLWaveSizeAttr *NewAttr =
777 if (NewAttr)
779}
780
783
785 (VT && VT->getNumElements() > 3)) {
786 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
787 << AL << "uint/uint2/uint3";
788 return false;
789 }
790
791 return true;
792}
793
795 auto *VD = cast(D);
797 return;
798
800 HLSLSV_DispatchThreadIDAttr(getASTContext(), AL));
801}
802
804 auto *VD = cast(D);
806 return;
807
810}
811
813 auto *VD = cast(D);
815 return;
816
818}
819
821 if (!isa(D) || !isa(D->getDeclContext())) {
822 Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)
823 << AL << "shader constant in a constant buffer";
824 return;
825 }
826
827 uint32_t SubComponent;
829 return;
830 uint32_t Component;
832 return;
833
834 QualType T = cast(D)->getType().getCanonicalType();
835
836
838
839
840 if (Component) {
842 if (IsAggregateTy || Size > 128) {
843 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
844 return;
845 } else {
846
847 if ((Component * 32 + Size) > 128) {
848 Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);
849 return;
850 }
853 EltTy = VT->getElementType();
855 if (Align > 32 && Component == 1) {
856
857
858 Diag(AL.getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)
859 << Align << EltTy;
860 return;
861 }
862 }
863 }
864
867}
868
870 StringRef Str;
873 return;
874
875 llvm::Triple::EnvironmentType ShaderType;
876 if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {
877 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
878 << AL << Str << ArgLoc;
879 return;
880 }
881
882
883
884 HLSLShaderAttr *NewAttr = mergeShaderAttr(D, AL, ShaderType);
885 if (NewAttr)
887}
888
892 assert(AttrList.size() && "expected list of resource attributes");
893
896 SourceLocation LocBegin = AttrList[0]->getRange().getBegin();
897 SourceLocation LocEnd = AttrList[0]->getRange().getEnd();
898
900
901 bool HasResourceClass = false;
902 for (const Attr *A : AttrList) {
903 if (!A)
904 continue;
905 LocEnd = A->getRange().getEnd();
906 switch (A->getKind()) {
907 case attr::HLSLResourceClass: {
908 ResourceClass RC = cast(A)->getResourceClass();
909 if (HasResourceClass) {
911 ? diag::warn_duplicate_attribute_exact
912 : diag::warn_duplicate_attribute)
913 << A;
914 return false;
915 }
917 HasResourceClass = true;
918 break;
919 }
920 case attr::HLSLROV:
921 if (ResAttrs.IsROV) {
922 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
923 return false;
924 }
925 ResAttrs.IsROV = true;
926 break;
927 case attr::HLSLRawBuffer:
929 S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
930 return false;
931 }
933 break;
934 case attr::HLSLContainedType: {
935 const HLSLContainedTypeAttr *CTAttr = cast(A);
936 QualType Ty = CTAttr->getType();
937 if (!ContainedTy.isNull()) {
938 S.Diag(A->getLocation(), ContainedTy == Ty
939 ? diag::warn_duplicate_attribute_exact
940 : diag::warn_duplicate_attribute)
941 << A;
942 return false;
943 }
944 ContainedTy = Ty;
945 ContainedTyInfo = CTAttr->getTypeLoc();
946 break;
947 }
948 default:
949 llvm_unreachable("unhandled resource attribute type");
950 }
951 }
952
953 if (!HasResourceClass) {
954 S.Diag(AttrList.back()->getRange().getEnd(),
955 diag::err_hlsl_missing_resource_class);
956 return false;
957 }
958
960 Wrapped, ContainedTy, ResAttrs);
961
962 if (LocInfo && ContainedTyInfo) {
965 }
966 return true;
967}
968
969
970
971
972
974
975 if (->isHLSLResourceType()) {
976 Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)
978 return false;
979 }
980
981
983 return false;
984
985 Attr *A = nullptr;
987 case ParsedAttr::AT_HLSLResourceClass: {
989 Diag(AL.getLoc(), diag::err_attribute_argument_type)
991 return false;
992 }
993
997
998
999 ResourceClass RC;
1000 if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
1001 Diag(ArgLoc, diag::warn_attribute_type_not_supported)
1003 return false;
1004 }
1006 break;
1007 }
1008
1009 case ParsedAttr::AT_HLSLROV:
1011 break;
1012
1013 case ParsedAttr::AT_HLSLRawBuffer:
1015 break;
1016
1017 case ParsedAttr::AT_HLSLContainedType: {
1019 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
1020 return false;
1021 }
1022
1025 assert(TSI && "no type source info for attribute argument");
1027 diag::err_incomplete_type))
1028 return false;
1030 break;
1031 }
1032
1033 default:
1034 llvm_unreachable("unhandled HLSL attribute");
1035 }
1036
1037 HLSLResourcesTypeAttrs.emplace_back(A);
1038 return true;
1039}
1040
1041
1043 if (!HLSLResourcesTypeAttrs.size())
1044 return CurrentType;
1045
1049 HLSLResourcesTypeAttrs, QT, &LocInfo)) {
1051 cast(QT.getTypePtr());
1052
1053
1054
1055
1056
1057 LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));
1058 }
1059 HLSLResourcesTypeAttrs.clear();
1060 return QT;
1061}
1062
1063
1067 auto I = LocsForHLSLAttributedResources.find(RT);
1068 if (I != LocsForHLSLAttributedResources.end()) {
1069 LocInfo = I->second;
1070 LocsForHLSLAttributedResources.erase(I);
1071 return LocInfo;
1072 }
1074 return LocInfo;
1075}
1076
1077
1078
1079void SemaHLSL::collectResourcesOnUserRecordDecl(const VarDecl *VD,
1084
1085
1086
1088 "incomplete arrays inside user defined types are not supported");
1092 }
1093
1095 continue;
1096
1099
1100 ResourceClass RC = AttrResType->getAttrs().ResourceClass;
1102 if (!DBI)
1103 Bindings.addDeclBindingInfo(VD, RC);
1104 } else if (const RecordType *RT = dyn_cast(Ty)) {
1105
1106
1107
1108
1109
1110 collectResourcesOnUserRecordDecl(VD, RT);
1111 }
1112 }
1113}
1114
1115
1116
1117
1118
1119
1122 bool SpecifiedSpace) {
1123 int RegTypeNum = static_cast<int>(RegType);
1124
1125
1127 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1128 return false;
1129 }
1130
1131
1132 if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast(D)) {
1133 ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer
1134 : ResourceClass::SRV;
1136 return true;
1137
1138 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
1139 << RegTypeNum;
1140 return false;
1141 }
1142
1143
1144 assert(isa(D) && "D is expected to be VarDecl or HLSLBufferDecl");
1146
1147
1151 if (RegType == getRegisterType(AttrResType->getAttrs().ResourceClass))
1152 return true;
1153
1154 S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)
1155 << RegTypeNum;
1156 return false;
1157 }
1158
1162
1163
1165 bool DeclaredInCOrTBuffer = isa(D->getDeclContext());
1166 if (SpecifiedSpace && !DeclaredInCOrTBuffer)
1167 S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1168
1169 if (!DeclaredInCOrTBuffer &&
1171
1172 if (RegType == RegisterType::CBuffer)
1173 S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1174 else if (RegType != RegisterType::C)
1175 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1176 } else {
1177 if (RegType == RegisterType::C)
1178 S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
1179 else
1180 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1181 }
1182 return false;
1183 }
1185
1186
1187 return true;
1188
1189
1190 S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
1191 return false;
1192}
1193
1196
1197
1198 bool RegisterTypesDetected[5] = {false};
1199 RegisterTypesDetected[static_cast<int>(regType)] = true;
1200
1201 for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {
1202 if (HLSLResourceBindingAttr *attr =
1203 dyn_cast(*it)) {
1204
1206 if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {
1207 int otherRegTypeNum = static_cast<int>(otherRegType);
1209 diag::err_hlsl_duplicate_register_annotation)
1210 << otherRegTypeNum;
1211 return false;
1212 }
1213 RegisterTypesDetected[static_cast<int>(otherRegType)] = true;
1214 }
1215 }
1216 return true;
1217}
1218
1221 bool SpecifiedSpace) {
1222
1223
1224 assert(((isa(D) && !isa(D)) ||
1226 "expecting VarDecl or HLSLBufferDecl");
1227
1228
1230 return false;
1231
1232
1234}
1235
1237 if (isa(TheDecl)) {
1239 cast(TheDecl)->getType(),
1240 diag::err_incomplete_type))
1241 return;
1242 }
1243 StringRef Space = "space0";
1244 StringRef Slot = "";
1245
1247 Diag(AL.getLoc(), diag::err_attribute_argument_type)
1249 return;
1250 }
1251
1253 StringRef Str = Loc->Ident->getName();
1255
1257 bool SpecifiedSpace = false;
1259 SpecifiedSpace = true;
1260 Slot = Str;
1262 Diag(AL.getLoc(), diag::err_attribute_argument_type)
1264 return;
1265 }
1266
1268 Space = Loc->Ident->getName();
1269 SpaceArgLoc = Loc->Loc;
1270 } else {
1271 Slot = Str;
1272 }
1273
1275 unsigned SlotNum = 0;
1276 unsigned SpaceNum = 0;
1277
1278
1279 if (!Slot.empty()) {
1281 Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
1282 return;
1283 }
1284 if (RegType == RegisterType::I) {
1285 Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);
1286 return;
1287 }
1288
1289 StringRef SlotNumStr = Slot.substr(1);
1290 if (SlotNumStr.getAsInteger(10, SlotNum)) {
1291 Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);
1292 return;
1293 }
1294 }
1295
1296 if (!Space.starts_with("space")) {
1297 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1298 return;
1299 }
1300 StringRef SpaceNumStr = Space.substr(5);
1301 if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
1302 Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1303 return;
1304 }
1305
1307 SpecifiedSpace))
1308 return;
1309
1310 HLSLResourceBindingAttr *NewAttr =
1311 HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);
1312 if (NewAttr) {
1313 NewAttr->setBinding(RegType, SlotNum, SpaceNum);
1314 TheDecl->addAttr(NewAttr);
1315 }
1316}
1317
1320 D, AL,
1321 static_castHLSLParamModifierAttr::Spelling\(AL.getSemanticSpelling()));
1322 if (NewAttr)
1324}
1325
1326namespace {
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1341 Sema &SemaRef;
1342
1343
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368 llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
1369
1370
1371
1372 llvm::Triple::EnvironmentType CurrentShaderEnvironment;
1373 unsigned CurrentShaderStageBit;
1374
1375
1376
1377
1378 bool ReportOnlyShaderStageIssues;
1379
1380
1381 void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
1382 static_assert(sizeof(unsigned) >= 4);
1383 assert(HLSLShaderAttr::isValidShaderType(ShaderType));
1384 assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&
1385 "ShaderType is too big for this bitmap");
1386
1387
1388 unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;
1389 CurrentShaderEnvironment = ShaderType;
1390 CurrentShaderStageBit = (1 << bitmapIndex);
1391 }
1392
1393 void SetUnknownShaderStageContext() {
1394 CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
1395 CurrentShaderStageBit = (1 << 31);
1396 }
1397
1398 llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
1399 return CurrentShaderEnvironment;
1400 }
1401
1402 bool InUnknownShaderStageContext() const {
1403 return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
1404 }
1405
1406
1407 void AddToScannedFunctions(const FunctionDecl *FD) {
1408 unsigned &ScannedStages = ScannedDecls[FD];
1409 ScannedStages |= CurrentShaderStageBit;
1410 }
1411
1412 unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }
1413
1414 bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {
1415 return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
1416 }
1417
1418 bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {
1419 return ScannerStages & CurrentShaderStageBit;
1420 }
1421
1422 static bool NeverBeenScanned(unsigned ScannedStages) {
1423 return ScannedStages == 0;
1424 }
1425
1426
1427 void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
1428 void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
1430 const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
1431 bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
1432
1433public:
1434 DiagnoseHLSLAvailability(Sema &SemaRef)
1435 : SemaRef(SemaRef),
1436 CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
1437 CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}
1438
1439
1442
1443 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
1445 if (FD)
1446 HandleFunctionOrMethodRef(FD, DRE);
1447 return true;
1448 }
1449
1450 bool VisitMemberExpr(MemberExpr *ME) override {
1452 if (FD)
1453 HandleFunctionOrMethodRef(FD, ME);
1454 return true;
1455 }
1456};
1457
1458void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
1459 Expr *RefExpr) {
1460 assert((isa(RefExpr) || isa(RefExpr)) &&
1461 "expected DeclRefExpr or MemberExpr");
1462
1463
1465 if (FD->hasBody(FDWithBody)) {
1466 if (!WasAlreadyScannedInCurrentStage(FDWithBody))
1467 DeclsToScan.push_back(FDWithBody);
1468 return;
1469 }
1470
1471
1472 const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
1473 if (AA)
1474 CheckDeclAvailability(
1476}
1477
1478void DiagnoseHLSLAvailability::RunOnTranslationUnit(
1480
1481
1482
1483
1484
1485
1487 DeclContextsToScan.push_back(TU);
1488
1489 while (!DeclContextsToScan.empty()) {
1490 const DeclContext *DC = DeclContextsToScan.pop_back_val();
1491 for (auto &D : DC->decls()) {
1492
1494 continue;
1495
1496
1497
1498 if (llvm::dyn_cast(D) || llvm::dyn_cast(D)) {
1499 DeclContextsToScan.push_back(llvm::dyn_cast(D));
1500 continue;
1501 }
1502
1503
1504 const FunctionDecl *FD = llvm::dyn_cast(D);
1506 continue;
1507
1508
1509 if (HLSLShaderAttr *ShaderAttr = FD->getAttr()) {
1510 SetShaderStageContext(ShaderAttr->getType());
1511 RunOnFunction(FD);
1512 continue;
1513 }
1514
1515
1516
1518 if (!isExport) {
1519 for (const auto *Redecl : FD->redecls()) {
1520 if (Redecl->isInExportDeclContext()) {
1521 isExport = true;
1522 break;
1523 }
1524 }
1525 }
1526 if (isExport) {
1527 SetUnknownShaderStageContext();
1528 RunOnFunction(FD);
1529 continue;
1530 }
1531 }
1532 }
1533}
1534
1535void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
1536 assert(DeclsToScan.empty() && "DeclsToScan should be empty");
1537 DeclsToScan.push_back(FD);
1538
1539 while (!DeclsToScan.empty()) {
1540
1541
1542
1543
1544 const FunctionDecl *FD = DeclsToScan.pop_back_val();
1545
1546
1547 const unsigned ScannedStages = GetScannedStages(FD);
1548 if (WasAlreadyScannedInCurrentStage(ScannedStages))
1549 continue;
1550
1551 ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
1552
1553 AddToScannedFunctions(FD);
1554 TraverseStmt(FD->getBody());
1555 }
1556}
1557
1558bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
1559 const AvailabilityAttr *AA) {
1560 IdentifierInfo *IIEnvironment = AA->getEnvironment();
1561 if (!IIEnvironment)
1562 return true;
1563
1564 llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
1565 if (CurrentEnv == llvm::Triple::UnknownEnvironment)
1566 return false;
1567
1568 llvm::Triple::EnvironmentType AttrEnv =
1569 AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
1570
1571 return CurrentEnv == AttrEnv;
1572}
1573
1574const AvailabilityAttr *
1575DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {
1576 AvailabilityAttr const *PartialMatch = nullptr;
1577
1578
1579
1580 for (const auto *A : D->attrs()) {
1581 if (const auto *Avail = dyn_cast(A)) {
1582 StringRef AttrPlatform = Avail->getPlatform()->getName();
1583 StringRef TargetPlatform =
1585
1586
1587 if (AttrPlatform == TargetPlatform) {
1588
1589 if (HasMatchingEnvironmentOrNone(Avail))
1590 return Avail;
1591 PartialMatch = Avail;
1592 }
1593 }
1594 }
1595 return PartialMatch;
1596}
1597
1598
1599
1600void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
1601 const AvailabilityAttr *AA,
1603
1605
1606 if (!IIEnv) {
1607
1608
1609
1610
1611
1612
1613
1614 if (SemaRef.getLangOpts().HLSLStrictAvailability)
1615 return;
1616
1617
1618
1619
1620 if (ReportOnlyShaderStageIssues)
1621 return;
1622
1623 } else {
1624
1625
1626 if (InUnknownShaderStageContext())
1627 return;
1628 }
1629
1630
1631 bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
1632 VersionTuple Introduced = AA->getIntroduced();
1635
1636 if (TargetVersion >= Introduced && EnvironmentMatches)
1637 return;
1638
1639
1641 llvm::StringRef PlatformName(
1642 AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
1643
1644 llvm::StringRef CurrentEnvStr =
1645 llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());
1646
1647 llvm::StringRef AttrEnvStr =
1648 AA->getEnvironment() ? AA->getEnvironment()->getName() : "";
1649 bool UseEnvironment = !AttrEnvStr.empty();
1650
1651 if (EnvironmentMatches) {
1653 << Range << D << PlatformName << Introduced.getAsString()
1654 << UseEnvironment << CurrentEnvStr;
1655 } else {
1656 SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)
1658 }
1659
1660 SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)
1661 << D << PlatformName << Introduced.getAsString()
1663 << UseEnvironment << AttrEnvStr << CurrentEnvStr;
1664}
1665
1666}
1667
1669
1670
1671
1672
1675 TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)
1676 return;
1677
1678 DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);
1679}
1680
1681
1685
1687
1690
1691 bool AllBArgAreVectors = true;
1692 for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {
1696 if (VecTyB == nullptr)
1697 AllBArgAreVectors &= false;
1698 if (VecTyA && VecTyB == nullptr) {
1699
1700
1701 S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1702 << TheCall->getDirectCallee() << true
1704 return true;
1705 }
1706 if (VecTyA && VecTyB) {
1707 bool retValue = false;
1708 if (VecTyA->getElementType() != VecTyB->getElementType()) {
1709
1710
1712 diag::err_vec_builtin_incompatible_vector)
1713 << TheCall->getDirectCallee() << true
1715 retValue = true;
1716 }
1717 if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
1718
1719
1720
1721 S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
1722 << TheCall->getDirectCallee() << true
1724 retValue = true;
1725 }
1726 if (retValue)
1727 return retValue;
1728 }
1729 }
1730
1731 if (VecTyA == nullptr && AllBArgAreVectors) {
1732
1733
1734 S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
1735 << TheCall->getDirectCallee() << true
1737 return true;
1738 }
1739 return false;
1740}
1741
1745 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
1747 return true;
1748 }
1749 return false;
1750}
1751
1754 llvm::function_ref<bool(clang::QualType PassedType)> Check) {
1756 if (Check(PassedType)) {
1759 ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
1760 S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
1761 << PassedType << ExpectedType << 1 << 0 << 0;
1762 return true;
1763 }
1764 return false;
1765}
1766
1769 llvm::function_ref<bool(clang::QualType PassedType)> Check) {
1770 for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
1773 return true;
1774 }
1775 }
1776 return false;
1777}
1778
1780 auto checkAllFloatTypes = [](clang::QualType PassedType) -> bool {
1781 return !PassedType->hasFloatingRepresentation();
1782 };
1784 checkAllFloatTypes);
1785}
1786
1788 auto checkFloatorHalf = [](clang::QualType PassedType) -> bool {
1792 : PassedType;
1794 };
1796 checkFloatorHalf);
1797}
1798
1800 unsigned ArgIndex) {
1801 auto *Arg = TheCall->getArg(ArgIndex);
1805 return false;
1806 S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;
1807 return true;
1808}
1809
1811 auto checkDoubleVector = [](clang::QualType PassedType) -> bool {
1812 if (const auto *VecTy = PassedType->getAs<VectorType>())
1813 return VecTy->getElementType()->isDoubleType();
1814 return false;
1815 };
1817 checkDoubleVector);
1818}
1820 auto checkAllSignedTypes = [](clang::QualType PassedType) -> bool {
1821 return !PassedType->hasIntegerRepresentation() &&
1822 !PassedType->hasFloatingRepresentation();
1823 };
1825 checkAllSignedTypes);
1826}
1827
1829 auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool {
1830 return !PassedType->hasUnsignedIntegerRepresentation();
1831 };
1833 checkAllUnsignedTypes);
1834}
1835
1839 if (VecTyA)
1842 TheCall->setType(ReturnType);
1843}
1844
1846 unsigned ArgIndex) {
1847 assert(TheCall->getNumArgs() >= ArgIndex);
1850
1852 (VTy &&
1855 diag::err_typecheck_expect_scalar_or_vector)
1856 << ArgType << Scalar;
1857 return true;
1858 }
1859 return false;
1860}
1861
1863 unsigned ArgIndex) {
1864 assert(TheCall->getNumArgs() >= ArgIndex);
1867
1869 (VTy && VTy->getElementType()->isScalarType()))) {
1871 diag::err_typecheck_expect_any_scalar_or_vector)
1872 << ArgType << 1;
1873 return true;
1874 }
1875 return false;
1876}
1877
1883
1885 (VTy &&
1888 diag::err_typecheck_expect_any_scalar_or_vector)
1889 << ArgType << 0;
1890 return true;
1891 }
1892 return false;
1893}
1894
1901 diag::err_typecheck_call_different_arg_types)
1904 return true;
1905 }
1906
1908 return false;
1909}
1910
1916 S->Diag(Arg1->getBeginLoc(), diag::err_builtin_non_vector_type)
1919 return true;
1920 }
1921
1923 S->Diag(Arg2->getBeginLoc(), diag::err_builtin_non_vector_type)
1926 return true;
1927 }
1928
1931 diag::err_typecheck_call_different_arg_types)
1934 return true;
1935 }
1936
1937
1938
1942 diag::err_typecheck_vector_lengths_not_equal)
1945 return true;
1946 }
1948 return false;
1949}
1950
1952 Sema *S, CallExpr *TheCall, unsigned ArgIndex,
1954 nullptr) {
1955 assert(TheCall->getNumArgs() >= ArgIndex);
1959 if (!ResTy) {
1961 diag::err_typecheck_expect_hlsl_resource)
1962 << ArgType;
1963 return true;
1964 }
1965 if (Check && Check(ResTy)) {
1967 diag::err_invalid_hlsl_resource_type)
1968 << ArgType;
1969 return true;
1970 }
1971 return false;
1972}
1973
1974
1975
1977 switch (BuiltinID) {
1978 case Builtin::BI__builtin_hlsl_resource_getpointer: {
1983 return true;
1984
1985 auto *ResourceTy =
1987 QualType ContainedTy = ResourceTy->getContainedType();
1988
1991
1992 break;
1993 }
1994 case Builtin::BI__builtin_hlsl_all:
1995 case Builtin::BI__builtin_hlsl_any: {
1997 return true;
1998 break;
1999 }
2000 case Builtin::BI__builtin_hlsl_asdouble: {
2002 return true;
2004 return true;
2005
2007 break;
2008 }
2009 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
2011 return true;
2013 return true;
2015 TheCall,
2017 return true;
2018 break;
2019 }
2020 case Builtin::BI__builtin_hlsl_cross: {
2022 return true;
2024 return true;
2026 return true;
2027
2028 int NumElementsArg1 =
2030 int NumElementsArg2 =
2032
2033 if (NumElementsArg1 != 3) {
2034 int LessOrMore = NumElementsArg1 > 3 ? 1 : 0;
2036 diag::err_vector_incorrect_num_elements)
2037 << LessOrMore << 3 << NumElementsArg1 << 1;
2038 return true;
2039 }
2040 if (NumElementsArg2 != 3) {
2041 int LessOrMore = NumElementsArg2 > 3 ? 1 : 0;
2042
2044 diag::err_vector_incorrect_num_elements)
2045 << LessOrMore << 3 << NumElementsArg2 << 1;
2046 return true;
2047 }
2048
2051
2052 TheCall->setType(ArgTyA);
2053 break;
2054 }
2055 case Builtin::BI__builtin_hlsl_dot: {
2057 return true;
2059 return true;
2061 return true;
2063 return true;
2064 break;
2065 }
2066 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:
2067 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
2069 return true;
2070
2071 const Expr *Arg = TheCall->getArg(0);
2074
2076
2078 EltTy = VecTy->getElementType();
2080 VecTy->getVectorKind());
2081 }
2082
2084 Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2085 << 1 << 6 << ArgTy;
2086 return true;
2087 }
2088
2089 TheCall->setType(ResTy);
2090 break;
2091 }
2092 case Builtin::BI__builtin_hlsl_select: {
2094 return true;
2096 return true;
2099 return true;
2101 if (VTy && VTy->getElementType()->isBooleanType() &&
2103 return true;
2104 break;
2105 }
2106 case Builtin::BI__builtin_hlsl_elementwise_saturate:
2107 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
2109 return true;
2111 return true;
2112 break;
2113 }
2114 case Builtin::BI__builtin_hlsl_elementwise_degrees:
2115 case Builtin::BI__builtin_hlsl_elementwise_radians:
2116 case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
2117 case Builtin::BI__builtin_hlsl_elementwise_frac: {
2119 return true;
2121 return true;
2122 break;
2123 }
2124 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
2126 return true;
2128 return true;
2130 break;
2131 }
2132 case Builtin::BI__builtin_hlsl_lerp: {
2134 return true;
2136 return true;
2138 return true;
2140 return true;
2141 break;
2142 }
2143 case Builtin::BI__builtin_hlsl_mad: {
2145 return true;
2147 return true;
2149 TheCall,
2151 return true;
2152 break;
2153 }
2154 case Builtin::BI__builtin_hlsl_normalize: {
2156 return true;
2158 return true;
2159
2162
2163 TheCall->setType(ArgTyA);
2164 break;
2165 }
2166 case Builtin::BI__builtin_hlsl_elementwise_sign: {
2168 return true;
2170 return true;
2172 break;
2173 }
2174 case Builtin::BI__builtin_hlsl_step: {
2176 return true;
2178 return true;
2179
2182
2183 TheCall->setType(ArgTyA);
2184 break;
2185 }
2186 case Builtin::BI__builtin_hlsl_wave_active_sum: {
2188 return true;
2189
2190
2192 return true;
2194 return true;
2197 TheCall->setType(ArgTyExpr);
2198 break;
2199 }
2200
2201
2202 case Builtin::BI__builtin_elementwise_bitreverse: {
2204 return true;
2205 break;
2206 }
2207 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
2209 return true;
2210
2211
2213 QualType ArgTyIndex = Index.get()->getType();
2216 diag::err_typecheck_convert_incompatible)
2218 return true;
2219 }
2220
2221
2223 return true;
2224
2227 TheCall->setType(ArgTyExpr);
2228 break;
2229 }
2230 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
2232 return true;
2233 break;
2234 }
2235 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
2237 return true;
2238
2241 1) ||
2243 2))
2244 return true;
2245
2248 return true;
2249 break;
2250 }
2251 case Builtin::BI__builtin_hlsl_elementwise_clip: {
2253 return true;
2254
2256 return true;
2257 break;
2258 }
2259 case Builtin::BI__builtin_elementwise_acos:
2260 case Builtin::BI__builtin_elementwise_asin:
2261 case Builtin::BI__builtin_elementwise_atan:
2262 case Builtin::BI__builtin_elementwise_atan2:
2263 case Builtin::BI__builtin_elementwise_ceil:
2264 case Builtin::BI__builtin_elementwise_cos:
2265 case Builtin::BI__builtin_elementwise_cosh:
2266 case Builtin::BI__builtin_elementwise_exp:
2267 case Builtin::BI__builtin_elementwise_exp2:
2268 case Builtin::BI__builtin_elementwise_floor:
2269 case Builtin::BI__builtin_elementwise_fmod:
2270 case Builtin::BI__builtin_elementwise_log:
2271 case Builtin::BI__builtin_elementwise_log2:
2272 case Builtin::BI__builtin_elementwise_log10:
2273 case Builtin::BI__builtin_elementwise_pow:
2274 case Builtin::BI__builtin_elementwise_roundeven:
2275 case Builtin::BI__builtin_elementwise_sin:
2276 case Builtin::BI__builtin_elementwise_sinh:
2277 case Builtin::BI__builtin_elementwise_sqrt:
2278 case Builtin::BI__builtin_elementwise_tan:
2279 case Builtin::BI__builtin_elementwise_tanh:
2280 case Builtin::BI__builtin_elementwise_trunc: {
2282 return true;
2283 break;
2284 }
2285 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
2287 return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
2288 ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
2289 };
2294 return true;
2295 Expr *OffsetExpr = TheCall->getArg(1);
2296 std::optionalllvm::APSInt Offset =
2298 if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {
2300 diag::err_hlsl_expect_arg_const_int_one_or_neg_one)
2301 << 1;
2302 return true;
2303 }
2304 break;
2305 }
2306 }
2307 return false;
2308}
2309
2313 WorkList.push_back(BaseTy);
2314 while (!WorkList.empty()) {
2315 QualType T = WorkList.pop_back_val();
2316 T = T.getCanonicalType().getUnqualifiedType();
2317 assert(!isa(T) && "Matrix types not yet supported in HLSL");
2318 if (const auto *AT = dyn_cast(T)) {
2320
2321
2322
2323
2325
2326 for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)
2327 List.insert(List.end(), ElementFields.begin(), ElementFields.end());
2328 continue;
2329 }
2330
2331
2332 if (const auto *VT = dyn_cast(T)) {
2333 List.insert(List.end(), VT->getNumElements(), VT->getElementType());
2334 continue;
2335 }
2336 if (const auto *RT = dyn_cast(T)) {
2339 List.push_back(T);
2340 continue;
2341 }
2342 const CXXRecordDecl *CXXD = dyn_cast(RD);
2343
2347
2348 for (const auto *FD : RD->fields())
2349 FieldTypes.push_back(FD->getType());
2350
2351 std::reverse(FieldTypes.begin(), FieldTypes.end());
2352 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2353
2354
2355
2357 FieldTypes.clear();
2358 for (const auto &Base : CXXD->bases())
2359 FieldTypes.push_back(Base.getType());
2360 std::reverse(FieldTypes.begin(), FieldTypes.end());
2361 WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
2362 }
2363 continue;
2364 }
2365 List.push_back(T);
2366 }
2367}
2368
2370
2372 return false;
2373
2374
2376 return false;
2377
2379 return false;
2380
2381
2384 return false;
2385 return true;
2386 }
2387
2389 int ArraySize = VT->getNumElements();
2390
2391 if (ArraySize > 4)
2392 return false;
2393
2394 QualType ElTy = VT->getElementType();
2396 return false;
2397
2399 return false;
2400 return true;
2401 }
2402
2403 return false;
2404}
2405
2408 return false;
2409
2412
2413
2415 return true;
2416
2421
2422
2423 return llvm::equal(T1Types, T2Types,
2426 });
2427}
2428
2432 return true;
2433
2434 bool HadError = false;
2435
2436 for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {
2439
2440
2441
2442
2443
2444 const auto *NDAttr = NewParam->getAttr();
2445 unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);
2446 const auto *ODAttr = OldParam->getAttr();
2447 unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);
2448
2449 if (NSpellingIdx != OSpellingIdx) {
2451 diag::err_hlsl_param_qualifier_mismatch)
2452 << NDAttr << NewParam;
2454 << ODAttr;
2455 HadError = true;
2456 }
2457 }
2458 return HadError;
2459}
2460
2462 assert(Param->hasAttr() &&
2463 "We should not get here without a parameter modifier expression");
2464 const auto *Attr = Param->getAttr();
2467
2471 << Arg << (IsInOut ? 1 : 0);
2473 }
2474
2476
2478
2479
2480
2481
2484 << Arg << (IsInOut ? 1 : 0);
2486 }
2487
2490
2491
2492
2500
2502 auto *OpV = new (Ctx)
2504
2505
2506
2508 tok::equal, ArgOpV, OpV);
2509
2512 Expr *Writeback = Res.get();
2513 auto *OutExpr =
2515
2517}
2518
2520
2521
2522
2524 "Pointer and reference types cannot be inout or out parameters");
2527 return Ty;
2528}
2529
2532
2536 diag::err_typecheck_decl_incomplete_type)) {
2538 return;
2539 }
2540
2541
2543 collectResourcesOnVarDecl(VD);
2544
2545
2546 processExplicitBindingsOnDecl(VD);
2547 }
2548}
2549
2550
2551
2552void SemaHLSL::collectResourcesOnVarDecl(VarDecl *VD) {
2554 "expected global variable that contains HLSL resource");
2555
2556
2557 if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast(VD)) {
2558 Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()
2559 ? ResourceClass::CBuffer
2560 : ResourceClass::SRV);
2561 return;
2562 }
2563
2564
2565
2570 }
2571
2572
2575 Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);
2576 return;
2577 }
2578
2579
2580 if (const RecordType *RT = dyn_cast(Ty))
2581 collectResourcesOnUserRecordDecl(VD, RT);
2582}
2583
2584
2585
2586
2587void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
2588 assert(VD->hasGlobalStorage() && "expected global variable");
2589
2591 HLSLResourceBindingAttr *RBA = dyn_cast(A);
2592 if (!RBA)
2593 continue;
2594
2596 assert(RT != RegisterType::I && "invalid or obsolete register type should "
2597 "never have an attribute created");
2598
2599 if (RT == RegisterType::C) {
2600 if (Bindings.hasBindingInfoForDecl(VD))
2602 diag::warn_hlsl_user_defined_type_missing_member)
2603 << static_cast<int>(RT);
2604 continue;
2605 }
2606
2607
2608
2609
2612
2614 } else {
2616 diag::warn_hlsl_user_defined_type_missing_member)
2617 << static_cast<int>(RT);
2618 }
2619 }
2620}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType)
static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl< QualType > &List)
static QualType handleIntegerVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static bool convertToRegisterType(StringRef Slot, RegisterType *RT)
static bool CheckWaveActive(Sema *S, CallExpr *TheCall)
static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz)
static bool CheckBoolSelect(Sema *S, CallExpr *TheCall)
static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall)
static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
static bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall)
static bool CheckFloatingOrIntRepresentation(Sema *S, CallExpr *TheCall)
static bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall)
static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType)
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
static RegisterType getRegisterType(ResourceClass RC)
static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall, unsigned ArgIndex)
static QualType castElement(Sema &S, ExprResult &E, QualType Ty)
static bool CheckArgTypeIsCorrect(Sema *S, Expr *Arg, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)
static bool CheckVectorSelect(Sema *S, CallExpr *TheCall)
static QualType handleFloatVectorBinOpConversion(Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign)
static ResourceClass getResourceClass(RegisterType RT)
static bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall)
static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar, unsigned ArgIndex)
static bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall)
static bool CheckResourceHandle(Sema *S, CallExpr *TheCall, unsigned ArgIndex, llvm::function_ref< bool(const HLSLAttributedResourceType *ResType)> Check=nullptr)
static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl)
HLSLResourceBindingAttr::RegisterType RegisterType
static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy, QualType SrcTy)
static bool isValidWaveSizeValue(unsigned Value)
static bool CheckAllArgTypesAreCorrect(Sema *S, CallExpr *TheCall, QualType ExpectedType, llvm::function_ref< bool(clang::QualType PassedType)> Check)
static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl, RegisterType regType)
static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc, Decl *D, RegisterType RegType, bool SpecifiedSpace)
This file declares semantic analysis for HLSL constructs.
Defines the clang::SourceLocation class and associated facilities.
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
unsigned getIntWidth(QualType T) const
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified 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....
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType UnsignedIntTy
QualType getCommonSugaredType(QualType X, QualType Y, bool Unqualified=false)
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
const TargetInfo & getTargetInfo() const
QualType getCorrespondingUnsignedType(QualType T) const
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
QualType getElementType() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceRange getRange() const
SourceLocation getLoc() const
Represents a C++ struct/union/class.
bool isStandardLayout() const
Determine whether this class is standard-layout per C++ [class]p7.
const CXXRecordDecl * getStandardLayoutBaseWithFields() const
If this is a standard-layout class or union, any and all data members will be declared in the same ty...
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 LLVM_READONLY
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.
Represents the canonical version of C arrays with a specified constant size.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
A reference to a declared variable, function, enum, etc.
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
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
Recursive AST visitor that supports extension via dynamic dispatch.
This represents one expression.
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, does not have an incomplet...
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Represents a member of a struct/union/class.
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 ...
ArrayRef< ParmVarDecl * > parameters() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
static const HLSLAttributedResourceType * findHandleTypeOnResource(const Type *RT)
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
static HLSLOutArgExpr * Create(const ASTContext &C, QualType Ty, OpaqueValueExpr *Base, OpaqueValueExpr *OpV, Expr *WB, bool IsInOut)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
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.
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.
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool hasBindingInfoForDecl(const VarDecl *VD) const
DeclBindingInfo * getDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
DeclBindingInfo * addDeclBindingInfo(const VarDecl *VD, ResourceClass ResClass)
Scope - A scope is a transient data structure that is used while parsing the program.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg)
void DiagnoseAttrStageMismatch(const Attr *A, llvm::Triple::EnvironmentType Stage, std::initializer_list< llvm::Triple::EnvironmentType > AllowedStages)
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL)
HLSLAttributedResourceLocInfo TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT)
QualType ProcessResourceTypeAttributes(QualType Wrapped)
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL)
void handleShaderAttr(Decl *D, const ParsedAttr &AL)
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL)
void CheckEntryPoint(FunctionDecl *FD)
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL)
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL)
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL)
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old)
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign)
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL)
bool IsTypedResourceElementCompatible(QualType T1)
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL)
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU)
void ActOnTopLevelFunction(FunctionDecl *FD)
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, llvm::Triple::EnvironmentType ShaderType)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
QualType getInoutParameterType(QualType Ty)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
HLSLWaveSizeAttr * mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, int Min, int Max, int Preferred, int SpelledArgsCount)
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL)
void ActOnVariableDeclarator(VarDecl *VD)
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Sema - This implements semantic analysis and AST building for C.
Scope * getCurScope() const
Retrieve the parser's current scope.
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
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.
bool BuiltinVectorToScalarMath(CallExpr *TheCall)
bool IsLayoutCompatible(QualType T1, QualType T2) const
const LangOptions & getLangOpts() const
bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall)
DeclContext * getCurLexicalContext() const
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
bool BuiltinElementwiseTernaryMath(CallExpr *TheCall, bool CheckForFloatArgs=true)
ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr)
Binary Operators. 'Tok' is the token for the operator.
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() 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
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 isStructureType() const
bool isBooleanType() const
bool isIncompleteArrayType() const
bool isConstantArrayType() const
bool isArithmeticType() 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.
bool isFloat32Type() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
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 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
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Represents a GCC generic vector type.
unsigned getNumElements() const
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
The JSON file list parser is used to communicate input to InstallAPI.
@ OK_Ordinary
An ordinary object is located at an address in memory.
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
@ Ordinary
This parameter uses ordinary ABI rules for its type.
ActionResult< Expr * > ExprResult
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const FunctionProtoType * T
@ Generic
not a target-specific vector type
Diagnostic wrappers for TextAPI types for error reporting.
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
TypeSourceInfo * ContainedTyInfo
llvm::dxil::ResourceClass ResourceClass
Wraps an identifier and optional source location for the identifier.
Describes how types, statements, expressions, and declarations should be printed.