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) {

31 if (SemaRef.checkArgCount(TheCall, 2))

32 return true;

35

36 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);

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) {

59 if (SemaRef.checkArgCount(TheCall, 2))

60 return true;

61

63 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);

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

76 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);

77 }

78

79 if (BuiltinID == AArch64::BI__builtin_arm_gmi) {

80 if (SemaRef.checkArgCount(TheCall, 2))

81 return true;

84

85 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);

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) {

103 if (SemaRef.checkArgCount(TheCall, 1))

104 return true;

106 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);

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

126 ExprResult ArgExprA = SemaRef.DefaultFunctionArrayLvalueConversion(ArgA);

127 ExprResult ArgExprB = SemaRef.DefaultFunctionArrayLvalueConversion(ArgB);

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 =

171 SemaRef.ImpCastExprToType(ArgExprA.get(), ArgTypeB, CK_NullToPointer);

172

173 if (isNull(ArgB))

174 ArgExprB =

175 SemaRef.ImpCastExprToType(ArgExprB.get(), ArgTypeA, CK_NullToPointer);

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

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 FieldBitWidths.append({IsAArch64Builtin ? 2 : 4, 3, 4, 4, 3});

255 else

256 FieldBitWidths.append({4, 3, 4});

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 < (1 << FieldBitWidths[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

312 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);

313 }

314

315 return false;

316}

317

318

319

320

322 bool IsPolyUnsigned, bool IsInt64Long) {

325 return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;

327 return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;

329 return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;

331 if (IsInt64Long)

332 return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;

333 else

334 return Flags.isUnsigned() ? Context.UnsignedLongLongTy

335 : Context.LongLongTy;

337 return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;

339 return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;

341 if (IsInt64Long)

342 return Context.UnsignedLongTy;

343 else

344 return Context.UnsignedLongLongTy;

346 break;

348 return Context.HalfTy;

350 return Context.FloatTy;

352 return Context.DoubleTy;

354 return Context.BFloat16Ty;

356 return Context.MFloat8Ty;

357 }

358 llvm_unreachable("Invalid NeonTypeFlag!");

359}

360

374

376 unsigned ArgIdx, unsigned EltBitWidth,

377 unsigned ContainerBitWidth) {

378

379

380 auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set,

381 int ErrDiag) -> bool {

382

385 return false;

386

387

388 llvm::APSInt Imm;

389 if (SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm))

390 return true;

391

392 if (!llvm::is_contained(Set, Imm.getSExtValue()))

394 return false;

395 };

396

398 case ImmCheckType::ImmCheck0_31:

399 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31))

400 return true;

401 break;

402 case ImmCheckType::ImmCheck0_13:

403 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13))

404 return true;

405 break;

406 case ImmCheckType::ImmCheck0_63:

407 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63))

408 return true;

409 break;

410 case ImmCheckType::ImmCheck1_16:

411 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16))

412 return true;

413 break;

414 case ImmCheckType::ImmCheck0_7:

415 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7))

416 return true;

417 break;

418 case ImmCheckType::ImmCheck1_1:

419 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1))

420 return true;

421 break;

422 case ImmCheckType::ImmCheck1_3:

423 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3))

424 return true;

425 break;

426 case ImmCheckType::ImmCheck1_7:

427 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7))

428 return true;

429 break;

430 case ImmCheckType::ImmCheckExtract:

431 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,

432 (2048 / EltBitWidth) - 1))

433 return true;

434 break;

435 case ImmCheckType::ImmCheckCvt:

436 case ImmCheckType::ImmCheckShiftRight:

437 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth))

438 return true;

439 break;

440 case ImmCheckType::ImmCheckShiftRightNarrow:

441 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2))

442 return true;

443 break;

444 case ImmCheckType::ImmCheckShiftLeft:

445 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))

446 return true;

447 break;

448 case ImmCheckType::ImmCheckLaneIndex:

449 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,

450 (ContainerBitWidth / EltBitWidth) - 1))

451 return true;

452 break;

453 case ImmCheckType::ImmCheckLaneIndexCompRotate:

454 if (SemaRef.BuiltinConstantArgRange(

455 TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1))

456 return true;

457 break;

458 case ImmCheckType::ImmCheckLaneIndexDot:

459 if (SemaRef.BuiltinConstantArgRange(

460 TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1))

461 return true;

462 break;

463 case ImmCheckType::ImmCheckComplexRot90_270:

464 if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))

465 return true;

466 break;

467 case ImmCheckType::ImmCheckComplexRotAll90:

468 if (CheckImmediateInSet({0, 90, 180, 270},

469 diag::err_rotation_argument_to_cmla))

