clang: lib/Sema/SemaARM.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
20
22
24
25
29
30 if (BuiltinID == AArch64::BI__builtin_arm_irg) {
32 return true;
35
38 return true;
41 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
43 TheCall->setArg(0, FirstArg.get());
44
47 return true;
50 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
52
53
54 TheCall->setType(FirstArgType);
55 return false;
56 }
57
58 if (BuiltinID == AArch64::BI__builtin_arm_addg) {
60 return true;
61
65 return true;
68 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
70 TheCall->setArg(0, FirstArg.get());
71
72
73 TheCall->setType(FirstArgType);
74
75
77 }
78
79 if (BuiltinID == AArch64::BI__builtin_arm_gmi) {
81 return true;
84
87 return true;
90 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
92
95 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
97 TheCall->setType(Context.IntTy);
98 return false;
99 }
100
101 if (BuiltinID == AArch64::BI__builtin_arm_ldg ||
102 BuiltinID == AArch64::BI__builtin_arm_stg) {
104 return true;
108 return true;
109
112 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
113 << "first" << FirstArgType << Arg0->getSourceRange();
114 TheCall->setArg(0, FirstArg.get());
115
116
117 if (BuiltinID == AArch64::BI__builtin_arm_ldg)
118 TheCall->setType(FirstArgType);
119 return false;
120 }
121
122 if (BuiltinID == AArch64::BI__builtin_arm_subp) {
125
128
130 return true;
131
134
135 auto isNull = [&](Expr *E) -> bool {
136 return E->isNullPointerConstant(Context,
138 };
139
140
142 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
144
146 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
148
149
154 if (!Context.typesAreCompatible(
155 Context.getCanonicalType(pointeeA).getUnqualifiedType(),
156 Context.getCanonicalType(pointeeB).getUnqualifiedType())) {
158 diag::err_typecheck_sub_ptr_compatible)
161 }
162 }
163
164
166 return Diag(TheCall->getBeginLoc(), diag::err_memtag_any2arg_pointer)
168
169 if (isNull(ArgA))
170 ArgExprA =
172
173 if (isNull(ArgB))
174 ArgExprB =
176
177 TheCall->setArg(0, ArgExprA.get());
178 TheCall->setArg(1, ArgExprB.get());
179 TheCall->setType(Context.LongLongTy);
180 return false;
181 }
182 assert(false && "Unhandled ARM MTE intrinsic");
183 return true;
184}
185
186
187
189 int ArgNum, unsigned ExpectedFieldNum,
190 bool AllowName) {
191 bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
192 BuiltinID == ARM::BI__builtin_arm_wsr64 ||
193 BuiltinID == ARM::BI__builtin_arm_rsr ||
194 BuiltinID == ARM::BI__builtin_arm_rsrp ||
195 BuiltinID == ARM::BI__builtin_arm_wsr ||
196 BuiltinID == ARM::BI__builtin_arm_wsrp;
197 bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
198 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
199 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
200 BuiltinID == AArch64::BI__builtin_arm_wsr128 ||
201 BuiltinID == AArch64::BI__builtin_arm_rsr ||
202 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
203 BuiltinID == AArch64::BI__builtin_arm_wsr ||
204 BuiltinID == AArch64::BI__builtin_arm_wsrp;
205 assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin.");
206
207
210 return false;
211
212
214 return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
216
217
218 StringRef Reg = cast(Arg->IgnoreParenImpCasts())->getString();
220 Reg.split(Fields, ":");
221
222 if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
223 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
225
226
227
228
229
230 if (Fields.size() > 1) {
231 bool FiveFields = Fields.size() == 5;
232
233 bool ValidString = true;
234 if (IsARMBuiltin) {
235 ValidString &= Fields[0].starts_with_insensitive("cp") ||
236 Fields[0].starts_with_insensitive("p");
237 if (ValidString)
238 Fields[0] = Fields[0].drop_front(
239 Fields[0].starts_with_insensitive("cp") ? 2 : 1);
240
241 ValidString &= Fields[2].starts_with_insensitive("c");
242 if (ValidString)
243 Fields[2] = Fields[2].drop_front(1);
244
245 if (FiveFields) {
246 ValidString &= Fields[3].starts_with_insensitive("c");
247 if (ValidString)
248 Fields[3] = Fields[3].drop_front(1);
249 }
250 }
251
253 if (FiveFields)
254 Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 15, 15, 7});
255 else
256 Ranges.append({15, 7, 15});
257
258 for (unsigned i = 0; i < Fields.size(); ++i) {
259 int IntField;
260 ValidString &= !Fields[i].getAsInteger(10, IntField);
261 ValidString &= (IntField >= 0 && IntField <= Ranges[i]);
262 }
263
264 if (!ValidString)
265 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
267 } else if (IsAArch64Builtin && Fields.size() == 1) {
268
269
270
272 return false;
273
274
275 if (BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
276 BuiltinID == AArch64::BI__builtin_arm_wsr128)
277 return false;
278
279
280
281 auto MaxLimit = llvm::StringSwitch<std::optional>(Reg)
282 .CaseLower("spsel", 15)
283 .CaseLower("daifclr", 15)
284 .CaseLower("daifset", 15)
285 .CaseLower("pan", 15)
286 .CaseLower("uao", 15)
287 .CaseLower("dit", 15)
288 .CaseLower("ssbs", 15)
289 .CaseLower("tco", 15)
290 .CaseLower("allint", 1)
291 .CaseLower("pm", 1)
292 .Default(std::nullopt);
293
294
295
296 if (!MaxLimit)
297 return false;
298
299
300
301
302
303
304
305
306
307
308
309
310
311
313 }
314
315 return false;
316}
317
318
319
320
322 bool IsPolyUnsigned, bool IsInt64Long) {
331 if (IsInt64Long)
333 else
341 if (IsInt64Long)
343 else
346 break;
348 return Context.HalfTy;
355 }
356 llvm_unreachable("Invalid NeonTypeFlag!");
357}
358
361
366
372
374 unsigned ArgIdx, unsigned EltBitWidth,
375 unsigned ContainerBitWidth) {
376
377
378 auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set,
379 int ErrDiag) -> bool {
380
383 return false;
384
385
386 llvm::APSInt Imm;
388 return true;
389
390 if (std::find(Set.begin(), Set.end(), Imm.getSExtValue()) == Set.end())
392 return false;
393 };
394
396 case ImmCheckType::ImmCheck0_31:
398 return true;
399 break;
400 case ImmCheckType::ImmCheck0_13:
402 return true;
403 break;
404 case ImmCheckType::ImmCheck0_63:
406 return true;
407 break;
408 case ImmCheckType::ImmCheck1_16:
410 return true;
411 break;
412 case ImmCheckType::ImmCheck0_7:
414 return true;
415 break;
416 case ImmCheckType::ImmCheck1_1:
418 return true;
419 break;
420 case ImmCheckType::ImmCheck1_3:
422 return true;
423 break;
424 case ImmCheckType::ImmCheck1_7:
426 return true;
427 break;
428 case ImmCheckType::ImmCheckExtract:
430 (2048 / EltBitWidth) - 1))
431 return true;
432 break;
433 case ImmCheckType::ImmCheckCvt:
434 case ImmCheckType::ImmCheckShiftRight:
436 return true;
437 break;
438 case ImmCheckType::ImmCheckShiftRightNarrow:
440 return true;
441 break;
442 case ImmCheckType::ImmCheckShiftLeft:
444 return true;
445 break;
446 case ImmCheckType::ImmCheckLaneIndex:
448 (ContainerBitWidth / EltBitWidth) - 1))
449 return true;
450 break;
451 case ImmCheckType::ImmCheckLaneIndexCompRotate:
453 TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1))
454 return true;
455 break;
456 case ImmCheckType::ImmCheckLaneIndexDot:
458 TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1))
459 return true;
460 break;
461 case ImmCheckType::ImmCheckComplexRot90_270:
462 if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))
463 return true;
464 break;
465 case ImmCheckType::ImmCheckComplexRotAll90:
466 if (CheckImmediateInSet({0, 90, 180, 270},
467 diag::err_rotation_argument_to_cmla))
468 return true;
469 break;
470 case ImmCheckType::ImmCheck0_1:
472 return true;
473 break;
474 case ImmCheckType::ImmCheck0_2:
476 return true;
477 break;
478 case ImmCheckType::ImmCheck0_3:
480 return true;
481 break;
482 case ImmCheckType::ImmCheck0_0:
484 return true;
485 break;
486 case ImmCheckType::ImmCheck0_15:
488 return true;
489 break;
490 case ImmCheckType::ImmCheck0_255:
492 return true;
493 break;
494 case ImmCheckType::ImmCheck1_32:
496 return true;
497 break;
498 case ImmCheckType::ImmCheck1_64:
500 return true;
501 break;
502 case ImmCheckType::ImmCheck2_4_Mul2:
505 return true;
506 break;
507 }
508 return false;
509}
510
513 SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks,
514 int OverloadType) {
515 bool HasError = false;
516
517 for (const auto &I : ImmChecks) {
518 auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I;
519
520 if (OverloadType >= 0)
522
523 HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth,
524 VecBitWidth);
525 }
526
527 return HasError;
528}
529
532 bool HasError = false;
533
534 for (const auto &I : ImmChecks) {
535 auto [ArgIdx, CheckTy, ElementBitWidth] = I;
536 HasError |=
537 CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128);
538 }
539
540 return HasError;
541}
542
544 if (FD->hasAttr())
548 if (FPT->getAArch64SMEAttributes() &
551 if (FPT->getAArch64SMEAttributes() &
554 }
555 }
557}
558
562 unsigned BuiltinID) {
564
565
566
567
568
570 llvm::StringMap CallerFeatureMapWithoutSVE;
572 CallerFeatureMapWithoutSVE["sve"] = false;
573
574
576 return false;
577
578 llvm::StringMap CallerFeatureMapWithoutSME;
580 CallerFeatureMapWithoutSME["sme"] = false;
581
582
583
584
585
586
587
588
589
590
591
592 StringRef BuiltinTargetGuards(
595 BuiltinTargetGuards, CallerFeatureMapWithoutSME);
597 BuiltinTargetGuards, CallerFeatureMapWithoutSVE);
598
599 if ((SatisfiesSVE && SatisfiesSME) ||
601 return false;
602 else if (SatisfiesSVE)
604 else if (SatisfiesSME)
606 else
607
608 return false;
609 }
610
613 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
617 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
619 else
620 return false;
621
622 return true;
623}
624
629 (FD->hasAttr() && FD->getAttr()->isNewZA());
630}
631
636 (FD->hasAttr() && FD->getAttr()->isNewZT0());
637}
638
640 switch (BuiltinID) {
641 default:
643#define GET_SME_BUILTIN_GET_STATE
644#include "clang/Basic/arm_sme_builtins_za_state.inc"
645#undef GET_SME_BUILTIN_GET_STATE
646 }
647}
648
652 std::optional BuiltinType;
653
654 switch (BuiltinID) {
655#define GET_SME_STREAMING_ATTRS
656#include "clang/Basic/arm_sme_streaming_attrs.inc"
657#undef GET_SME_STREAMING_ATTRS
658 }
659
662 return true;
663
666 diag::warn_attribute_arm_za_builtin_no_za_state)
668
671 diag::warn_attribute_arm_zt0_builtin_no_zt0_state)
673 }
674
675
677
678 switch (BuiltinID) {
679 default:
680 return false;
681#define GET_SME_IMMEDIATE_CHECK
682#include "clang/Basic/arm_sme_sema_rangechecks.inc"
683#undef GET_SME_IMMEDIATE_CHECK
684 }
685
687}
688
692 std::optional BuiltinType;
693
694 switch (BuiltinID) {
695#define GET_SVE_STREAMING_ATTRS
696#include "clang/Basic/arm_sve_streaming_attrs.inc"
697#undef GET_SVE_STREAMING_ATTRS
698 }
701 return true;
702 }
703
705
706 switch (BuiltinID) {
707 default:
708 return false;
709#define GET_SVE_IMMEDIATE_CHECK
710#include "clang/Basic/arm_sve_sema_rangechecks.inc"
711#undef GET_SVE_IMMEDIATE_CHECK
712 }
713
715}
716
718 unsigned BuiltinID,
721
722 switch (BuiltinID) {
723 default:
724 break;
725#define GET_NEON_BUILTINS
726#define TARGET_BUILTIN(id, ...) case NEON::BI##id:
727#define BUILTIN(id, ...) case NEON::BI##id:
728#include "clang/Basic/arm_neon.inc"
730 BuiltinID))
731 return true;
732 break;
733#undef TARGET_BUILTIN
734#undef BUILTIN
735#undef GET_NEON_BUILTINS
736 }
737 }
738
740 uint64_t mask = 0;
741 int TV = -1;
742 int PtrArgNum = -1;
743 bool HasConstPtr = false;
744 switch (BuiltinID) {
745#define GET_NEON_OVERLOAD_CHECK
746#include "clang/Basic/arm_fp16.inc"
747#include "clang/Basic/arm_neon.inc"
748#undef GET_NEON_OVERLOAD_CHECK
749 }
750
751
752
753 unsigned ImmArg = TheCall->getNumArgs() - 1;
754 if (mask) {
756 return true;
757
758 TV = Result.getLimitedValue(64);
759 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
760 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
762 }
763
764 if (PtrArgNum >= 0) {
765
766 Expr *Arg = TheCall->getArg(PtrArgNum);
768 Arg = ICE->getSubExpr();
771
772 llvm::Triple::ArchType Arch = TI.getTriple().getArch();
773 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
774 Arch == llvm::Triple::aarch64_32 ||
775 Arch == llvm::Triple::aarch64_be;
778 IsPolyUnsigned, IsInt64Long);
779 if (HasConstPtr)
785 return true;
787 RHSTy, RHS.get(),
789 return true;
790 }
791
792
793
795 switch (BuiltinID) {
796 default:
797 return false;
798#define GET_NEON_IMMEDIATE_CHECK
799#include "clang/Basic/arm_fp16.inc"
800#include "clang/Basic/arm_neon.inc"
801#undef GET_NEON_IMMEDIATE_CHECK
802 }
803
805}
806
809 switch (BuiltinID) {
810 default:
811 return false;
812#include "clang/Basic/arm_mve_builtin_sema.inc"
813 }
814}
815
817 unsigned BuiltinID,
819 bool Err = false;
820 switch (BuiltinID) {
821 default:
822 return false;
823#include "clang/Basic/arm_cde_builtin_sema.inc"
824 }
825
826 if (Err)
827 return true;
828
830}
831
833 const Expr *CoprocArg,
834 bool WantCDE) {
837 return false;
838
839
841 return false;
842
844 int64_t CoprocNo = CoprocNoAP.getExtValue();
845 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
846
848 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
849
850 if (IsCDECoproc != WantCDE)
851 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
853
854 return false;
855}
856
859 unsigned MaxWidth) {
860 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
861 BuiltinID == ARM::BI__builtin_arm_ldaex ||
862 BuiltinID == ARM::BI__builtin_arm_strex ||
863 BuiltinID == ARM::BI__builtin_arm_stlex ||
864 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
865 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
866 BuiltinID == AArch64::BI__builtin_arm_strex ||
867 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
868 "unexpected ARM builtin");
869 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
870 BuiltinID == ARM::BI__builtin_arm_ldaex ||
871 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
872 BuiltinID == AArch64::BI__builtin_arm_ldaex;
873
877
878
880 return true;
881
882
883
884
885
886 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
890 return true;
891 PointerArg = PointerArgRes.get();
892
895 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
897 return true;
898 }
899
900
901
902
905 if (IsLdrex)
907
908
909 CastKind CastNeeded = CK_NoOp;
911 CastNeeded = CK_BitCast;
912 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
913 << PointerArg->getType() << Context.getPointerType(AddrType)
915 }
916
917
918 AddrType = Context.getPointerType(AddrType);
921 return true;
922 PointerArg = PointerArgRes.get();
923
924 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
925
926
929 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
931 return true;
932 }
933
934
935 if (Context.getTypeSize(ValType) > MaxWidth) {
936 assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
937 Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size)
939 return true;
940 }
941
945
946 break;
947
953 return true;
954 }
955
956 if (IsLdrex) {
957 TheCall->setType(ValType);
958 return false;
959 }
960
961
964 Context, ValType, false);
967 return true;
968 TheCall->setArg(0, ValArg.get());
969
970
971
972 TheCall->setType(Context.IntTy);
973 return false;
974}
975
977 unsigned BuiltinID,
979 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
980 BuiltinID == ARM::BI__builtin_arm_ldaex ||
981 BuiltinID == ARM::BI__builtin_arm_strex ||
982 BuiltinID == ARM::BI__builtin_arm_stlex) {
984 }
985
986 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
989 }
990
991 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
992 BuiltinID == ARM::BI__builtin_arm_wsr64)
994
995 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
996 BuiltinID == ARM::BI__builtin_arm_rsrp ||
997 BuiltinID == ARM::BI__builtin_arm_wsr ||
998 BuiltinID == ARM::BI__builtin_arm_wsrp)
1000
1002 return true;
1004 return true;
1006 return true;
1007
1008
1009
1010
1011 switch (BuiltinID) {
1012 default:
1013 return false;
1014 case ARM::BI__builtin_arm_ssat:
1016 case ARM::BI__builtin_arm_usat:
1018 case ARM::BI__builtin_arm_ssat16:
1020 case ARM::BI__builtin_arm_usat16:
1022 case ARM::BI__builtin_arm_vcvtr_f:
1023 case ARM::BI__builtin_arm_vcvtr_d:
1025 case ARM::BI__builtin_arm_dmb:
1026 case ARM::BI__builtin_arm_dsb:
1027 case ARM::BI__builtin_arm_isb:
1028 case ARM::BI__builtin_arm_dbg:
1030 case ARM::BI__builtin_arm_cdp:
1031 case ARM::BI__builtin_arm_cdp2:
1032 case ARM::BI__builtin_arm_mcr:
1033 case ARM::BI__builtin_arm_mcr2:
1034 case ARM::BI__builtin_arm_mrc:
1035 case ARM::BI__builtin_arm_mrc2:
1036 case ARM::BI__builtin_arm_mcrr:
1037 case ARM::BI__builtin_arm_mcrr2:
1038 case ARM::BI__builtin_arm_mrrc:
1039 case ARM::BI__builtin_arm_mrrc2:
1040 case ARM::BI__builtin_arm_ldc:
1041 case ARM::BI__builtin_arm_ldcl:
1042 case ARM::BI__builtin_arm_ldc2:
1043 case ARM::BI__builtin_arm_ldc2l:
1044 case ARM::BI__builtin_arm_stc:
1045 case ARM::BI__builtin_arm_stcl:
1046 case ARM::BI__builtin_arm_stc2:
1047 case ARM::BI__builtin_arm_stc2l:
1050 false);
1051 }
1052}
1053
1055 unsigned BuiltinID,
1057 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1058 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1059 BuiltinID == AArch64::BI__builtin_arm_strex ||
1060 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1062 }
1063
1064 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1069 }
1070
1071 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1072 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1073 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1074 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1076
1077
1078 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1079 BuiltinID == AArch64::BI__builtin_arm_addg ||
1080 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1081 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1082 BuiltinID == AArch64::BI__builtin_arm_stg ||
1083 BuiltinID == AArch64::BI__builtin_arm_subp) {
1085 }
1086
1087 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1088 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1089 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1090 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1092
1093
1094
1095
1096 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1097 BuiltinID == AArch64::BI_WriteStatusReg)
1099
1100 if (BuiltinID == AArch64::BI__getReg)
1102
1103 if (BuiltinID == AArch64::BI__break)
1105
1106 if (BuiltinID == AArch64::BI__hlt)
1108
1110 return true;
1111
1113 return true;
1114
1116 return true;
1117
1118
1119
1120 unsigned i = 0, l = 0, u = 0;
1121 switch (BuiltinID) {
1122 default: return false;
1123 case AArch64::BI__builtin_arm_dmb:
1124 case AArch64::BI__builtin_arm_dsb:
1125 case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break;
1126 case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break;
1127 }
1128
1130}
1131
1132namespace {
1133struct IntrinToName {
1137};
1138}
1139
1142 const char *IntrinNames) {
1143 AliasName.consume_front("__arm_");
1144 const IntrinToName *It =
1145 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
1146 return L.Id < Id;
1147 });
1148 if (It == Map.end() || It->Id != BuiltinID)
1149 return false;
1150 StringRef FullName(&IntrinNames[It->FullName]);
1152 return true;
1153 if (It->ShortName == -1)
1154 return false;
1155 StringRef ShortName(&IntrinNames[It->ShortName]);
1157}
1158
1160#include "clang/Basic/arm_mve_builtin_aliases.inc"
1161
1162
1163
1164 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1165}
1166
1168#include "clang/Basic/arm_cde_builtin_aliases.inc"
1169 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1170}
1171
1177}
1178
1184}
1185
1189 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1191 return;
1192 }
1193
1196 StringRef AliasName = cast(D)->getIdentifier()->getName();
1197
1198 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1199 if ((IsAArch64 && (BuiltinID, AliasName) &&
1201 (!IsAArch64 && (BuiltinID, AliasName) &&
1203 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
1204 return;
1205 }
1206
1207 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1208}
1209
1213 auto CheckForIncompatibleAttr =
1215 StringRef IncompatibleStateName) {
1216 if (CurrentState == IncompatibleState) {
1217 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1218 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
1219 << (std::string("'") + IncompatibleStateName.str() + "(\"" +
1220 StateName.str() + "\")'")
1221 << true;
1223 }
1224 };
1225
1231}
1232
1235 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
1237 return;
1238 }
1239
1240 std::vector NewState;
1241 if (const auto *ExistingAttr = D->getAttr()) {
1242 for (StringRef S : ExistingAttr->newArgs())
1243 NewState.push_back(S);
1244 }
1245
1246 bool HasZA = false;
1247 bool HasZT0 = false;
1248 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1249 StringRef StateName;
1252 return;
1253
1254 if (StateName == "za")
1255 HasZA = true;
1256 else if (StateName == "zt0")
1257 HasZT0 = true;
1258 else {
1259 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1261 return;
1262 }
1263
1264 if (!llvm::is_contained(NewState, StateName))
1265 NewState.push_back(StateName);
1266 }
1267
1268 if (auto *FPT = dyn_cast(D->getFunctionType())) {
1273 return;
1278 return;
1279 }
1280
1281 D->dropAttr();
1283 getASTContext(), AL, NewState.data(), NewState.size()));
1284}
1285
1288 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
1289 return;
1290 }
1291
1292 const auto *FD = cast(D);
1293 if (!FD->isExternallyVisible()) {
1294 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
1295 return;
1296 }
1297
1299}
1300
1302
1304 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1305 return;
1306 }
1307
1308 StringRef Str;
1310
1312 Str = "";
1314 return;
1315
1316 ARMInterruptAttr::InterruptType Kind;
1317 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1318 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1319 << AL << Str << ArgLoc;
1320 return;
1321 }
1322
1325 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1326
1329}
1330
1331
1332
1333
1335 const auto *Attr = FD->getAttr();
1336 bool UsesSM = FD->hasAttr();
1337 bool UsesZA = Attr && Attr->isNewZA();
1338 bool UsesZT0 = Attr && Attr->isNewZT0();
1339
1340 if (UsesZA || UsesZT0) {
1344 Diag(FD->getLocation(), diag::err_sme_unsupported_agnostic_new);
1345 }
1346 }
1347
1348 if (FD->hasAttr()) {
1351 diag::warn_sme_locally_streaming_has_vl_args_returns)
1352 << false;
1354 return P->getOriginalType()->isSizelessVectorType();
1355 }))
1357 diag::warn_sme_locally_streaming_has_vl_args_returns)
1358 << true;
1359 }
1367 }
1368
1370 if (UsesSM || UsesZA) {
1371 llvm::StringMap FeatureMap;
1372 Context.getFunctionFeatureMap(FeatureMap, FD);
1373 if (!FeatureMap.contains("sme")) {
1374 if (UsesSM)
1376 diag::err_sme_definition_using_sm_in_non_sme_target);
1377 else
1379 diag::err_sme_definition_using_za_in_non_sme_target);
1380 }
1381 }
1382 if (UsesZT0) {
1383 llvm::StringMap FeatureMap;
1384 Context.getFunctionFeatureMap(FeatureMap, FD);
1385 if (!FeatureMap.contains("sme2")) {
1387 diag::err_sme_definition_using_zt0_in_non_sme2_target);
1388 }
1389 }
1390}
1391
1392}
static constexpr Builtin::Info BuiltinInfo[]
enum clang::sema::@1725::IndirectLocalPathEntry::EntryKind Kind
This file declares semantic analysis functions specific to ARM.
Enumerates target-specific builtins in their own namespaces within namespace clang.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
Builtin::Context & BuiltinInfo
CanQualType UnsignedLongTy
CanQualType UnsignedCharTy
CanQualType UnsignedIntTy
CanQualType UnsignedLongLongTy
CanQualType UnsignedShortTy
const TargetInfo & getTargetInfo() const
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
Attr - This represents one attribute.
SourceLocation getLoc() const
This class is used for builtin types like 'int'.
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
const char * getRequiredFeatures(unsigned ID) const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr)
setArg - Set the specified argument.
SourceLocation getBeginLoc() const LLVM_READONLY
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
A reference to a declared variable, function, enum, etc.
SourceLocation getBeginLoc() const LLVM_READONLY
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() const
This represents one expression.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
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 function declaration or definition.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
Represents a prototype with parameter type info, e.g.
unsigned getAArch64SMEAttributes() const
Return a bitmask describing the SME attributes on the function type, see AArch64SMETypeAttributes for...
static ArmStateValue getArmZT0State(unsigned AttrBits)
static ArmStateValue getArmZAState(unsigned AttrBits)
@ SME_PStateSMEnabledMask
@ SME_PStateSMCompatibleMask
@ SME_AgnosticZAStateMask
One of these records is kept for each identifier that is lexed.
unsigned getBuiltinID() const
Return a value indicating whether this is a builtin function.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
Flags to identify the types for overloaded Neon builtins.
unsigned getEltSizeInBits() const
EltType getEltType() const
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
void setInvalid(bool b=true) const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
bool isArgIdent(unsigned Arg) const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
QualType withConst() const
void addConst()
Add the const type qualifier to this QualType.
QualType withVolatile() const
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
const Type * getTypePtrOrNull() const
bool isAtLeastAsQualifiedAs(QualType Other, const ASTContext &Ctx) const
Determine whether this type is at least as qualified as the other given type, requiring exact equalit...
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
void CheckSMEFunctionDefAttributes(const FunctionDecl *FD)
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool PerformNeonImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int, int > > &ImmChecks, int OverloadType=-1)
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
bool PerformSVEImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int > > &ImmChecks)
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)
@ ArmStreaming
Intrinsic is only available in normal mode.
@ VerifyRuntimeMode
Intrinsic is available both in normal and Streaming-SVE mode.
@ ArmStreamingCompatible
Intrinsic is only available in Streaming-SVE mode.
void handleNewAttr(Decl *D, const ParsedAttr &AL)
bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, unsigned MaxWidth)
bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall)
BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions.
void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL)
bool CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, unsigned ArgIdx, unsigned EltBitWidth, unsigned VecBitWidth)
bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum, unsigned ExpectedFieldNum, bool AllowName)
BuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr TheCall is an ARM/AArch64 specia...
bool SmeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
Sema - This implements semantic analysis and AST building for C.
bool BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Multiple)
BuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr TheCall is a constant expr...
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
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.
AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, bool Diagnose=true, bool DiagnoseCFAudited=false, bool ConvertRHS=true)
Check assignment constraints for an assignment of RHS to LHSType.
ExprResult DefaultLvalueConversion(Expr *E)
AssignConvertType
AssignConvertType - All of the 'assignment' semantic checks return this enum to indicate whether the ...
bool BuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result)
BuiltinConstantArg - Handle a check if argument ArgNum of CallExpr TheCall is a constant expression.
bool isConstantEvaluatedContext() const
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, QualType DstType, QualType SrcType, Expr *SrcExpr, AssignmentAction Action, bool *Complained=nullptr)
DiagnoseAssignmentResult - Emit a diagnostic, if required, for the assignment conversion type specifi...
bool BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError=true)
BuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr TheCall is a constant express...
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.
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.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
IntType getInt64Type() const
uint32_t getARMCDECoprocMask() const
For ARM targets returns a mask defining which coprocessors are configured as Custom Datapath.
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
The base class of the type hierarchy.
bool isBlockPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs'.
bool isSizelessVectorType() const
Returns true for all scalable vector types.
Defines the clang::TargetInfo interface.
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
const AstTypeMatcher< PointerType > pointerType
Matches pointer types, but does not match Objective-C object pointer types.
The JSON file list parser is used to communicate input to InstallAPI.
static bool hasArmZAState(const FunctionDecl *FD)
static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)
static ArmSMEState getSMEState(unsigned BuiltinID)
static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
static bool hasArmZT0State(const FunctionDecl *FD)
CastKind
CastKind - The kind of operation required for a conversion.
const FunctionProtoType * T
static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, bool IsPolyUnsigned, bool IsInt64Long)
getNeonEltType - Return the QualType corresponding to the elements of the vector type specified by th...
static bool checkNewAttrMutualExclusion(Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, FunctionType::ArmStateValue CurrentState, StringRef StateName)
Extra information about a function prototype.
unsigned AArch64SMEAttributes