30 if (BuiltinID == AArch64::BI__builtin_arm_irg) {
31 if (
SemaRef.checkArgCount(TheCall, 2))
41 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
50 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_must_be_integer)
59 if (BuiltinID == AArch64::BI__builtin_arm_addg) {
60 if (
SemaRef.checkArgCount(TheCall, 2))
69 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
77 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
80 if (BuiltinID == AArch64::BI__builtin_arm_gmi) {
81 if (
SemaRef.checkArgCount(TheCall, 2))
91 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
100 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_must_be_integer)
107 if (BuiltinID == AArch64::BI__builtin_arm_ldg ||
108 BuiltinID == AArch64::BI__builtin_arm_stg) {
109 if (
SemaRef.checkArgCount(TheCall, 1))
118 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
123 if (BuiltinID == AArch64::BI__builtin_arm_ldg)
124 TheCall->
setType(FirstArgType);
128 if (BuiltinID == AArch64::BI__builtin_arm_subp) {
141 auto isNull = [&](
Expr *E) ->
bool {
142 return E->isNullPointerConstant(Context,
148 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
152 return Diag(TheCall->
getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
160 if (!Context.typesAreCompatible(
161 Context.getCanonicalType(pointeeA).getUnqualifiedType(),
162 Context.getCanonicalType(pointeeB).getUnqualifiedType())) {
164 diag::err_typecheck_sub_ptr_compatible)
177 SemaRef.ImpCastExprToType(ArgExprA.
get(), ArgTypeB, CK_NullToPointer);
181 SemaRef.ImpCastExprToType(ArgExprB.
get(), ArgTypeA, CK_NullToPointer);
187 assert(
false &&
"Unhandled ARM MTE intrinsic");
194 int ArgNum,
unsigned ExpectedFieldNum,
196 bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
197 BuiltinID == ARM::BI__builtin_arm_wsr64 ||
198 BuiltinID == ARM::BI__builtin_arm_rsr ||
199 BuiltinID == ARM::BI__builtin_arm_rsrp ||
200 BuiltinID == ARM::BI__builtin_arm_wsr ||
201 BuiltinID == ARM::BI__builtin_arm_wsrp;
202 bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
203 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
204 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
205 BuiltinID == AArch64::BI__builtin_arm_wsr128 ||
206 BuiltinID == AArch64::BI__builtin_arm_rsr ||
207 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
208 BuiltinID == AArch64::BI__builtin_arm_wsr ||
209 BuiltinID == AArch64::BI__builtin_arm_wsrp;
210 assert((IsARMBuiltin || IsAArch64Builtin) &&
"Unexpected ARM builtin.");
225 Reg.split(Fields,
":");
227 if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
235 if (Fields.size() > 1) {
236 bool FiveFields = Fields.size() == 5;
238 bool ValidString =
true;
240 ValidString &= Fields[0].starts_with_insensitive(
"cp") ||
241 Fields[0].starts_with_insensitive(
"p");
243 Fields[0] = Fields[0].drop_front(
244 Fields[0].starts_with_insensitive(
"cp") ? 2 : 1);
246 ValidString &= Fields[2].starts_with_insensitive(
"c");
248 Fields[2] = Fields[2].drop_front(1);
251 ValidString &= Fields[3].starts_with_insensitive(
"c");
253 Fields[3] = Fields[3].drop_front(1);
259 FieldBitWidths.append({IsAArch64Builtin ? 2 : 4, 3, 4, 4, 3});
261 FieldBitWidths.append({4, 3, 4});
263 for (
unsigned i = 0; i < Fields.size(); ++i) {
265 ValidString &= !Fields[i].getAsInteger(10, IntField);
266 ValidString &= (IntField >= 0 && IntField < (1 << FieldBitWidths[i]));
272 }
else if (IsAArch64Builtin && Fields.size() == 1) {
280 if (BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
281 BuiltinID == AArch64::BI__builtin_arm_wsr128)
286 auto MaxLimit = llvm::StringSwitch<std::optional<unsigned>>(Reg)
287 .CaseLower(
"spsel", 15)
288 .CaseLower(
"daifclr", 15)
289 .CaseLower(
"daifset", 15)
290 .CaseLower(
"pan", 15)
291 .CaseLower(
"uao", 15)
292 .CaseLower(
"dit", 15)
293 .CaseLower(
"ssbs", 15)
294 .CaseLower(
"tco", 15)
295 .CaseLower(
"allint", 1)
297 .Default(std::nullopt);
317 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);
327 bool IsPolyUnsigned,
bool IsInt64Long) {
330 return Flags.
isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
332 return Flags.
isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
334 return Flags.
isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
337 return Flags.
isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
339 return Flags.
isUnsigned() ? Context.UnsignedLongLongTy
340 : Context.LongLongTy;
342 return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
344 return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
347 return Context.UnsignedLongTy;
349 return Context.UnsignedLongLongTy;
353 return Context.HalfTy;
355 return Context.FloatTy;
357 return Context.DoubleTy;
359 return Context.BFloat16Ty;
361 return Context.MFloat8Ty;
363 llvm_unreachable(
"Invalid NeonTypeFlag!");
381 unsigned ArgIdx,
unsigned EltBitWidth,
382 unsigned ContainerBitWidth) {
385 auto CheckImmediateInSet = [&](std::initializer_list<int64_t>
Set,
386 int ErrDiag) ->
bool {
394 if (
SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm))
397 if (!llvm::is_contained(
Set, Imm.getSExtValue()))
403 case ImmCheckType::ImmCheck0_31:
404 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31))
407 case ImmCheckType::ImmCheck0_13:
408 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13))
411 case ImmCheckType::ImmCheck0_63:
412 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63))
415 case ImmCheckType::ImmCheck1_16:
416 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16))
419 case ImmCheckType::ImmCheck0_7:
420 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7))
423 case ImmCheckType::ImmCheck1_1:
424 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1))
427 case ImmCheckType::ImmCheck1_3:
428 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3))
431 case ImmCheckType::ImmCheck1_7:
432 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7))
435 case ImmCheckType::ImmCheckExtract:
436 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
437 (2048 / EltBitWidth) - 1))
440 case ImmCheckType::ImmCheckCvt:
441 case ImmCheckType::ImmCheckShiftRight:
442 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth))
445 case ImmCheckType::ImmCheckShiftRightNarrow:
446 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2))
449 case ImmCheckType::ImmCheckShiftLeft:
450 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))
453 case ImmCheckType::ImmCheckLaneIndex:
454 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
455 (ContainerBitWidth / EltBitWidth) - 1))
458 case ImmCheckType::ImmCheckLaneIndexCompRotate:
459 if (
SemaRef.BuiltinConstantArgRange(
460 TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1))
463 case ImmCheckType::ImmCheckLaneIndexDot:
464 if (
SemaRef.BuiltinConstantArgRange(
465 TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1))
468 case ImmCheckType::ImmCheckComplexRot90_270:
469 if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))
472 case ImmCheckType::ImmCheckComplexRotAll90:
473 if (CheckImmediateInSet({0, 90, 180, 270},
474 diag::err_rotation_argument_to_cmla))
477 case ImmCheckType::ImmCheck0_1:
478 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1))
481 case ImmCheckType::ImmCheck0_2:
482 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2))
485 case ImmCheckType::ImmCheck0_3:
486 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3))
489 case ImmCheckType::ImmCheck0_0:
490 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0))
493 case ImmCheckType::ImmCheck0_15:
494 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15))
497 case ImmCheckType::ImmCheck0_255:
498 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255))
501 case ImmCheckType::ImmCheck1_32:
502 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32))
505 case ImmCheckType::ImmCheck1_64:
506 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64))
509 case ImmCheckType::ImmCheck2_4_Mul2:
510 if (
SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) ||
511 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2))
522 bool HasError =
false;
524 for (
const auto &I : ImmChecks) {
525 auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I;
527 if (OverloadType >= 0)
539 bool HasError =
false;
541 for (
const auto &I : ImmChecks) {
542 auto [ArgIdx, CheckTy, ElementBitWidth] = I;
551 if (FD->
hasAttr<ArmLocallyStreamingAttr>())
555 if (FPT->getAArch64SMEAttributes() &
558 if (FPT->getAArch64SMEAttributes() &
569 unsigned BuiltinID) {
577 llvm::StringMap<bool> CallerFeatures;
584 const auto FindTopLevelPipe = [](
const char *S) {
586 unsigned I = 0, E = strlen(S);
588 if (S[I] ==
'|' && Depth == 0)
592 else if (S[I] ==
')')
598 const char *RequiredFeatures =
600 unsigned PipeIdx = FindTopLevelPipe(RequiredFeatures);
601 assert(PipeIdx != 0 && PipeIdx != strlen(RequiredFeatures) &&
602 "Expected feature string of the form 'SVE-EXPR|SME-EXPR'");
603 StringRef NonStreamingBuiltinGuard = StringRef(RequiredFeatures, PipeIdx);
604 StringRef StreamingBuiltinGuard = StringRef(RequiredFeatures + PipeIdx + 1);
607 NonStreamingBuiltinGuard, CallerFeatures);
609 StreamingBuiltinGuard, CallerFeatures);
611 if (SatisfiesSVE && SatisfiesSME)
614 else if (SatisfiesSVE)
616 else if (SatisfiesSME)
625 S.
Diag(TheCall->
getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
629 S.
Diag(TheCall->
getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
641#define GET_SME_BUILTIN_GET_STATE
642#include "clang/Basic/arm_sme_builtins_za_state.inc"
643#undef GET_SME_BUILTIN_GET_STATE
650 SemaRef.getCurFunctionDecl(
true)) {
654#define GET_SME_STREAMING_ATTRS
655#include "clang/Basic/arm_sme_streaming_attrs.inc"
656#undef GET_SME_STREAMING_ATTRS
665 diag::warn_attribute_arm_za_builtin_no_za_state)
670 diag::warn_attribute_arm_zt0_builtin_no_zt0_state)
680#define GET_SME_IMMEDIATE_CHECK
681#include "clang/Basic/arm_sme_sema_rangechecks.inc"
682#undef GET_SME_IMMEDIATE_CHECK
691 SemaRef.getCurFunctionDecl(
true)) {
695#define GET_SVE_STREAMING_ATTRS
696#include "clang/Basic/arm_sve_streaming_attrs.inc"
697#undef GET_SVE_STREAMING_ATTRS
709#define GET_SVE_IMMEDIATE_CHECK
710#include "clang/Basic/arm_sve_sema_rangechecks.inc"
711#undef GET_SVE_IMMEDIATE_CHECK
721 SemaRef.getCurFunctionDecl(
true)) {
727#define GET_NEON_STREAMING_COMPAT_FLAG
728#include "clang/Basic/arm_neon.inc"
729#undef GET_NEON_STREAMING_COMPAT_FLAG
740 bool HasConstPtr =
false;
742#define GET_NEON_OVERLOAD_CHECK
743#include "clang/Basic/arm_fp16.inc"
744#include "clang/Basic/arm_neon.inc"
745#undef GET_NEON_OVERLOAD_CHECK
757 TV =
Result.getLimitedValue(64);
758 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
763 if (PtrArgNum >= 0) {
767 Arg = ICE->getSubExpr();
772 bool IsPolyUnsigned =
Arch == llvm::Triple::aarch64 ||
773 Arch == llvm::Triple::aarch64_32 ||
774 Arch == llvm::Triple::aarch64_be;
777 IsPolyUnsigned, IsInt64Long);
782 ConvTy =
SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
797#define GET_NEON_IMMEDIATE_CHECK
798#include "clang/Basic/arm_fp16.inc"
799#include "clang/Basic/arm_neon.inc"
800#undef GET_NEON_IMMEDIATE_CHECK
811#include "clang/Basic/arm_mve_builtin_sema.inc"
822#include "clang/Basic/arm_cde_builtin_sema.inc"
832 const Expr *CoprocArg,
835 if (
SemaRef.isConstantEvaluatedContext())
843 int64_t CoprocNo = CoprocNoAP.getExtValue();
844 assert(CoprocNo >= 0 &&
"Coprocessor immediate must be non-negative");
847 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
849 if (IsCDECoproc != WantCDE)
859 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
860 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
861 BuiltinID == ARM::BI__builtin_arm_ldaex ||
862 BuiltinID == ARM::BI__builtin_arm_strex ||
863 BuiltinID == ARM::BI__builtin_arm_strexd ||
864 BuiltinID == ARM::BI__builtin_arm_stlex ||
865 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
866 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
867 BuiltinID == AArch64::BI__builtin_arm_strex ||
868 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
869 "unexpected ARM builtin");
870 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
871 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
872 BuiltinID == ARM::BI__builtin_arm_ldaex ||
873 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
874 BuiltinID == AArch64::BI__builtin_arm_ldaex;
875 bool IsDoubleWord = BuiltinID == ARM::BI__builtin_arm_ldrexd ||
876 BuiltinID == ARM::BI__builtin_arm_strexd;
883 if (
SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
890 Expr *PointerArg = TheCall->
getArg(IsLdrex ? 0 : 1);
892 SemaRef.DefaultFunctionArrayLvalueConversion(PointerArg);
895 PointerArg = PointerArgRes.
get();
915 CastNeeded = CK_BitCast;
916 Diag(DRE->
getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
917 << PointerArg->
getType() << Context.getPointerType(AddrType)
922 AddrType = Context.getPointerType(AddrType);
923 PointerArgRes =
SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
926 PointerArg = PointerArgRes.
get();
928 TheCall->
setArg(IsLdrex ? 0 : 1, PointerArg);
933 Diag(DRE->
getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
942 unsigned Bits = Context.getTypeSize(ValType);
949 (llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8));
959 diag::err_atomic_exclusive_builtin_pointer_size)
961 bool Started =
false;
962 for (
unsigned Size = 1; Size <= 8; Size <<= 1) {
969 if (!(Mask & Size)) {
988 bool EmitDoubleWordDiagnostic =
991 diag::err_atomic_exclusive_builtin_pointer_size_none)
992 << (EmitDoubleWordDiagnostic ? 1 : 0)
1020 Context, ValType,
false);
1028 TheCall->
setType(Context.IntTy);
1035 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
1036 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1037 BuiltinID == ARM::BI__builtin_arm_ldaex ||
1038 BuiltinID == ARM::BI__builtin_arm_strex ||
1039 BuiltinID == ARM::BI__builtin_arm_strexd ||
1040 BuiltinID == ARM::BI__builtin_arm_stlex) {
1044 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
1045 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1046 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
1049 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
1050 BuiltinID == ARM::BI__builtin_arm_wsr64)
1053 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
1054 BuiltinID == ARM::BI__builtin_arm_rsrp ||
1055 BuiltinID == ARM::BI__builtin_arm_wsr ||
1056 BuiltinID == ARM::BI__builtin_arm_wsrp)
1069 switch (BuiltinID) {
1072 case ARM::BI__builtin_arm_ssat:
1073 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
1074 case ARM::BI__builtin_arm_usat:
1075 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1076 case ARM::BI__builtin_arm_ssat16:
1077 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
1078 case ARM::BI__builtin_arm_usat16:
1079 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
1080 case ARM::BI__builtin_arm_vcvtr_f:
1081 case ARM::BI__builtin_arm_vcvtr_d:
1082 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
1083 case ARM::BI__builtin_arm_dmb:
1085 case ARM::BI__builtin_arm_dsb:
1087 case ARM::BI__builtin_arm_isb:
1089 case ARM::BI__builtin_arm_dbg:
1090 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
1091 case ARM::BI__builtin_arm_cdp:
1092 case ARM::BI__builtin_arm_cdp2:
1093 case ARM::BI__builtin_arm_mcr:
1094 case ARM::BI__builtin_arm_mcr2:
1095 case ARM::BI__builtin_arm_mrc:
1096 case ARM::BI__builtin_arm_mrc2:
1097 case ARM::BI__builtin_arm_mcrr:
1098 case ARM::BI__builtin_arm_mcrr2:
1099 case ARM::BI__builtin_arm_mrrc:
1100 case ARM::BI__builtin_arm_mrrc2:
1101 case ARM::BI__builtin_arm_ldc:
1102 case ARM::BI__builtin_arm_ldcl:
1103 case ARM::BI__builtin_arm_ldc2:
1104 case ARM::BI__builtin_arm_ldc2l:
1105 case ARM::BI__builtin_arm_stc:
1106 case ARM::BI__builtin_arm_stcl:
1107 case ARM::BI__builtin_arm_stc2:
1108 case ARM::BI__builtin_arm_stc2l:
1109 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
1118 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1119 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1120 BuiltinID == AArch64::BI__builtin_arm_strex ||
1121 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1125 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1126 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1127 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
1128 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
1129 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
1132 if (BuiltinID == AArch64::BI__builtin_arm_range_prefetch_x) {
1133 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1134 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1) ||
1135 SemaRef.BuiltinConstantArgRange(TheCall, 3, -2097152, 2097151) ||
1136 SemaRef.BuiltinConstantArgRange(TheCall, 4, 1, 65536) ||
1137 SemaRef.BuiltinConstantArgRange(TheCall, 5, -2097152, 2097151);
1140 if (BuiltinID == AArch64::BI__builtin_arm_range_prefetch) {
1141 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1142 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
1145 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1146 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1147 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1148 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1152 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1153 BuiltinID == AArch64::BI__builtin_arm_addg ||
1154 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1155 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1156 BuiltinID == AArch64::BI__builtin_arm_stg ||
1157 BuiltinID == AArch64::BI__builtin_arm_subp) {
1161 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1162 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1163 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1164 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1170 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1171 BuiltinID == AArch64::BI_WriteStatusReg)
1172 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0x4000, 0x7fff);
1174 if (BuiltinID == AArch64::BI__sys)
1175 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x3fff);
1177 if (BuiltinID == AArch64::BI__getReg)
1178 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
1180 if (BuiltinID == AArch64::BI__break)
1181 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1183 if (BuiltinID == AArch64::BI__hlt)
1184 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1197 unsigned i = 0, l = 0, u = 0;
1198 switch (BuiltinID) {
1199 default:
return false;
1200 case AArch64::BI__builtin_arm_dmb:
1201 case AArch64::BI__dmb:
1202 case AArch64::BI__builtin_arm_dsb:
1203 case AArch64::BI__dsb:
1204 case AArch64::BI__builtin_arm_isb:
1205 case AArch64::BI__isb:
1211 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
1215struct IntrinToName {
1224 const char *IntrinNames) {
1225 AliasName.consume_front(
"__arm_");
1226 const IntrinToName *It =
1227 llvm::lower_bound(Map, BuiltinID, [](
const IntrinToName &L,
unsigned Id) {
1230 if (It == Map.end() || It->Id != BuiltinID)
1232 StringRef FullName(&IntrinNames[It->FullName]);
1233 if (AliasName == FullName)
1235 if (It->ShortName == -1)
1237 StringRef ShortName(&IntrinNames[It->ShortName]);
1238 return AliasName == ShortName;
1242#include "clang/Basic/arm_mve_builtin_aliases.inc"
1250#include "clang/Basic/arm_cde_builtin_aliases.inc"
1271 Diag(AL.
getLoc(), diag::err_attribute_argument_n_type)
1280 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1285 Diag(AL.
getLoc(), diag::err_attribute_arm_builtin_alias);
1289 D->
addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1295 auto CheckForIncompatibleAttr =
1297 StringRef IncompatibleStateName) {
1298 if (CurrentState == IncompatibleState) {
1299 S.
Diag(AL.
getLoc(), diag::err_attributes_are_not_compatible)
1300 << (std::string(
"'__arm_new(\"") + StateName.str() +
"\")'")
1301 << (std::string(
"'") + IncompatibleStateName.str() +
"(\"" +
1302 StateName.str() +
"\")'")
1317 Diag(AL.
getLoc(), diag::err_missing_arm_state) << AL;
1322 std::vector<StringRef> NewState;
1323 if (
const auto *ExistingAttr = D->
getAttr<ArmNewAttr>()) {
1324 for (StringRef S : ExistingAttr->newArgs())
1325 NewState.push_back(S);
1329 bool HasZT0 =
false;
1330 for (
unsigned I = 0, E = AL.
getNumArgs(); I != E; ++I) {
1331 StringRef StateName;
1333 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
1336 if (StateName ==
"za")
1338 else if (StateName ==
"zt0")
1341 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1346 if (!llvm::is_contained(NewState, StateName))
1347 NewState.push_back(StateName);
1370 Diag(AL.
getLoc(), diag::err_attribute_not_clinkage) << AL;
1375 if (!FD->isExternallyVisible()) {
1376 Diag(AL.
getLoc(), diag::warn_attribute_cmse_entry_static);
1386 Diag(AL.
getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1395 else if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1398 ARMInterruptAttr::InterruptType Kind;
1399 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1400 Diag(AL.
getLoc(), diag::warn_attribute_type_not_supported)
1401 << AL << Str << ArgLoc;
1405 if (!D->
hasAttr<ARMSaveFPAttr>()) {
1420 SemaRef.ARM().handleInterruptAttr(D, AL);
1423 if (!D->
hasAttr<ARMInterruptAttr>()) {
1429 bool VFP =
SemaRef.Context.getTargetInfo().hasFeature(
"vfp");
1442 bool UsesSM = FD->
hasAttr<ArmLocallyStreamingAttr>();
1443 bool UsesZA =
Attr &&
Attr->isNewZA();
1444 bool UsesZT0 =
Attr &&
Attr->isNewZT0();
1446 if (UsesZA || UsesZT0) {
1454 if (FD->
hasAttr<ArmLocallyStreamingAttr>()) {
1457 diag::warn_sme_locally_streaming_has_vl_args_returns)
1460 return P->getOriginalType()->isSizelessVectorType();
1463 diag::warn_sme_locally_streaming_has_vl_args_returns)
1476 if (UsesSM || UsesZA) {
1477 llvm::StringMap<bool> FeatureMap;
1478 Context.getFunctionFeatureMap(FeatureMap, FD);
1479 if (!FeatureMap.contains(
"sme")) {
1482 diag::err_sme_definition_using_sm_in_non_sme_target);
1485 diag::err_sme_definition_using_za_in_non_sme_target);
1489 llvm::StringMap<bool> FeatureMap;
1490 Context.getFunctionFeatureMap(FeatureMap, FD);
1491 if (!FeatureMap.contains(
"sme2")) {
1493 diag::err_sme_definition_using_zt0_in_non_sme2_target);
1502 uint64_t VScale = IsStreaming ? Context.getLangOpts().VScaleStreamingMin
1503 : Context.getLangOpts().VScaleMin;
1504 if (Ty->
getKind() == BuiltinType::SveBool ||
1505 Ty->
getKind() == BuiltinType::SveCount)
1506 return (VScale * 128) / Context.getCharWidth();
1507 return VScale * 128;
1511 bool IsStreaming =
false;
1515 SemaRef.getCurFunctionDecl(
true)) {
1518 if (T->getAArch64SMEAttributes() &
1535 return BT->getKind() == BuiltinType::SveBool;
1537 return VT->getElementType().getCanonicalType() ==
1539 BT->getKind() != BuiltinType::SveBool;
1541 return Context.getTypeSize(SecondType) ==
1543 Context.hasSameType(
1544 VT->getElementType(),
1545 Context.getBuiltinVectorTypeInfo(BT).ElementType);
1551 return IsValidCast(FirstType, SecondType) ||
1552 IsValidCast(SecondType, FirstType);
1557 bool IsStreaming =
false;
1561 SemaRef.getCurFunctionDecl(
true)) {
1564 if (T->getAArch64SMEAttributes() &
1587 if (BT->getKind() == BuiltinType::SveBool &&
1597 Context.getTypeSize(SecondType) !=
1609 return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
1616 return IsLaxCompatible(FirstType, SecondType) ||
1617 IsLaxCompatible(SecondType, FirstType);
1621 if (!Buffer.empty())
1623 Buffer.append(Feat);
1628 StringRef PriorityString[8] = {
"P0",
"P1",
"P2",
"P3",
1629 "P4",
"P5",
"P6",
"P7"};
1631 assert(Priority > 0 && Priority < 256 &&
"priority out of range");
1633 for (
unsigned BitPos = 0; BitPos < 8; ++BitPos)
1634 if (Priority & (1U << BitPos))
1643 auto [LHS, RHS] = Param.split(
';');
1645 bool IsDefault =
false;
1647 LHS.split(Features,
'+');
1648 for (StringRef Feat : Features) {
1650 if (Feat ==
"default")
1652 else if (!
getASTContext().getTargetInfo().validateCpuSupports(Feat))
1653 return Diag(Loc, diag::warn_unsupported_target_attribute)
1658 if (!RHS.empty() && RHS.consume_front(
"priority=")) {
1660 Diag(Loc, diag::warn_invalid_default_version_priority);
1663 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1664 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1680 assert(Params.size() == Locs.size() &&
1681 "Mismatch between number of string parameters and locations");
1683 bool HasDefault =
false;
1684 bool HasNonDefault =
false;
1685 for (
unsigned I = 0, E = Params.size(); I < E; ++I) {
1686 const StringRef Param = Params[I].trim();
1689 auto [LHS, RHS] = Param.split(
';');
1691 bool HasPriority = !RHS.empty() && RHS.consume_front(
"priority=");
1694 return Diag(Loc, diag::warn_unsupported_target_attribute)
1697 if (LHS ==
"default") {
1699 Diag(Loc, diag::warn_target_clone_duplicate_options);
1702 Diag(Loc, diag::warn_invalid_default_version_priority);
1703 NewParams.push_back(LHS);
1709 bool HasCodeGenImpact =
false;
1712 LHS.split(Features,
'+');
1713 for (StringRef Feat : Features) {
1715 if (!
getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
1716 Diag(Loc, diag::warn_unsupported_target_attribute)
1720 if (
getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))
1721 HasCodeGenImpact =
true;
1722 ValidFeatures.push_back(Feat);
1726 if (!HasCodeGenImpact) {
1727 Diag(Loc, diag::warn_target_clone_no_impact_options);
1731 if (ValidFeatures.empty())
1735 llvm::sort(ValidFeatures);
1737 if (llvm::is_contained(NewParams, NewParam)) {
1738 Diag(Loc, diag::warn_target_clone_duplicate_options);
1744 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1745 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1751 NewParams.push_back(NewParam);
1752 HasNonDefault =
true;
1755 return !HasNonDefault;
1760 const llvm::StringMap<bool> &FeatureMap) {
1764 if (FeatureMap.lookup(
"sve"))
1768 if (!FeatureMap.lookup(
"sme"))
1769 return Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
1774 return Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target)
Determine whether a translation unit built using the current language options has the given feature.
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
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.
SourceLocation getBeginLoc() const
void setArg(unsigned Arg, Expr *ArgExpr)
setArg - Set the specified argument.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
A reference to a declared variable, function, enum, etc.
SourceLocation getBeginLoc() const
Decl - This represents one declaration (or definition), e.g.
const FunctionType * getFunctionType(bool BlocksToo=true) const
Looks through the Decl's underlying type to extract a FunctionType when possible.
SourceLocation getLocation() const
DeclContext * getDeclContext()
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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Represents a function declaration or definition.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
Represents a prototype with parameter type info, e.g.
@ SME_PStateSMEnabledMask
@ SME_PStateSMCompatibleMask
@ SME_AgnosticZAStateMask
static ArmStateValue getArmZT0State(unsigned AttrBits)
static ArmStateValue getArmZAState(unsigned AttrBits)
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.
IdentifierInfo * getIdentifierInfo() const
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.
@ Integer
Permit vector bitcasts between integer vectors with different numbers of elements but the same total ...
@ All
Permit vector bitcasts between all vectors with the same total bit-width.
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.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
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)
void handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL)
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(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
bool areCompatibleSveTypes(QualType FirstType, QualType SecondType)
Return true if the given types are an SVE builtin and a VectorType that is a fixed-length representat...
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc, SmallString< 64 > &NewParam)
bool checkSVETypeSupport(QualType Ty, SourceLocation Loc, const FunctionDecl *FD, const llvm::StringMap< bool > &FeatureMap)
bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType)
Return true if the given vector types are lax-compatible SVE vector types, false otherwise.
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 checkTargetClonesAttr(SmallVectorImpl< StringRef > &Params, SmallVectorImpl< SourceLocation > &Locs, SmallVectorImpl< SmallString< 64 > > &NewParams)
bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
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
@ ARM_LDREX_D
word (32-bit)
virtual unsigned getARMLDREXMask() 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).
bool isSVESizelessBuiltinType() const
Returns true for SVE scalable vector types.
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
QualType getSveEltType(const ASTContext &Ctx) const
Returns the representative type for the element of an SVE builtin type.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isSizelessVectorType() const
Returns true for all scalable vector types.
Represents a GCC generic vector type.
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.
Enums for the diagnostics of target, target_version and target_clones.
const AstTypeMatcher< PointerType > pointerType
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
static void convertPriorityString(unsigned Priority, SmallString< 64 > &NewParam)
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)
static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty, bool IsStreaming)
getSVETypeSize - Return SVE vector or predicate register size.
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
AssignConvertType
AssignConvertType - All of the 'assignment' semantic checks return this enum to indicate whether the ...
bool hasArmZT0State(const FunctionDecl *FD)
Returns whether the given FunctionDecl has Arm ZT0 state.
CastKind
CastKind - The kind of operation required for a conversion.
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)
static void appendFeature(StringRef Feat, SmallString< 64 > &Buffer)
@ SveFixedLengthData
is AArch64 SVE fixed-length data vector
@ Generic
not a target-specific vector type
@ SveFixedLengthPredicate
is AArch64 SVE fixed-length predicate vector
U cast(CodeGen::Address addr)
@ None
The alignment was not explicit in code.
bool IsArmStreamingFunction(const FunctionDecl *FD, bool IncludeLocallyStreaming)
Returns whether the given FunctionDecl has an __arm[_locally]_streaming attribute.
ActionResult< Expr * > ExprResult
bool hasArmZAState(const FunctionDecl *FD)
Returns whether the given FunctionDecl has Arm ZA state.
Extra information about a function prototype.
unsigned AArch64SMEAttributes