470 return true;

471 break;

472 case ImmCheckType::ImmCheck0_1:

473 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1))

474 return true;

475 break;

476 case ImmCheckType::ImmCheck0_2:

477 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2))

478 return true;

479 break;

480 case ImmCheckType::ImmCheck0_3:

481 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3))

482 return true;

483 break;

484 case ImmCheckType::ImmCheck0_0:

485 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0))

486 return true;

487 break;

488 case ImmCheckType::ImmCheck0_15:

489 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15))

490 return true;

491 break;

492 case ImmCheckType::ImmCheck0_255:

493 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255))

494 return true;

495 break;

496 case ImmCheckType::ImmCheck1_32:

497 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32))

498 return true;

499 break;

500 case ImmCheckType::ImmCheck1_64:

501 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64))

502 return true;

503 break;

504 case ImmCheckType::ImmCheck2_4_Mul2:

505 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) ||

506 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2))

507 return true;

508 break;

509 }

510 return false;

511}

512

515 SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks,

516 int OverloadType) {

517 bool HasError = false;

518

519 for (const auto &I : ImmChecks) {

520 auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I;

521

522 if (OverloadType >= 0)

524

525 HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth,

526 VecBitWidth);

527 }

528

529 return HasError;

530}

531

534 bool HasError = false;

535

536 for (const auto &I : ImmChecks) {

537 auto [ArgIdx, CheckTy, ElementBitWidth] = I;

538 HasError |=

539 CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128);

540 }

541

542 return HasError;

543}

544

546 if (FD->hasAttr())

550 if (FPT->getAArch64SMEAttributes() &

553 if (FPT->getAArch64SMEAttributes() &

556 }

557 }

559}

560

564 unsigned BuiltinID) {

566

567

568

569

570

572 llvm::StringMap CallerFeatures;

574

575

577 return false;

578

579 const auto FindTopLevelPipe = [](const char *S) {

580 unsigned Depth = 0;

581 unsigned I = 0, E = strlen(S);

582 for (; I < E; ++I) {

583 if (S[I] == '|' && Depth == 0)

584 break;

585 if (S[I] == '(')

586 ++Depth;

587 else if (S[I] == ')')

588 --Depth;

589 }

590 return I;

591 };

592

593 const char *RequiredFeatures =

595 unsigned PipeIdx = FindTopLevelPipe(RequiredFeatures);

596 assert(PipeIdx != 0 && PipeIdx != strlen(RequiredFeatures) &&

597 "Expected feature string of the form 'SVE-EXPR|SME-EXPR'");

598 StringRef NonStreamingBuiltinGuard = StringRef(RequiredFeatures, PipeIdx);

599 StringRef StreamingBuiltinGuard = StringRef(RequiredFeatures + PipeIdx + 1);

600

602 NonStreamingBuiltinGuard, CallerFeatures);

604 StreamingBuiltinGuard, CallerFeatures);

605

606 if (SatisfiesSVE && SatisfiesSME)

607

608 return false;

609 else if (SatisfiesSVE)

611 else if (SatisfiesSME)

613 else

614

615 return false;

616 }

617

620 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)

624 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)

626 else

627 return false;

628

629 return true;

630}

631

633 switch (BuiltinID) {

634 default:

636#define GET_SME_BUILTIN_GET_STATE

637#include "clang/Basic/arm_sme_builtins_za_state.inc"

638#undef GET_SME_BUILTIN_GET_STATE

639 }

640}

641

645 SemaRef.getCurFunctionDecl(true)) {

646 std::optional BuiltinType;

647

648 switch (BuiltinID) {

649#define GET_SME_STREAMING_ATTRS

650#include "clang/Basic/arm_sme_streaming_attrs.inc"

651#undef GET_SME_STREAMING_ATTRS

652 }

653

656 return true;

657

660 diag::warn_attribute_arm_za_builtin_no_za_state)

662

665 diag::warn_attribute_arm_zt0_builtin_no_zt0_state)

667 }

668

669

671

672 switch (BuiltinID) {

673 default:

674 return false;

675#define GET_SME_IMMEDIATE_CHECK

676#include "clang/Basic/arm_sme_sema_rangechecks.inc"

677#undef GET_SME_IMMEDIATE_CHECK

678 }

679

681}

682

686 SemaRef.getCurFunctionDecl(true)) {

687 std::optional BuiltinType;

688

689 switch (BuiltinID) {

690#define GET_SVE_STREAMING_ATTRS

691#include "clang/Basic/arm_sve_streaming_attrs.inc"

692#undef GET_SVE_STREAMING_ATTRS

693 }

696 return true;

697 }

698

