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 && SveAliasValid(BuiltinID, AliasName) &&

1201 (!IsAArch64 && MveAliasValid(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