700

701 switch (BuiltinID) {

702 default:

703 return false;

704#define GET_SVE_IMMEDIATE_CHECK

705#include "clang/Basic/arm_sve_sema_rangechecks.inc"

706#undef GET_SVE_IMMEDIATE_CHECK

707 }

708

710}

711

713 unsigned BuiltinID,

716 SemaRef.getCurFunctionDecl(true)) {

717 std::optional BuiltinType;

718

719 switch (BuiltinID) {

720 default:

721 break;

722#define GET_NEON_STREAMING_COMPAT_FLAG

723#include "clang/Basic/arm_neon.inc"

724#undef GET_NEON_STREAMING_COMPAT_FLAG

725 }

728 return true;

729 }

730

732 uint64_t mask = 0;

733 int TV = -1;

734 int PtrArgNum = -1;

735 bool HasConstPtr = false;

736 switch (BuiltinID) {

737#define GET_NEON_OVERLOAD_CHECK

738#include "clang/Basic/arm_fp16.inc"

739#include "clang/Basic/arm_neon.inc"

740#undef GET_NEON_OVERLOAD_CHECK

741 }

742

743

744

745 unsigned ImmArg = TheCall->getNumArgs() - 1;

746 if (mask) {

747 if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))

748 return true;

749

750 TV = Result.getLimitedValue(64);

751 if ((TV > 63) || (mask & (1ULL << TV)) == 0)

752 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)

754 }

755

756 if (PtrArgNum >= 0) {

757

758 Expr *Arg = TheCall->getArg(PtrArgNum);

760 Arg = ICE->getSubExpr();

761 ExprResult RHS = SemaRef.DefaultFunctionArrayLvalueConversion(Arg);

763

764 llvm::Triple::ArchType Arch = TI.getTriple().getArch();

765 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||

766 Arch == llvm::Triple::aarch64_32 ||

767 Arch == llvm::Triple::aarch64_be;

770 IsPolyUnsigned, IsInt64Long);

771 if (HasConstPtr)

775 ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);

777 return true;

778 if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,

779 RHSTy, RHS.get(),

781 return true;

782 }

783

784

785

787 switch (BuiltinID) {

788 default:

789 return false;

790#define GET_NEON_IMMEDIATE_CHECK

791#include "clang/Basic/arm_fp16.inc"

792#include "clang/Basic/arm_neon.inc"

793#undef GET_NEON_IMMEDIATE_CHECK

794 }

795

797}

798

801 switch (BuiltinID) {

802 default:

803 return false;

804#include "clang/Basic/arm_mve_builtin_sema.inc"

805 }

806}

807

809 unsigned BuiltinID,

811 bool Err = false;

812 switch (BuiltinID) {

813 default:

814 return false;

815#include "clang/Basic/arm_cde_builtin_sema.inc"

816 }

817

818 if (Err)

819 return true;

820

822}

823

825 const Expr *CoprocArg,

826 bool WantCDE) {

828 if (SemaRef.isConstantEvaluatedContext())

829 return false;

830

831

833 return false;

834

836 int64_t CoprocNo = CoprocNoAP.getExtValue();

837 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");

838

840 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));

841

842 if (IsCDECoproc != WantCDE)

843 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)

845

846 return false;

847}

848

850 unsigned BuiltinID,

852 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||

853 BuiltinID == ARM::BI__builtin_arm_ldrexd ||

854 BuiltinID == ARM::BI__builtin_arm_ldaex ||

855 BuiltinID == ARM::BI__builtin_arm_strex ||

856 BuiltinID == ARM::BI__builtin_arm_strexd ||

857 BuiltinID == ARM::BI__builtin_arm_stlex ||

858 BuiltinID == AArch64::BI__builtin_arm_ldrex ||

859 BuiltinID == AArch64::BI__builtin_arm_ldaex ||

860 BuiltinID == AArch64::BI__builtin_arm_strex ||

861 BuiltinID == AArch64::BI__builtin_arm_stlex) &&

862 "unexpected ARM builtin");

863 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||

864 BuiltinID == ARM::BI__builtin_arm_ldrexd ||

865 BuiltinID == ARM::BI__builtin_arm_ldaex ||

866 BuiltinID == AArch64::BI__builtin_arm_ldrex ||

867 BuiltinID == AArch64::BI__builtin_arm_ldaex;

868 bool IsDoubleWord = BuiltinID == ARM::BI__builtin_arm_ldrexd ||

869 BuiltinID == ARM::BI__builtin_arm_strexd;

870

874

875

876 if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))

877 return true;

878

879

880

881

882

883 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);

885 SemaRef.DefaultFunctionArrayLvalueConversion(PointerArg);

887 return true;

888 PointerArg = PointerArgRes.get();

889

892 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)

894 return true;

895 }

896

897

898

899

902 if (IsLdrex)

904

905

906 CastKind CastNeeded = CK_NoOp;

908 CastNeeded = CK_BitCast;

909 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)

910 << PointerArg->getType() << Context.getPointerType(AddrType)

912 }

913

914

915 AddrType = Context.getPointerType(AddrType);

916 PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);

918 return true;

919 PointerArg = PointerArgRes.get();

920

921 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);

922

923

926 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)

928 return true;

929 }

930

931

932

933 if (!TI.getTriple().isAArch64()) {

935 unsigned Bits = Context.getTypeSize(ValType);

936 if (IsDoubleWord) {

937

938

940 }

941 bool Supported =

942 (llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8));

943

944 if (!Supported) {

945

946

947

948

949

950 if (Mask) {

952 diag::err_atomic_exclusive_builtin_pointer_size)

953 << PointerArg->getType();

954 bool Started = false;

955 for (unsigned Size = 1; Size <= 8; Size <<= 1) {

956

957

958

959

960

961

962 if (!(Mask & Size)) {

963

964

965 D << 0 << 0;

966 } else {

967

968

969 Mask &= ~Size;

970 if (!Started)

971 D << 0;

972 else if (Mask)

973 D << 1;

974 else

975 D << 2;

976 D << 1;

977 Started = true;

978 }

979 }

980 } else {

981 bool EmitDoubleWordDiagnostic =

984 diag::err_atomic_exclusive_builtin_pointer_size_none)

985 << (EmitDoubleWordDiagnostic ? 1 : 0)

987 }

988 }

989 }

990

994

995 break;

996

1000 Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)

1002 return true;

1003 }

1004

1005 if (IsLdrex) {

1006 TheCall->setType(ValType);

1007 return false;

1008 }

1009

1010

1013 Context, ValType, false);

1016 return true;

1017 TheCall->setArg(0, ValArg.get());

1018

1019

1020

1021 TheCall->setType(Context.IntTy);

1022 return false;

1023}

1024

1026 unsigned BuiltinID,

1028 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||

1029 BuiltinID == ARM::BI__builtin_arm_ldrexd ||

1030 BuiltinID == ARM::BI__builtin_arm_ldaex ||

1031 BuiltinID == ARM::BI__builtin_arm_strex ||

1032 BuiltinID == ARM::BI__builtin_arm_strexd ||

1033 BuiltinID == ARM::BI__builtin_arm_stlex) {

1035 }

1036

1037 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {

1038 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||

1039 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);

1040 }

1041

1042 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||

1043 BuiltinID == ARM::BI__builtin_arm_wsr64)

1045

1046 if (BuiltinID == ARM::BI__builtin_arm_rsr ||

1047 BuiltinID == ARM::BI__builtin_arm_rsrp ||

1048 BuiltinID == ARM::BI__builtin_arm_wsr ||

1049 BuiltinID == ARM::BI__builtin_arm_wsrp)

1051

1053 return true;

1055 return true;

1057 return true;

1058

1059

1060

1061

1062 switch (BuiltinID) {

1063 default:

1064 return false;

1065 case ARM::BI__builtin_arm_ssat:

1066 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);

1067 case ARM::BI__builtin_arm_usat:

1068 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);

1069 case ARM::BI__builtin_arm_ssat16:

1070 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);

1071 case ARM::BI__builtin_arm_usat16:

1072 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);

1073 case ARM::BI__builtin_arm_vcvtr_f:

1074 case ARM::BI__builtin_arm_vcvtr_d:

1075 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);

1076 case ARM::BI__builtin_arm_dmb:

1077 case ARM::BI__dmb:

1078 case ARM::BI__builtin_arm_dsb:

1079 case ARM::BI__dsb:

1080 case ARM::BI__builtin_arm_isb:

1081 case ARM::BI__isb:

1082 case ARM::BI__builtin_arm_dbg:

1083 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);

1084 case ARM::BI__builtin_arm_cdp:

1085 case ARM::BI__builtin_arm_cdp2:

1086 case ARM::BI__builtin_arm_mcr:

1087 case ARM::BI__builtin_arm_mcr2:

1088 case ARM::BI__builtin_arm_mrc:

1089 case ARM::BI__builtin_arm_mrc2:

1090 case ARM::BI__builtin_arm_mcrr:

1091 case ARM::BI__builtin_arm_mcrr2:

1092 case ARM::BI__builtin_arm_mrrc:

1093 case ARM::BI__builtin_arm_mrrc2:

1094 case ARM::BI__builtin_arm_ldc:

1095 case ARM::BI__builtin_arm_ldcl:

1096 case ARM::BI__builtin_arm_ldc2:

1097 case ARM::BI__builtin_arm_ldc2l:

1098 case ARM::BI__builtin_arm_stc:

1099 case ARM::BI__builtin_arm_stcl:

1100 case ARM::BI__builtin_arm_stc2:

1101 case ARM::BI__builtin_arm_stc2l:

1102 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||

1104 false);

1105 }

1106}

1107

1109 unsigned BuiltinID,

1111 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||

1112 BuiltinID == AArch64::BI__builtin_arm_ldaex ||

1113 BuiltinID == AArch64::BI__builtin_arm_strex ||

1114 BuiltinID == AArch64::BI__builtin_arm_stlex) {

1116 }

1117

1118 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {

1119 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||

1120 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||

1121 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||

1122 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);

1123 }

1124

1125 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||

1126 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||

1127 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||

1128 BuiltinID == AArch64::BI__builtin_arm_wsr128)

1130

1131

1132 if (BuiltinID == AArch64::BI__builtin_arm_irg ||

1133 BuiltinID == AArch64::BI__builtin_arm_addg ||

1134 BuiltinID == AArch64::BI__builtin_arm_gmi ||

1135 BuiltinID == AArch64::BI__builtin_arm_ldg ||

1136 BuiltinID == AArch64::BI__builtin_arm_stg ||

1137 BuiltinID == AArch64::BI__builtin_arm_subp) {

1139 }

1140

1141 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||

1142 BuiltinID == AArch64::BI__builtin_arm_rsrp ||

1143 BuiltinID == AArch64::BI__builtin_arm_wsr ||

1144 BuiltinID == AArch64::BI__builtin_arm_wsrp)

1146

1147

1148

1149

1150 if (BuiltinID == AArch64::BI_ReadStatusReg ||

1151 BuiltinID == AArch64::BI_WriteStatusReg || BuiltinID == AArch64::BI__sys)

1152 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);

1153

1154 if (BuiltinID == AArch64::BI__getReg)

1155 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);

1156

1157 if (BuiltinID == AArch64::BI__break)

1158 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);

1159

1160 if (BuiltinID == AArch64::BI__hlt)

1161 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);

1162

1164 return true;

1165

1167 return true;

1168

1170 return true;

1171

1172

1173

1174 unsigned i = 0, l = 0, u = 0;

1175 switch (BuiltinID) {

1176 default: return false;

1177 case AArch64::BI__builtin_arm_dmb:

1178 case AArch64::BI__dmb:

1179 case AArch64::BI__builtin_arm_dsb:

1180 case AArch64::BI__dsb:

1181 case AArch64::BI__builtin_arm_isb:

1182 case AArch64::BI__isb:

1183 l = 0;

1184 u = 15;

1185 break;

1186 }

1187

1188 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);

1189}

1190

1191namespace {

1192struct IntrinToName {

1193 uint32_t Id;

1194 int32_t FullName;

1195 int32_t ShortName;

1196};

1197}

1198

1201 const char *IntrinNames) {

1202 AliasName.consume_front("__arm_");

1203 const IntrinToName *It =

1204 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {

1205 return L.Id < Id;

1206 });

1207 if (It == Map.end() || It->Id != BuiltinID)

1208 return false;

1209 StringRef FullName(&IntrinNames[It->FullName]);

1210 if (AliasName == FullName)

1211 return true;

1212 if (It->ShortName == -1)

1213 return false;

1214 StringRef ShortName(&IntrinNames[It->ShortName]);

1215 return AliasName == ShortName;

1216}

1217

1219#include "clang/Basic/arm_mve_builtin_aliases.inc"

1220

1221

1222

1223 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);

1224}

1225

1227#include "clang/Basic/arm_cde_builtin_aliases.inc"

1228 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);

1229}

1230

1232 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))

1236}

1237

1239 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))

1243}

1244

1248 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)

1250 return;

1251 }

1252

1255 StringRef AliasName = cast(D)->getIdentifier()->getName();

1256

1257 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();

1258 if ((IsAArch64 && SveAliasValid(BuiltinID, AliasName) &&

1260 (!IsAArch64 && MveAliasValid(BuiltinID, AliasName) &&

1262 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);

1263 return;

1264 }

1265

1266 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));

1267}

1268

1272 auto CheckForIncompatibleAttr =

1274 StringRef IncompatibleStateName) {

1275 if (CurrentState == IncompatibleState) {

1276 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)

1277 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")

1278 << (std::string("'") + IncompatibleStateName.str() + "(\"" +

1279 StateName.str() + "\")'")

1280 << true;

1282 }

1283 };

1284

1290}

1291

1294 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;

1296 return;

1297 }

1298

1299 std::vector NewState;

1300 if (const auto *ExistingAttr = D->getAttr()) {

1301 for (StringRef S : ExistingAttr->newArgs())

1302 NewState.push_back(S);

1303 }

1304

1305 bool HasZA = false;

1306 bool HasZT0 = false;

1307 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {

1308 StringRef StateName;

1310 if (SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))

1311 return;

1312

1313 if (StateName == "za")

1314 HasZA = true;

1315 else if (StateName == "zt0")

1316 HasZT0 = true;

1317 else {

1318 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;

1320 return;

1321 }

1322

1323 if (!llvm::is_contained(NewState, StateName))

1324 NewState.push_back(StateName);

1325 }

1326

1327 if (auto *FPT = dyn_cast(D->getFunctionType())) {

1332 return;

1337 return;

1338 }

1339

1342 getASTContext(), AL, NewState.data(), NewState.size()));

1343}

1344

1347 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;

1348 return;

1349 }

1350

1352 if (!FD->isExternallyVisible()) {

1353 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);

1354 return;

1355 }

1356

1358}

1359

1361

1363 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;

1364 return;

1365 }

1366

1367 StringRef Str;

1369

1371 Str = "";

1372 else if (SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))

1373 return;

1374

1375 ARMInterruptAttr::InterruptType Kind;

1376 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {

1377 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)

1378 << AL << Str << ArgLoc;

1379 return;

1380 }

1381

1382 if (!D->hasAttr()) {

1385 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);

1386 }

1387

1390}

1391

1393

1394

1395

1397 SemaRef.ARM().handleInterruptAttr(D, AL);

1398

1399

1400 if (!D->hasAttr()) {

1401 D->dropAttr();

1402 return;

1403 }

1404

1405

1406 bool VFP = SemaRef.Context.getTargetInfo().hasFeature("vfp");

1407

1408 if (!VFP) {

1409 SemaRef.Diag(D->getLocation(), diag::warn_arm_interrupt_save_fp_without_vfp_unit);

1410 D->dropAttr();

1411 }

1412}

1413

1414

1415

1416

1418 const auto *Attr = FD->getAttr();

1419 bool UsesSM = FD->hasAttr();

1420 bool UsesZA = Attr && Attr->isNewZA();

1421 bool UsesZT0 = Attr && Attr->isNewZT0();

1422

1423 if (UsesZA || UsesZT0) {

1427 Diag(FD->getLocation(), diag::err_sme_unsupported_agnostic_new);

1428 }

1429 }

1430

1431 if (FD->hasAttr()) {

1434 diag::warn_sme_locally_streaming_has_vl_args_returns)

1435 << false;

1437 return P->getOriginalType()->isSizelessVectorType();

1438 }))

1440 diag::warn_sme_locally_streaming_has_vl_args_returns)

1441 << true;

1442 }

1450 }

1451

1453 if (UsesSM || UsesZA) {

1454 llvm::StringMap FeatureMap;

1455 Context.getFunctionFeatureMap(FeatureMap, FD);

1456 if (!FeatureMap.contains("sme")) {

1457 if (UsesSM)

1459 diag::err_sme_definition_using_sm_in_non_sme_target);

1460 else

1462 diag::err_sme_definition_using_za_in_non_sme_target);

1463 }

1464 }

1465 if (UsesZT0) {

1466 llvm::StringMap FeatureMap;

1467 Context.getFunctionFeatureMap(FeatureMap, FD);

1468 if (!FeatureMap.contains("sme2")) {

1470 diag::err_sme_definition_using_zt0_in_non_sme2_target);

1471 }

1472 }

1473}

1474

1475

1477 bool IsStreaming) {

1479 uint64_t VScale = IsStreaming ? Context.getLangOpts().VScaleStreamingMin

1480 : Context.getLangOpts().VScaleMin;

1481 if (Ty->getKind() == BuiltinType::SveBool ||

1482 Ty->getKind() == BuiltinType::SveCount)

1483 return (VScale * 128) / Context.getCharWidth();

1484 return VScale * 128;

1485}

1486

1488 bool IsStreaming = false;

1492 SemaRef.getCurFunctionDecl(true)) {

1493

1495 if (T->getAArch64SMEAttributes() &

1497 return false;

1498 }

1499

1501 IsStreaming = true;

1502 }

1503 }

1504

1505 auto IsValidCast = [&](QualType FirstType, QualType SecondType) {

1508

1509

1512 return BT->getKind() == BuiltinType::SveBool;

1514 return VT->getElementType().getCanonicalType() ==

1517 return Context.getTypeSize(SecondType) ==

1519 Context.hasSameType(

1520 VT->getElementType(),

1521 Context.getBuiltinVectorTypeInfo(BT).ElementType);

1522 }

1523 }

1524 return false;

1525 };

1526

1527 return IsValidCast(FirstType, SecondType) ||

1528 IsValidCast(SecondType, FirstType);

1529}

1530

1533 bool IsStreaming = false;

1537 SemaRef.getCurFunctionDecl(true)) {

1538

1540 if (T->getAArch64SMEAttributes() &

1542 return false;

1543

1545 IsStreaming = true;

1546 }

1547 }

1548

1549 auto IsLaxCompatible = [&](QualType FirstType, QualType SecondType) {

1551 if (!BT)

1552 return false;

1553

1558 getLangOpts().getLaxVectorConversions();

1560

1561

1562

1563 if (BT->getKind() == BuiltinType::SveBool &&

1565 return false;

1566

1567

1568

1569

1570

1571

1573 Context.getTypeSize(SecondType) !=

1575 return false;

1576

1577

1578

1580 return true;

1581

1582

1583

1585 return VecTy->getElementType().getCanonicalType()->isIntegerType() &&

1587 }

1588

1589 return false;

1590 };

1591

1592 return IsLaxCompatible(FirstType, SecondType) ||

1593 IsLaxCompatible(SecondType, FirstType);

1594}

1595

1597 if (!Buffer.empty())

1598 Buffer.append("+");

1599 Buffer.append(Feat);

1600}

1601

1604 StringRef PriorityString[8] = {"P0", "P1", "P2", "P3",

1605 "P4", "P5", "P6", "P7"};

1606

1607 assert(Priority > 0 && Priority < 256 && "priority out of range");

1608

1609 for (unsigned BitPos = 0; BitPos < 8; ++BitPos)

1610 if (Priority & (1U << BitPos))

1611 appendFeature(PriorityString[BitPos], NewParam);

1612}

1613

1618

1619 auto [LHS, RHS] = Param.split(';');

1620 RHS = RHS.trim();

1621 bool IsDefault = false;

1623 LHS.split(Features, '+');

1624 for (StringRef Feat : Features) {

1625 Feat = Feat.trim();

1626 if (Feat == "default")

1627 IsDefault = true;

1628 else if (getASTContext().getTargetInfo().validateCpuSupports(Feat))

1629 return Diag(Loc, diag::warn_unsupported_target_attribute)

1632 }

1633

1634 if (!RHS.empty() && RHS.consume_front("priority=")) {

1635 if (IsDefault)

1636 Diag(Loc, diag::warn_invalid_default_version_priority);

1637 else {

1638 unsigned Digit;

1639 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)

1640 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;

1641 else

1643 }

1644 }

1645 return false;

1646}

1647

1652

1654 return true;

1655

1656 assert(Params.size() == Locs.size() &&

1657 "Mismatch between number of string parameters and locations");

1658

1659 bool HasDefault = false;

1660 bool HasNonDefault = false;

1661 for (unsigned I = 0, E = Params.size(); I < E; ++I) {

1662 const StringRef Param = Params[I].trim();

1664

1665 auto [LHS, RHS] = Param.split(';');

1666 RHS = RHS.trim();

1667 bool HasPriority = !RHS.empty() && RHS.consume_front("priority=");

1668

1669 if (LHS.empty())

1670 return Diag(Loc, diag::warn_unsupported_target_attribute)

1672

1673 if (LHS == "default") {

1674 if (HasDefault)

1675 Diag(Loc, diag::warn_target_clone_duplicate_options);

1676 else {

1677 if (HasPriority)

1678 Diag(Loc, diag::warn_invalid_default_version_priority);

1679 NewParams.push_back(LHS);

1680 HasDefault = true;

1681 }

1682 continue;

1683 }

1684

1685 bool HasCodeGenImpact = false;

1688 LHS.split(Features, '+');

1689 for (StringRef Feat : Features) {

1690 Feat = Feat.trim();

1691 if (getASTContext().getTargetInfo().validateCpuSupports(Feat)) {

1692 Diag(Loc, diag::warn_unsupported_target_attribute)

1694 continue;

1695 }

1696 if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))

1697 HasCodeGenImpact = true;

1698 ValidFeatures.push_back(Feat);

1699 }

1700

1701

1702 if (!HasCodeGenImpact) {

1703 Diag(Loc, diag::warn_target_clone_no_impact_options);

1704 continue;

1705 }

1706

1707 if (ValidFeatures.empty())

1708 continue;

1709

1710

1711 llvm::sort(ValidFeatures);

1712 SmallString<64> NewParam(llvm::join(ValidFeatures, "+"));

1713 if (llvm::is_contained(NewParams, NewParam)) {

1714 Diag(Loc, diag::warn_target_clone_duplicate_options);

1715 continue;

1716 }

1717

1718 if (HasPriority) {

1719 unsigned Digit;

1720 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)

1721 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;

1722 else

1724 }

1725

1726

1727 NewParams.push_back(NewParam);

1728 HasNonDefault = true;

1729 }

1730 if (!HasNonDefault)

1731 return true;

1732

1733 return false;

1734}

1735

1738 const llvm::StringMap &FeatureMap) {

1740 return false;

1741

1742 if (FeatureMap.lookup("sve"))

1743 return false;

1744

1745

1746 if (!FeatureMap.lookup("sme"))

1747 return Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;

1748

1749

1752 return Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;

1753

1754 return false;

1755}

1756}

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)

Definition SemaARM.cpp:1417

bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:1025

void handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL)

Definition SemaARM.cpp:1392

bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:642

bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)

Definition SemaARM.cpp:824

bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:683

bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:712

bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:808

bool PerformNeonImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int, int > > &ImmChecks, int OverloadType=-1)

Definition SemaARM.cpp:513

bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:799

void handleInterruptAttr(Decl *D, const ParsedAttr &AL)

Definition SemaARM.cpp:1360

bool PerformSVEImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int > > &ImmChecks)

Definition SemaARM.cpp:532

void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)

Definition SemaARM.cpp:1245

@ 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)

Definition SemaARM.cpp:1292

bool CheckARMBuiltinExclusiveCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:849

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...

Definition SemaARM.cpp:1487

bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc, SmallString< 64 > &NewParam)

Definition SemaARM.cpp:1614

bool checkSVETypeSupport(QualType Ty, SourceLocation Loc, const FunctionDecl *FD, const llvm::StringMap< bool > &FeatureMap)

Definition SemaARM.cpp:1736

bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)

Definition SemaARM.cpp:1231

bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType)

Return true if the given vector types are lax-compatible SVE vector types, false otherwise.

Definition SemaARM.cpp:1531

bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)

Definition SemaARM.cpp:1108

bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)

Definition SemaARM.cpp:1218

bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall)

BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions.

Definition SemaARM.cpp:26

void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL)

Definition SemaARM.cpp:1345

bool CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, unsigned ArgIdx, unsigned EltBitWidth, unsigned VecBitWidth)

Definition SemaARM.cpp:375

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...

Definition SemaARM.cpp:188

bool SmeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)

Definition SemaARM.cpp:1238

bool checkTargetClonesAttr(SmallVectorImpl< StringRef > &Params, SmallVectorImpl< SourceLocation > &Locs, SmallVectorImpl< SmallString< 64 > > &NewParams)

Definition SemaARM.cpp:1648

bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)

Definition SemaARM.cpp:1226

SemaARM(Sema &S)

Definition SemaARM.cpp:23

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'.

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)

Definition SemaARM.cpp:1602

static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)

Definition SemaARM.cpp:1199

static ArmSMEState getSMEState(unsigned BuiltinID)

Definition SemaARM.cpp:632

static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)

Definition SemaARM.cpp:561

ArmSMEState

Definition SemaARM.cpp:361

@ ArmInOutZA

Definition SemaARM.cpp:366

@ ArmZT0Mask

Definition SemaARM.cpp:372

@ ArmInOutZT0

Definition SemaARM.cpp:371

@ ArmInZA

Definition SemaARM.cpp:364

@ ArmInZT0

Definition SemaARM.cpp:369

@ ArmZAMask

Definition SemaARM.cpp:367

@ ArmOutZA

Definition SemaARM.cpp:365

@ ArmOutZT0

Definition SemaARM.cpp:370

@ ArmNoState

Definition SemaARM.cpp:362

SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)

Definition SemaARM.cpp:545

static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty, bool IsStreaming)

getSVETypeSize - Return SVE vector or predicate register size.

Definition SemaARM.cpp:1476

@ AANT_ArgumentIdentifier

@ Result

The result type of a method or function.

const FunctionProtoType * T

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...

Definition SemaARM.cpp:321

static bool checkNewAttrMutualExclusion(Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, FunctionType::ArmStateValue CurrentState, StringRef StateName)

Definition SemaARM.cpp:1269

static void appendFeature(StringRef Feat, SmallString< 64 > &Buffer)

Definition SemaARM.cpp:1596

@ 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