clang: lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

22

27#include "llvm/Support/ErrorHandling.h"

28

29using namespace clang;

31

32namespace {

33

34class CIRGenItaniumCXXABI : public CIRGenCXXABI {

35protected:

36

37 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;

38

39public:

40 CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {

43 }

44

45 AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf,

46 const CXXConstructorDecl *d,

48 bool forVirtualBase,

49 bool delegating) override;

50

51 bool needsVTTParameter(clang::GlobalDecl gd) override;

52

53 AddedStructorArgCounts

54 buildStructorSignature(GlobalDecl gd,

55 llvm::SmallVectorImpl &argTys) override;

56

57 void emitInstanceFunctionProlog(SourceLocation loc,

58 CIRGenFunction &cgf) override;

59

60 void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy,

61 FunctionArgList &params) override;

63 const CXXDestructorDecl *dd,

65 bool forVirtualBase,

66 bool delegating) override;

67 void emitCXXConstructors(const clang::CXXConstructorDecl *d) override;

68 void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;

69 void emitCXXStructor(clang::GlobalDecl gd) override;

70

71 void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd,

73 bool delegating, Address thisAddr,

74 QualType thisTy) override;

75 void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,

76 mlir::Value addr) override;

77 void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,

78 Address ptr, QualType elementType,

79 const CXXDestructorDecl *dtor) override;

80

81 void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;

82 void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;

83

84 void emitBeginCatch(CIRGenFunction &cgf,

85 const CXXCatchStmt *catchStmt) override;

86

87 bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,

89

90

91

92 return false;

93 }

94

95 bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,

96 CIRGenFunction::VPtr vptr) override;

97

98 cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,

99 CharUnits vptrOffset) override;

100 CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,

101 clang::GlobalDecl gd, Address thisAddr,

102 mlir::Type ty,

103 SourceLocation loc) override;

104 mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf,

105 const CXXDestructorDecl *dtor,

107 DeleteOrMemberCallExpr e) override;

108 mlir::Value getVTableAddressPoint(BaseSubobject base,

109 const CXXRecordDecl *vtableClass) override;

110 mlir::Value getVTableAddressPointInStructorWithVTT(

111 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,

112 const CXXRecordDecl *nearestVBase);

113

114 mlir::Value getVTableAddressPointInStructor(

115 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,

116 clang::BaseSubobject base,

117 const clang::CXXRecordDecl *nearestVBase) override;

118 void emitVTableDefinitions(CIRGenVTables &cgvt,

119 const CXXRecordDecl *rd) override;

120 void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;

121

122 mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,

123 QualType ty) override;

124 CatchTypeInfo

125 getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,

126 QualType catchHandlerType) override {

127 auto rtti = dyn_castcir::GlobalViewAttr(getAddrOfRTTIDescriptor(loc, ty));

128 assert(rtti && "expected GlobalViewAttr");

129 return CatchTypeInfo{rtti, 0};

130 }

131

132 bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {

133 return true;

134 }

135

136 size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,

137 FunctionArgList &args) const override {

138 assert(!args.empty() && "expected the arglist to not be empty!");

139 return args.size() - 1;

140 }

141

142 void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override;

143

144 mlir::Value

145 getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,

146 Address thisAddr, const CXXRecordDecl *classDecl,

147 const CXXRecordDecl *baseClassDecl) override;

148

149

150

151

152

153

154 mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,

155 QualType srcRecordTy, QualType destRecordTy,

156 cir::PointerType destCIRTy, bool isRefCast,

157 Address src) override;

158

159 Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,

160 mlir::Value numElements, const CXXNewExpr *e,

161 QualType elementType) override;

162

163protected:

164 CharUnits getArrayCookieSizeImpl(QualType elementType) override;

165

166

167

168

169 virtual bool shouldRTTIBeUnique() const { return true; }

170

171public:

172

173 enum RTTIUniquenessKind {

174

175

176 RUK_Unique,

177

178

179

180 RUK_NonUniqueHidden,

181

182

183

184

185 RUK_NonUniqueVisible

186 };

187

188

189

190 RTTIUniquenessKind

191 classifyRTTIUniqueness(QualType canTy, cir::GlobalLinkageKind linkage) const;

192};

193

194}

195

196void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,

198

201 "emitInstanceFunctionProlog: Naked");

202 }

203

204

205

206 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));

207

208

209 if (getStructorImplicitParamDecl(cgf)) {

213 setStructorImplicitParamValue(cgf, val);

214 }

215

216

217

218

219

220

221

222

223

224 if (hasThisReturn(cgf.curGD)) {

226 "emitInstanceFunctionProlog: hasThisReturn");

227 }

228}

229

230CIRGenCXXABI::AddedStructorArgCounts

231CIRGenItaniumCXXABI::buildStructorSignature(

232 GlobalDecl gd, llvm::SmallVectorImpl &argTys) {

233 clang::ASTContext &astContext = cgm.getASTContext();

234

235

236

237

238

243 argTys.insert(argTys.begin() + 1,

246 return AddedStructorArgCounts::withPrefix(1);

247 }

248

249 return AddedStructorArgCounts{};

250}

251

252

253namespace {

254enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };

255}

256

260 return StructorCIRGen::Emit;

261

262

263

265 return StructorCIRGen::Emit;

266

268 if (const auto *dd = dyn_cast(md)) {

270 } else {

273 }

274

276

278 return StructorCIRGen::RAUW;

279

280

282 return StructorCIRGen::RAUW;

283

285

288 return StructorCIRGen::COMDAT;

289 return StructorCIRGen::Emit;

290 }

291

292 return StructorCIRGen::Alias;

293}

294

299

300

301 StringRef mangledName = cgm.getMangledName(aliasDecl);

302 auto globalValue = dyn_cast_or_nullcir::CIRGlobalValueInterface(

304 if (globalValue && !globalValue.isDeclaration())

305 return;

306

307 auto entry = cast_or_nullcir::FuncOp(cgm.getGlobalValue(mangledName));

308

309

311

312

313 cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);

314}

315

316void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {

319 const auto *cd = dyn_cast(md);

320

323 GlobalDecl baseDecl =

325 ;

326

327 if (cirGenType == StructorCIRGen::Alias ||

328 cirGenType == StructorCIRGen::COMDAT) {

330 return;

331 }

332

333 if (cirGenType == StructorCIRGen::RAUW) {

335 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);

337 return;

338 }

339 }

340

342

344}

345

346void CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,

347 QualType &resTy,

348 FunctionArgList &params) {

351

352

353 if (needsVTTParameter(cgf.curGD)) {

355

356

360 astContext, nullptr, md->getLocation(),

361 &astContext.Idents.get("vtt"), t, ImplicitParamKind::CXXVTT);

362 params.insert(params.begin() + 1, vttDecl);

363 getStructorImplicitParamDecl(cgf) = vttDecl;

364 }

365}

366

367void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {

368

370

371

372

374

375

376

378

380 }

381}

382

383void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {

384

385

387

388

389

391

392

393

394

397}

398

399CIRGenCXXABI::AddedStructorArgs CIRGenItaniumCXXABI::getImplicitConstructorArgs(

400 CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,

401 bool forVirtualBase, bool delegating) {

402 if (!needsVTTParameter(GlobalDecl(d, type)))

403 return AddedStructorArgs{};

404

405

406

407

408 mlir::Value vtt =

410 QualType vttTy =

413 return AddedStructorArgs::withPrefix({{vtt, vttTy}});

414}

415

416

417

418

419bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {

421

422

423 if (!md->getParent()->getNumVBases())

424 return false;

425

426

428 return true;

429

430

432 return true;

433

434 return false;

435}

436

437void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,

438 const CXXRecordDecl *rd) {

439 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());

440 if (vtable.hasInitializer())

441 return;

442

444 const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);

446 mlir::Attribute rtti =

449

450

451

452

455

456

457 vtable.setLinkage(linkage);

458

460 vtable.setComdat(true);

461

462

464

465

466

467

475 "emitVTableDefinitions: __fundamental_type_info");

476 }

477

478 [[maybe_unused]] auto vtableAsGlobalValue =

479 dyn_castcir::CIRGlobalValueInterface(*vtable);

480 assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");

481

482

483

484

485

486

490 "emitVTableDefinitions: WholeProgramVTables");

491 }

492

496 }

497}

498

499mlir::Value CIRGenItaniumCXXABI::emitVirtualDestructorCall(

500 CIRGenFunction &cgf, const CXXDestructorDecl *dtor, CXXDtorType dtorType,

501 Address thisAddr, DeleteOrMemberCallExpr expr) {

502 auto *callExpr = dyn_cast<const CXXMemberCallExpr *>(expr);

503 auto *delExpr = dyn_cast<const CXXDeleteExpr *>(expr);

504 assert((callExpr != nullptr) ^ (delExpr != nullptr));

507

508 GlobalDecl globalDecl(dtor, dtorType);

509 const CIRGenFunctionInfo *fnInfo =

513

514 QualType thisTy =

515 callExpr ? callExpr->getObjectType() : delExpr->getDestroyedType();

516

518 thisTy, nullptr, QualType(), nullptr);

519 return nullptr;

520}

521

522void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(

523 const CXXRecordDecl *rd) {

524 CIRGenVTables &vtables = cgm.getVTables();

525 cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);

527}

528

529namespace {

530class CIRGenItaniumRTTIBuilder {

531 CIRGenModule &cgm;

532 const CIRGenItaniumCXXABI &cxxABI;

533

534

535 SmallVector<mlir::Attribute, 16> fields;

536

537

538 cir::GlobalOp getAddrOfTypeName(mlir::Location loc, QualType ty,

539 cir::GlobalLinkageKind linkage);

540

541

542 mlir::Attribute getAddrOfExternalRTTIDescriptor(mlir::Location loc,

543 QualType ty);

544

545

546 void buildVTablePointer(mlir::Location loc, const Type *ty);

547

548

549

550 void buildSIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);

551

552

553

554

555 void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);

556

557public:

558 CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm)

559 : cgm(cgm), cxxABI(abi) {}

560

561

562

563 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty);

564

565

566 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty,

567 cir::GlobalLinkageKind linkage,

568 mlir::SymbolTable::Visibility visibility);

569};

570}

571

572

573namespace {

574

575

576enum {

577

578 PTI_Const = 0x1,

579

580

581 PTI_Volatile = 0x2,

582

583

584 PTI_Restrict = 0x4,

585

586

587 PTI_Incomplete = 0x8,

588

589

590

591 PTI_ContainingClassIncomplete = 0x10,

592

593

594

595

596

597 PTI_Noexcept = 0x40,

598};

599

600

601enum {

602

603 VMI_NonDiamondRepeat = 0x1,

604

605

606 VMI_DiamondShaped = 0x2

607};

608

609

610enum {

611

612 BCTI_Virtual = 0x1,

613

614

615 BCTI_Public = 0x2

616};

617

618

619

620

621static bool typeInfoIsInStandardLibrary(const BuiltinType *ty) {

622

623

624

625

626

627

628

629

630

631

632

633

634

635

637 case BuiltinType::WasmExternRef:

638 case BuiltinType::HLSLResource:

639 llvm_unreachable("NYI");

640 case BuiltinType::Void:

641 case BuiltinType::NullPtr:

642 case BuiltinType::Bool:

643 case BuiltinType::WChar_S:

644 case BuiltinType::WChar_U:

645 case BuiltinType::Char_U:

646 case BuiltinType::Char_S:

647 case BuiltinType::UChar:

648 case BuiltinType::SChar:

649 case BuiltinType::Short:

650 case BuiltinType::UShort:

651 case BuiltinType::Int:

652 case BuiltinType::UInt:

653 case BuiltinType::Long:

654 case BuiltinType::ULong:

655 case BuiltinType::LongLong:

656 case BuiltinType::ULongLong:

657 case BuiltinType::Half:

658 case BuiltinType::Float:

659 case BuiltinType::Double:

660 case BuiltinType::LongDouble:

661 case BuiltinType::Float16:

662 case BuiltinType::Float128:

663 case BuiltinType::Ibm128:

664 case BuiltinType::Char8:

665 case BuiltinType::Char16:

666 case BuiltinType::Char32:

667 case BuiltinType::Int128:

668 case BuiltinType::UInt128:

669 return true;

670

671#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \

672 case BuiltinType::Id:

673#include "clang/Basic/OpenCLImageTypes.def"

674#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:

675#include "clang/Basic/OpenCLExtensionTypes.def"

676 case BuiltinType::OCLSampler:

677 case BuiltinType::OCLEvent:

678 case BuiltinType::OCLClkEvent:

679 case BuiltinType::OCLQueue:

680 case BuiltinType::OCLReserveID:

681#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:

682#include "clang/Basic/AArch64ACLETypes.def"

683#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:

684#include "clang/Basic/PPCTypes.def"

685#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:

686#include "clang/Basic/RISCVVTypes.def"

687#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:

688#include "clang/Basic/AMDGPUTypes.def"

689 case BuiltinType::ShortAccum:

690 case BuiltinType::Accum:

691 case BuiltinType::LongAccum:

692 case BuiltinType::UShortAccum:

693 case BuiltinType::UAccum:

694 case BuiltinType::ULongAccum:

695 case BuiltinType::ShortFract:

696 case BuiltinType::Fract:

697 case BuiltinType::LongFract:

698 case BuiltinType::UShortFract:

699 case BuiltinType::UFract:

700 case BuiltinType::ULongFract:

701 case BuiltinType::SatShortAccum:

702 case BuiltinType::SatAccum:

703 case BuiltinType::SatLongAccum:

704 case BuiltinType::SatUShortAccum:

705 case BuiltinType::SatUAccum:

706 case BuiltinType::SatULongAccum:

707 case BuiltinType::SatShortFract:

708 case BuiltinType::SatFract:

709 case BuiltinType::SatLongFract:

710 case BuiltinType::SatUShortFract:

711 case BuiltinType::SatUFract:

712 case BuiltinType::SatULongFract:

713 case BuiltinType::BFloat16:

714 return false;

715

716 case BuiltinType::Dependent:

717#define BUILTIN_TYPE(Id, SingletonId)

718#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:

719#include "clang/AST/BuiltinTypes.def"

720 llvm_unreachable("asking for RRTI for a placeholder type!");

721

722 case BuiltinType::ObjCId:

723 case BuiltinType::ObjCClass:

724 case BuiltinType::ObjCSel:

725 llvm_unreachable("FIXME: Objective-C types are unsupported!");

726 }

727

728 llvm_unreachable("Invalid BuiltinType Kind!");

729}

730

731static bool typeInfoIsInStandardLibrary(const PointerType *pointerTy) {

733 const auto *builtinTy = dyn_cast(pointeeTy);

734 if (!builtinTy)

735 return false;

736

737

740

741 if (!quals.empty())

742 return false;

743

744 return typeInfoIsInStandardLibrary(builtinTy);

745}

746

747

748

749static bool isStandardLibraryRttiDescriptor(QualType ty) {

750

751 if (const auto *builtinTy = dyn_cast(ty))

752 return typeInfoIsInStandardLibrary(builtinTy);

753

754

755

756 if (const auto *pointerTy = dyn_cast(ty))

757 return typeInfoIsInStandardLibrary(pointerTy);

758

759 return false;

760}

761

762

763

764

765

766static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) {

768

769

770

772 return false;

773

774 if (const auto *recordTy = dyn_cast(ty)) {

775 const auto *rd =

778 return false;

779

781 return false;

782

783

784

785

786

787 bool isDLLImport = rd->hasAttr();

788

789

790 if (cgm.getTriple().isOSCygMing())

791 return false;

792

795 return true;

796

797 return !isDLLImport || cgm.getTriple().isWindowsItaniumEnvironment();

798 }

799

800 if (isDLLImport)

801 return true;

802 }

803

804 return false;

805}

806

807

808

809struct SeenBases {

810 llvm::SmallPtrSet<const CXXRecordDecl *, 16> nonVirtualBases;

811 llvm::SmallPtrSet<const CXXRecordDecl *, 16> virtualBases;

812};

813

814

815

816static unsigned computeVmiClassTypeInfoFlags(const CXXBaseSpecifier *base,

817 SeenBases &bases) {

818

819 unsigned flags = 0;

821

823

824 if (!bases.virtualBases.insert(baseDecl).second) {

825

826

827 flags |= VMI_DiamondShaped;

828 } else {

829 if (bases.nonVirtualBases.count(baseDecl))

830 flags |= VMI_NonDiamondRepeat;

831 }

832 } else {

833

834 if (!bases.nonVirtualBases.insert(baseDecl).second) {

835

836

837 flags |= VMI_NonDiamondRepeat;

838 } else {

839 if (bases.virtualBases.count(baseDecl))

840 flags |= VMI_NonDiamondRepeat;

841 }

842 }

843

844

845 for (const auto &bs : baseDecl->bases())

846 flags |= computeVmiClassTypeInfoFlags(&bs, bases);

847

848 return flags;

849}

850

851static unsigned computeVmiClassTypeInfoFlags(const CXXRecordDecl *rd) {

852 unsigned flags = 0;

853 SeenBases bases;

854

855

856 for (const auto &bs : rd->bases())

857 flags |= computeVmiClassTypeInfoFlags(&bs, bases);

858

859 return flags;

860}

861

862

863

864

865

866static bool canUseSingleInheritance(const CXXRecordDecl *rd) {

867

869 return false;

870

871

873

874

876 return false;

877

878

880 return false;

881

882

884 return baseDecl->isEmpty() ||

886}

887

888

889static bool isIncompleteClassType(const RecordType *recordTy) {

890 return !recordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();

891}

892

893

894

895

896

897

898

899

900

901

902

903

904static bool containsIncompleteClassType(QualType ty) {

905 if (const auto *recordTy = dyn_cast(ty)) {

906 if (isIncompleteClassType(recordTy))

907 return true;

908 }

909

910 if (const auto *pointerTy = dyn_cast(ty))

911 return containsIncompleteClassType(pointerTy->getPointeeType());

912

913 if (const auto *memberPointerTy = dyn_cast(ty)) {

914

915 if (!memberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())

916 return true;

917

918 return containsIncompleteClassType(memberPointerTy->getPointeeType());

919 }

920

921 return false;

922}

923

924const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {

925

926 static const char *const classTypeInfo =

927 "_ZTVN10__cxxabiv117__class_type_infoE";

928

929 static const char *const siClassTypeInfo =

930 "_ZTVN10__cxxabiv120__si_class_type_infoE";

931

932 static const char *const vmiClassTypeInfo =

933 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";

934

936#define TYPE(Class, Base)

937#define ABSTRACT_TYPE(Class, Base)

938#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:

939#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:

940#define DEPENDENT_TYPE(Class, Base) case Type::Class:

941#include "clang/AST/TypeNodes.inc"

942 llvm_unreachable("Non-canonical and dependent types shouldn't get here");

943

944 case Type::LValueReference:

945 case Type::RValueReference:

946 llvm_unreachable("References shouldn't get here");

947

948 case Type::Auto:

949 case Type::DeducedTemplateSpecialization:

950 llvm_unreachable("Undeduced type shouldn't get here");

951

952 case Type::Pipe:

953 llvm_unreachable("Pipe types shouldn't get here");

954

955 case Type::ArrayParameter:

956 llvm_unreachable("Array Parameter types should not get here.");

957

958 case Type::Builtin:

959 case Type::BitInt:

960

961 case Type::Vector:

962 case Type::ExtVector:

963 case Type::ConstantMatrix:

964 case Type::Complex:

965 case Type::Atomic:

966

967 case Type::BlockPointer:

968 return "_ZTVN10__cxxabiv123__fundamental_type_infoE";

969 case Type::ConstantArray:

970 case Type::IncompleteArray:

971 case Type::VariableArray:

972 cgm.errorNYI("VTableClassNameForType: __array_type_info");

973 break;

974

975 case Type::FunctionNoProto:

976 case Type::FunctionProto:

977 cgm.errorNYI("VTableClassNameForType: __function_type_info");

978 break;

979

980 case Type::Enum:

981 return "_ZTVN10__cxxabiv116__enum_type_infoE";

982

983 case Type::Record: {

985 ->getDefinitionOrSelf();

986

988 return classTypeInfo;

989 }

990

991 if (canUseSingleInheritance(rd)) {

992 return siClassTypeInfo;

993 }

994

995 return vmiClassTypeInfo;

996 }

997

998 case Type::ObjCObject:

999 cgm.errorNYI("VTableClassNameForType: ObjCObject");

1000 break;

1001

1002 case Type::ObjCInterface:

1003 cgm.errorNYI("VTableClassNameForType: ObjCInterface");

1004 break;

1005

1006 case Type::ObjCObjectPointer:

1007 case Type::Pointer:

1008 cgm.errorNYI("VTableClassNameForType: __pointer_type_info");

1009 break;

1010

1011 case Type::MemberPointer:

1012 cgm.errorNYI("VTableClassNameForType: __pointer_to_member_type_info");

1013 break;

1014

1015 case Type::HLSLAttributedResource:

1016 case Type::HLSLInlineSpirv:

1017 llvm_unreachable("HLSL doesn't support virtual functions");

1018 }

1019

1020 return nullptr;

1021}

1022}

1023

1024

1025

1028

1029

1030

1031

1032

1033

1034

1035

1036 if (containsIncompleteClassType(ty))

1037 return cir::GlobalLinkageKind::InternalLinkage;

1038

1041 llvm_unreachable("Linkage hasn't been computed!");

1042

1046 return cir::GlobalLinkageKind::InternalLinkage;

1047

1051

1052

1054 return cir::GlobalLinkageKind::LinkOnceODRLinkage;

1055

1056 if (const RecordType *record = dyn_cast(ty)) {

1057 const auto *rd =

1059 if (rd->hasAttr())

1060 return cir::GlobalLinkageKind::WeakODRLinkage;

1061

1062 if (cgm.getTriple().isWindowsItaniumEnvironment())

1063 if (rd->hasAttr() &&

1064 shouldUseExternalRttiDescriptor(cgm, ty))

1065 return cir::GlobalLinkageKind::ExternalLinkage;

1066

1067

1071 .isWindowsGNUEnvironment())

1073 }

1074

1075 return cir::GlobalLinkageKind::LinkOnceODRLinkage;

1076 }

1077

1078 llvm_unreachable("Invalid linkage!");

1079}

1080

1081cir::GlobalOp

1082CIRGenItaniumRTTIBuilder::getAddrOfTypeName(mlir::Location loc, QualType ty,

1083 cir::GlobalLinkageKind linkage) {

1084 CIRGenBuilderTy &builder = cgm.getBuilder();

1085 SmallString<256> name;

1086 llvm::raw_svector_ostream out(name);

1088

1089

1090

1091

1092 mlir::Attribute init = builder.getString(

1094 std::nullopt);

1095

1096 CharUnits align =

1098

1099

1100

1101

1103

1105 loc, name, initStr.getType(), linkage, align);

1107 return gv;

1108}

1109

1110mlir::Attribute

1111CIRGenItaniumRTTIBuilder::getAddrOfExternalRTTIDescriptor(mlir::Location loc,

1112 QualType ty) {

1113

1114 SmallString<256> name;

1115 llvm::raw_svector_ostream out(name);

1117 CIRGenBuilderTy &builder = cgm.getBuilder();

1118

1119

1120 cir::GlobalOp gv = dyn_cast_or_nullcir::GlobalOp(

1121 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));

1122

1123 if (!gv) {

1124

1125

1126

1127

1129 true);

1132

1133

1134

1136 cgm.errorNYI("getAddrOfExternalRTTIDescriptor: hasPS4DLLImportExport");

1137 }

1138 }

1139

1141}

1142

1143void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,

1144 const Type *ty) {

1145 CIRGenBuilderTy &builder = cgm.getBuilder();

1146 const char *vTableName = vTableClassNameForType(cgm, ty);

1147

1148

1150 cgm.errorNYI("buildVTablePointer: isRelativeLayout");

1151 return;

1152 }

1153

1157 loc, vTableName, vtableGlobalTy, cir::GlobalLinkageKind::ExternalLinkage,

1159

1160

1161 mlir::Attribute field{};

1163 cgm.errorNYI("buildVTablePointer: isRelativeLayout");

1164 } else {

1165 SmallVector<mlir::Attribute, 4> offsets{

1166 cgm.getBuilder().getI32IntegerAttr(2)};

1167 auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);

1169 vTable, indices);

1170 }

1171

1172 assert(field && "expected attribute");

1173 fields.push_back(field);

1174}

1175

1176

1177

1178void CIRGenItaniumRTTIBuilder::buildSIClassTypeInfo(mlir::Location loc,

1179 const CXXRecordDecl *rd) {

1180

1181

1182

1183 mlir::Attribute baseTypeInfo =

1184 CIRGenItaniumRTTIBuilder(cxxABI, cgm)

1186 fields.push_back(baseTypeInfo);

1187}

1188

1189

1190

1191

1192void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,

1193 const CXXRecordDecl *rd) {

1194 mlir::Type unsignedIntLTy =

1196

1197

1198

1199

1200

1201 unsigned flags = computeVmiClassTypeInfoFlags(rd);

1202 fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags));

1203

1204

1205

1206

1207 fields.push_back(cir::IntAttr::get(unsignedIntLTy, rd->getNumBases()));

1208

1210 return;

1211

1212

1213

1214

1215

1216

1217

1218

1219

1220

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230

1231

1232

1233

1234

1237 if (ti.getTriple().isOSCygMing() &&

1240 mlir::Type offsetFlagsLTy = cgm.convertType(offsetFlagsTy);

1241

1242 for (const CXXBaseSpecifier &base : rd->bases()) {

1243

1244 fields.push_back(CIRGenItaniumRTTIBuilder(cxxABI, cgm)

1245 .buildTypeInfo(loc, base.getType()));

1246

1248 int64_t offsetFlags = 0;

1249

1250

1251

1252

1253

1254 CharUnits offset;

1257 rd, baseDecl);

1258 else {

1259 const ASTRecordLayout &layout =

1262 }

1264

1265

1266

1268 offsetFlags |= BCTI_Virtual;

1270 offsetFlags |= BCTI_Public;

1271

1272 fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags));

1273 }

1274}

1275

1276mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc,

1277 QualType ty) {

1278

1280

1281

1282 SmallString<256> name;

1283 llvm::raw_svector_ostream out(name);

1285

1286 auto oldGV = dyn_cast_or_nullcir::GlobalOp(

1287 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));

1288

1289 if (oldGV && !oldGV.isDeclaration()) {

1290 assert(!oldGV.hasAvailableExternallyLinkage() &&

1291 "available_externally typeinfos not yet implemented");

1293 oldGV);

1294 }

1295

1296

1297 if (isStandardLibraryRttiDescriptor(ty) ||

1298 shouldUseExternalRttiDescriptor(cgm, ty))

1299 return getAddrOfExternalRTTIDescriptor(loc, ty);

1300

1301

1303

1304

1305

1308

1309 mlir::SymbolTable::Visibility symVisibility;

1311

1312 symVisibility = mlir::SymbolTable::Visibility::Public;

1313 else if (cxxABI.classifyRTTIUniqueness(ty, linkage) ==

1314 CIRGenItaniumCXXABI::RUK_NonUniqueHidden) {

1316 "buildTypeInfo: classifyRTTIUniqueness == RUK_NonUniqueHidden");

1318 } else

1320

1321 return buildTypeInfo(loc, ty, linkage, symVisibility);

1322}

1323

1324mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(

1325 mlir::Location loc, QualType ty, cir::GlobalLinkageKind linkage,

1326 mlir::SymbolTable::Visibility visibility) {

1327 CIRGenBuilderTy &builder = cgm.getBuilder();

1328

1330

1331

1332 buildVTablePointer(loc, cast(ty));

1333

1334

1335 cir::GlobalOp typeName = getAddrOfTypeName(loc, ty, linkage);

1336 mlir::Attribute typeNameField;

1337

1338

1339

1340 CIRGenItaniumCXXABI::RTTIUniquenessKind rttiUniqueness =

1341 cxxABI.classifyRTTIUniqueness(ty, linkage);

1342 if (rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique) {

1343

1344

1346 "buildTypeInfo: rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique");

1347 } else {

1348 typeNameField =

1350 }

1351

1352 fields.push_back(typeNameField);

1353

1355#define TYPE(Class, Base)

1356#define ABSTRACT_TYPE(Class, Base)

1357#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:

1358#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:

1359#define DEPENDENT_TYPE(Class, Base) case Type::Class:

1360#include "clang/AST/TypeNodes.inc"

1361 llvm_unreachable("Non-canonical and dependent types shouldn't get here");

1362

1363

1364 case Type::Builtin:

1365 case Type::Vector:

1366 case Type::ExtVector:

1367 case Type::ConstantMatrix:

1368 case Type::Complex:

1369 case Type::BlockPointer:

1370

1371

1372 break;

1373

1374 case Type::LValueReference:

1375 case Type::RValueReference:

1376 llvm_unreachable("References shouldn't get here");

1377

1378 case Type::Auto:

1379 case Type::DeducedTemplateSpecialization:

1380 llvm_unreachable("Undeduced type shouldn't get here");

1381

1382 case Type::Pipe:

1383 break;

1384

1385 case Type::BitInt:

1386 break;

1387

1388 case Type::ConstantArray:

1389 case Type::IncompleteArray:

1390 case Type::VariableArray:

1391 case Type::ArrayParameter:

1392

1393

1394 break;

1395

1396 case Type::FunctionNoProto:

1397 case Type::FunctionProto:

1398

1399

1400 break;

1401

1402 case Type::Enum:

1403

1404

1405 break;

1406

1407 case Type::Record: {

1409 ->getDefinitionOrSelf();

1411

1412 break;

1413 }

1414

1415 if (canUseSingleInheritance(rd)) {

1416 buildSIClassTypeInfo(loc, rd);

1417 } else {

1418 buildVMIClassTypeInfo(loc, rd);

1419 }

1420

1421 break;

1422 }

1423

1424 case Type::ObjCObject:

1425 case Type::ObjCInterface:

1426 cgm.errorNYI("buildTypeInfo: ObjCObject & ObjCInterface");

1427 break;

1428

1429 case Type::ObjCObjectPointer:

1430 cgm.errorNYI("buildTypeInfo: ObjCObjectPointer");

1431 break;

1432

1433 case Type::Pointer:

1434 cgm.errorNYI("buildTypeInfo: Pointer");

1435 break;

1436

1437 case Type::MemberPointer:

1438 cgm.errorNYI("buildTypeInfo: MemberPointer");

1439 break;

1440

1441 case Type::Atomic:

1442

1443 break;

1444

1445 case Type::HLSLAttributedResource:

1446 case Type::HLSLInlineSpirv:

1447 llvm_unreachable("HLSL doesn't support RTTI");

1448 }

1449

1451 cir::TypeInfoAttr init = builder.getTypeInfo(builder.getArrayAttr(fields));

1452

1453 SmallString<256> name;

1454 llvm::raw_svector_ostream out(name);

1456

1457

1458 auto oldGV = dyn_cast_or_nullcir::GlobalOp(

1459 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));

1460

1461 cir::GlobalOp gv =

1463 true);

1464

1465

1466

1468 cgm.errorNYI("buildTypeInfo: target hasPS4DLLImportExport");

1469 return {};

1470 }

1471

1472

1473 if (oldGV) {

1474

1475 gv.setName(oldGV.getName());

1476 if (!oldGV->use_empty()) {

1477 cgm.errorNYI("buildTypeInfo: old GV !use_empty");

1478 return {};

1479 }

1480 oldGV->erase();

1481 }

1482

1485 cgm.errorNYI("buildTypeInfo: supportsCOMDAT & isWeakForLinker");

1486 return {};

1487 }

1488

1491 gv.setAlignmentAttr(cgm.getSize(align));

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503

1504

1505

1506

1507

1508 mlir::SymbolTable::setSymbolVisibility(typeName, visibility);

1512

1513 mlir::SymbolTable::setSymbolVisibility(gv, visibility);

1517

1520}

1521

1522mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,

1523 QualType ty) {

1524 return CIRGenItaniumRTTIBuilder(*this, cgm).buildTypeInfo(loc, ty);

1525}

1526

1527

1528

1529CIRGenItaniumCXXABI::RTTIUniquenessKind

1530CIRGenItaniumCXXABI::classifyRTTIUniqueness(

1531 QualType canTy, cir::GlobalLinkageKind linkage) const {

1532 if (shouldRTTIBeUnique())

1533 return RUK_Unique;

1534

1535

1536 if (linkage != cir::GlobalLinkageKind::LinkOnceODRLinkage &&

1537 linkage != cir::GlobalLinkageKind::WeakODRLinkage)

1538 return RUK_Unique;

1539

1540

1542 return RUK_Unique;

1543

1544

1545 if (linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)

1546 return RUK_NonUniqueHidden;

1547

1548

1549

1550

1551 assert(linkage == cir::GlobalLinkageKind::WeakODRLinkage);

1552 return RUK_NonUniqueVisible;

1553}

1554

1555void CIRGenItaniumCXXABI::emitDestructorCall(

1556 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,

1557 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {

1558 GlobalDecl gd(dd, type);

1559 mlir::Value vtt =

1564 CIRGenCallee callee =

1566

1568 vttTy, nullptr);

1569}

1570

1571void CIRGenItaniumCXXABI::registerGlobalDtor(const VarDecl *vd,

1572 cir::FuncOp dtor,

1573 mlir::Value addr) {

1575 return;

1576

1579 return;

1580 }

1581

1582

1585 return;

1586 }

1587

1588

1589

1590}

1591

1592mlir::Value CIRGenItaniumCXXABI::getCXXDestructorImplicitParam(

1593 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,

1594 bool forVirtualBase, bool delegating) {

1595 GlobalDecl gd(dd, type);

1596 return cgf.getVTTParameter(gd, forVirtualBase, delegating);

1597}

1598

1599

1600

1601

1603 mlir::Value exceptionPtr = {},

1604 mlir::FlatSymbolRefAttr typeInfo = {},

1605 mlir::FlatSymbolRefAttr dtor = {}) {

1606 mlir::Block *currentBlock = builder.getInsertionBlock();

1607 mlir::Region *region = currentBlock->getParent();

1608

1609 if (currentBlock->empty()) {

1610 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);

1611 cir::UnreachableOp::create(builder, loc);

1612 } else {

1613 mlir::Block *throwBlock = builder.createBlock(region);

1614

1615 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);

1616 cir::UnreachableOp::create(builder, loc);

1617

1618 builder.setInsertionPointToEnd(currentBlock);

1619 cir::BrOp::create(builder, loc, throwBlock);

1620 }

1621

1622 (void)builder.createBlock(region);

1623}

1624

1625void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {

1626

1627 if (isNoReturn) {

1628 CIRGenBuilderTy &builder = cgf.getBuilder();

1629 assert(cgf.currSrcLoc && "expected source location");

1630 mlir::Location loc = *cgf.currSrcLoc;

1632 } else {

1633 cgm.errorNYI("emitRethrow with isNoReturn false");

1634 }

1635}

1636

1637void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,

1638 const CXXThrowExpr *e) {

1639

1640

1641

1642

1643

1644 CIRGenBuilderTy &builder = cgf.getBuilder();

1646 cir::PointerType throwTy =

1651

1652

1653 mlir::TypedValuecir::PointerType exceptionPtr =

1654 cir::AllocExceptionOp::create(builder, subExprLoc, throwTy,

1655 builder.getI64IntegerAttr(typeSize))

1656 .getAddr();

1657

1658

1661

1662

1663 auto typeInfo = mlir::castcir::GlobalViewAttr(

1665 true));

1666 assert(!typeInfo.getIndices() && "expected no indirection");

1667

1668

1669

1670

1671

1672

1673

1674

1675 if (const RecordType *recordTy = clangThrowType->getAs()) {

1678 if (!rec->hasTrivialDestructor()) {

1679 cgm.errorNYI("emitThrow: non-trivial destructor");

1680 return;

1681 }

1682 }

1683

1684

1687}

1688

1691 case TargetCXXABI::GenericItanium:

1692 case TargetCXXABI::GenericAArch64:

1693 return new CIRGenItaniumCXXABI(cgm);

1694

1695 case TargetCXXABI::AppleARM64:

1696

1697

1699 return new CIRGenItaniumCXXABI(cgm);

1700

1701 default:

1702 llvm_unreachable("bad or NYI ABI kind");

1703 }

1704}

1705

1706cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,

1708 assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");

1709 cir::GlobalOp &vtable = vtables[rd];

1710 if (vtable)

1711 return vtable;

1712

1713

1715

1717 llvm::raw_svector_ostream out(name);

1718 getMangleContext().mangleCXXVTable(rd, out);

1719

1723

1724

1725

1726

1728 ? 32

1730

1733 cir::GlobalLinkageKind::ExternalLinkage,

1735

1737

1738

1739

1740

1741

1742

1743

1744

1747 "getAddrOfVTable: PS4 DLL import/export");

1748

1750 return vtable;

1751}

1752

1753CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(

1757 mlir::Location loc = cgf.getLoc(srcLoc);

1758 cir::PointerType tyPtr = builder.getPointerTo(ty);

1760 mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());

1761

1763 mlir::Value vfunc{};

1765 cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");

1766 } else {

1768

1769 mlir::Value vfuncLoad;

1772 cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");

1773 } else {

1774 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(

1775 builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);

1776 vfuncLoad = builder.createAlignedLoad(loc, tyPtr, vtableSlotPtr,

1778 }

1779

1780

1781

1782

1783

1784

1785

1788 cgm.errorNYI(loc, "getVirtualFunctionPointer: strictVTablePointers");

1789 }

1790 vfunc = vfuncLoad;

1791 }

1792

1793 CIRGenCallee callee(gd, vfunc.getDefiningOp());

1794 return callee;

1795}

1796

1797mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(

1798 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,

1799 const CXXRecordDecl *nearestVBase) {

1801 needsVTTParameter(cgf.curGD) && "This class doesn't have VTT");

1802

1803

1804 uint64_t virtualPointerIndex =

1806

1807

1808 mlir::Value vttPtr = cgf.loadCXXVTT();

1810

1812 virtualPointerIndex);

1813

1814 auto vptrType = cir::VPtrType::get(cgf.getBuilder().getContext());

1817}

1818

1819mlir::Value

1820CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,

1821 const CXXRecordDecl *vtableClass) {

1822 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());

1823

1824

1825

1826 VTableLayout::AddressPointLocation addressPoint =

1830

1831 mlir::OpBuilder &builder = cgm.getBuilder();

1832 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());

1833

1834 return cir::VTableAddrPointOp::create(

1836 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),

1837 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),

1840}

1841

1842mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(

1843 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,

1844 clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {

1845

1847 needsVTTParameter(cgf.curGD)) {

1848 return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,

1849 nearestVBase);

1850 }

1851 return getVTableAddressPoint(base, vtableClass);

1852}

1853

1854bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(

1855 CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {

1857 return false;

1858 return needsVTTParameter(cgf.curGD);

1859}

1860

1861mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(

1862 mlir::Location loc, CIRGenFunction &cgf, Address thisAddr,

1863 const CXXRecordDecl *classDecl, const CXXRecordDecl *baseClassDecl) {

1864 CIRGenBuilderTy &builder = cgf.getBuilder();

1865 mlir::Value vtablePtr = cgf.getVTablePtr(loc, thisAddr, classDecl);

1867 CharUnits vbaseOffsetOffset =

1869 baseClassDecl);

1870 mlir::Value offsetVal =

1872 auto vbaseOffsetPtr = cir::PtrStrideOp::create(builder, loc, cgm.uInt8PtrTy,

1873 vtableBytePtr, offsetVal);

1874

1875 mlir::Value vbaseOffset;

1878 cgm.errorNYI(loc, "getVirtualBaseClassOffset: relative layout");

1879 } else {

1884 }

1885 return vbaseOffset;

1886}

1887

1889

1890

1891

1893

1894 cir::FuncType fnTy =

1897}

1898

1900

1902

1904 cir::UnreachableOp::create(cgf.getBuilder(), loc);

1905 cgf.getBuilder().clearInsertionPoint();

1906}

1907

1908void CIRGenItaniumCXXABI::emitBadCastCall(CIRGenFunction &cgf,

1909 mlir::Location loc) {

1911}

1912

1913

1917 CXXBasePaths paths(true, true,

1918 false);

1919

1920

1921

1922 if (!dst->isDerivedFrom(src, paths))

1924

1925 unsigned numPublicPaths = 0;

1927

1928

1930 if (path.Access != AS_public)

1931 continue;

1932

1933 ++numPublicPaths;

1934

1936

1937

1938 if (pathElement.Base->isVirtual())

1940

1941 if (numPublicPaths > 1)

1942 continue;

1943

1944

1948 pathElement.Base->getType()->getAsCXXRecordDecl());

1949 }

1950 }

1951

1952

1953 if (numPublicPaths == 0)

1955

1956

1957 if (numPublicPaths > 1)

1959

1960

1961

1962 return offset;

1963}

1964

1966

1967

1968

1969

1970

1971

1975

1976

1980

1981

1983

1985 {voidPtrTy, rttiPtrTy, rttiPtrTy, ptrDiffTy}, voidPtrTy);

1987}

1988

1991 bool vtableUsesRelativeLayout =

1994 loc, src.getPointer(), vtableUsesRelativeLayout);

1996}

1997

2002 cir::PointerType destCIRTy,

2003 bool isRefCast, Address src) {

2004

2007 CXXBasePaths paths(true, true,

2008 false);

2010

2011

2012

2013 std::optional offset;

2015

2017 continue;

2018

2021

2023 pathElement.Base->getType()->getAsCXXRecordDecl();

2024 if (pathElement.Base->isVirtual()) {

2025

2026

2030 } else {

2034 }

2035 }

2036

2037 if (!offset) {

2038 offset = pathOffset;

2039 } else if (offset != pathOffset) {

2040

2041

2042

2043

2045 srcDecl = destDecl;

2047 break;

2048 }

2049 }

2050

2052

2053 if (!offset) {

2054

2055 mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);

2056 if (isRefCast) {

2057 mlir::Region *currentRegion = builder.getBlock()->getParent();

2059

2060

2061

2062 builder.createBlock(currentRegion, currentRegion->end());

2063 }

2064

2065 return nullPtrValue;

2066 }

2067

2068

2069

2070

2071

2072

2073 mlir::Value expectedVPtr =

2074 abi.getVTableAddressPoint(BaseSubobject(srcDecl, *offset), destDecl);

2075

2076

2078 mlir::Type vptrTy = expectedVPtr.getType();

2079 mlir::Type vptrPtrTy = builder.getPointerTo(vptrTy);

2082 mlir::Value srcVPtr = builder.createLoad(loc, srcVPtrPtr);

2083

2084

2086

2087 mlir::Value success =

2088 builder.createCompare(loc, cir::CmpOpKind::eq, srcVPtr, expectedVPtr);

2089

2090 auto emitCastResult = [&] {

2091 if (offset->isZero())

2093

2094

2097

2098 mlir::Value strideToApply =

2101 mlir::Value resultU8Ptr = cir::PtrStrideOp::create(builder, loc, u8PtrTy,

2102 srcU8Ptr, strideToApply);

2103 return builder.createBitcast(resultU8Ptr, destCIRTy);

2104 };

2105

2106 if (isRefCast) {

2107 mlir::Value failed = builder.createNot(success);

2108 cir::IfOp::create(builder, loc, failed, false,

2109 [&](mlir::OpBuilder &, mlir::Location) {

2111 });

2112 return emitCastResult();

2113 }

2114

2115 return cir::TernaryOp::create(

2116 builder, loc, success,

2117 [&](mlir::OpBuilder &, mlir::Location) {

2118 auto result = emitCastResult();

2120 },

2121 [&](mlir::OpBuilder &, mlir::Location) {

2122 mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);

2124 })

2125 .getResult();

2126}

2127

2129 mlir::Location loc,

2132 auto srcRtti = mlir::castcir::GlobalViewAttr(

2134 auto destRtti = mlir::castcir::GlobalViewAttr(

2136

2138 cir::FuncOp badCastFuncOp = getBadCastFn(cgf);

2139 auto runtimeFuncRef = mlir::FlatSymbolRefAttr::get(runtimeFuncOp);

2140 auto badCastFuncRef = mlir::FlatSymbolRefAttr::get(badCastFuncOp);

2141

2145

2147 auto offsetHintAttr = cir::IntAttr::get(ptrdiffTy, offsetHint.getQuantity());

2148

2149 return cir::DynamicCastInfoAttr::get(srcRtti, destRtti, runtimeFuncRef,

2150 badCastFuncRef, offsetHintAttr);

2151}

2152

2153mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,

2154 mlir::Location loc,

2155 QualType srcRecordTy,

2156 QualType destRecordTy,

2157 cir::PointerType destCIRTy,

2158 bool isRefCast, Address src) {

2159 bool isCastToVoid = destRecordTy.isNull();

2160 assert((!isCastToVoid || !isRefCast) && "cannot cast to void reference");

2161

2162 if (isCastToVoid)

2164

2165

2166

2169 CIRGenBuilderTy &builder = cgf.getBuilder();

2170

2171 if (!isRefCast) {

2173 return cir::TernaryOp::create(

2174 builder, loc, srcPtrIsNull,

2175 [&](mlir::OpBuilder, mlir::Location) {

2177 loc, builder.getNullPtr(destCIRTy, loc).getResult());

2178 },

2179 [&](mlir::OpBuilder &, mlir::Location) {

2181 *this, cgf, loc, srcRecordTy, destRecordTy, destCIRTy,

2182 isRefCast, src);

2184 })

2185 .getResult();

2186 }

2187

2189 destCIRTy, isRefCast, src);

2190 }

2191

2192 cir::DynamicCastInfoAttr castInfo =

2195 isRefCast, castInfo);

2196}

2197

2198

2199

2200void CIRGenItaniumCXXABI::emitVirtualObjectDelete(

2201 CIRGenFunction &cgf, const CXXDeleteExpr *delExpr, Address ptr,

2202 QualType elementType, const CXXDestructorDecl *dtor) {

2204 if (useGlobalDelete) {

2206 "emitVirtualObjectDelete: global delete");

2207 }

2208

2210 emitVirtualDestructorCall(cgf, dtor, dtorType, ptr, delExpr);

2211}

2212

2213

2214

2215CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {

2216

2217

2218 return std::max(

2221}

2222

2223Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf,

2224 Address newPtr,

2225 mlir::Value numElements,

2226 const CXXNewExpr *e,

2227 QualType elementType) {

2228 assert(requiresArrayCookie(e));

2229

2230

2231

2234

2238

2239

2240 CharUnits cookieSize =

2242 assert(cookieSize == getArrayCookieSizeImpl(elementType));

2243

2245 mlir::Value baseBytePtr =

2247

2248

2249 CharUnits cookieOffset = cookieSize - sizeSize;

2250 mlir::Value cookiePtrValue = baseBytePtr;

2251 if (!cookieOffset.isZero()) {

2253 loc, cookieOffset.getQuantity(), 32);

2254 cookiePtrValue =

2256 }

2257

2258 CharUnits baseAlignment = newPtr.getAlignment();

2259 CharUnits cookiePtrAlignment = baseAlignment.alignmentAtOffset(cookieOffset);

2260 Address cookiePtr(cookiePtrValue, u8PtrTy, cookiePtrAlignment);

2261

2262

2263 Address numElementsPtr =

2266

2267

2268

2269 mlir::Value dataOffset =

2271 32);

2272 mlir::Value dataPtr =

2274 mlir::Value finalPtr =

2276 CharUnits finalAlignment = baseAlignment.alignmentAtOffset(cookieSize);

2277 return Address(finalPtr, newPtr.getElementType(), finalAlignment);

2278}

2279

2280namespace {

2281

2282

2283

2284

2285

2286

2287

2288

2289

2290

2291

2292

2293

2294struct CallEndCatch final : EHScopeStack::Cleanup {

2295 CallEndCatch(bool mightThrow) : mightThrow(mightThrow) {}

2296 bool mightThrow;

2297

2298 void emit(CIRGenFunction &cgf, Flags flags) override {

2299 if (!mightThrow) {

2300

2301

2302

2303

2305 return;

2306 }

2307

2308

2309

2310

2311

2312 if (!cgf.getBuilder().getBlock()->mightHaveTerminator())

2314 }

2315};

2316}

2317

2319 bool endMightThrow) {

2320 auto catchParam = cir::CatchParamOp::create(

2322

2323 cgf.ehStack.pushCleanup(

2325 endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor);

2326

2327 return catchParam.getParam();

2328}

2329

2330

2331

2336

2337

2339 cgf.cgm.errorNYI(loc, "initCatchParam: ReferenceType");

2340 return;

2341 }

2342

2343

2346

2347

2348

2349 if (catchType->hasPointerRepresentation()) {

2350 cgf.cgm.errorNYI(loc, "initCatchParam: hasPointerRepresentation");

2351 return;

2352 }

2353

2355 mlir::Value catchParam =

2358 LValue destLV = cgf.makeAddrLValue(paramAddr, catchType);

2359 switch (tek) {

2361 cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Complex");

2362 return;

2363 }

2367 return;

2368 }

2370 llvm_unreachable("evaluation kind filtered out!");

2371 }

2372

2373

2374 llvm_unreachable("bad evaluation kind");

2375 }

2376

2377 cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate");

2378}

2379

2380

2381

2382void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf,

2383 const CXXCatchStmt *catchStmt) {

2384

2385

2386

2387

2388

2389

2390

2391

2392

2393

2394

2395

2396

2397

2398

2399

2400

2401

2402

2403

2404

2405

2406

2408 if (!catchParam) {

2410 true);

2411 return;

2412 }

2413

2414 auto getCatchParamAllocaIP = [&]() {

2415 cir::CIRBaseBuilderTy::InsertPoint currIns =

2416 cgf.getBuilder().saveInsertionPoint();

2417 mlir::Operation *currParent = currIns.getBlock()->getParentOp();

2418

2419 mlir::Block *insertBlock = nullptr;

2420 if (auto scopeOp = currParent->getParentOfTypecir::ScopeOp()) {

2421 insertBlock = &scopeOp.getScopeRegion().getBlocks().back();

2422 } else if (auto fnOp = currParent->getParentOfTypecir::FuncOp()) {

2423 insertBlock = &fnOp.getRegion().getBlocks().back();

2424 } else {

2425 llvm_unreachable("unknown outermost scope-like parent");

2426 }

2428 };

2429

2430

2431

2432

2433

2434 CIRGenFunction::AutoVarEmission var =

2439}

static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)

Helper to write bytecode and bail out if 32-bit offsets become invalid.

static void emitConstructorDestructorAlias(CIRGenModule &cgm, GlobalDecl aliasDecl, GlobalDecl targetDecl)

Definition CIRGenItaniumCXXABI.cpp:295

static CharUnits computeOffsetHint(ASTContext &astContext, const CXXRecordDecl *src, const CXXRecordDecl *dst)

Definition CIRGenItaniumCXXABI.cpp:1914

static void initCatchParam(CIRGenFunction &cgf, const VarDecl &catchParam, Address paramAddr, SourceLocation loc)

A "special initializer" callback for initializing a catch parameter during catch initialization.

Definition CIRGenItaniumCXXABI.cpp:2332

static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc, mlir::Value exceptionPtr={}, mlir::FlatSymbolRefAttr typeInfo={}, mlir::FlatSymbolRefAttr dtor={})

Definition CIRGenItaniumCXXABI.cpp:1602

static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Type paramTy, bool endMightThrow)

Definition CIRGenItaniumCXXABI.cpp:2318

static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, Address src)

Definition CIRGenItaniumCXXABI.cpp:1989

static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, QualType destRecordTy)

Definition CIRGenItaniumCXXABI.cpp:2128

static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm, QualType ty)

Return the linkage that the type info and type info name constants should have for the given type.

Definition CIRGenItaniumCXXABI.cpp:1026

static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi, CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, QualType destRecordTy, cir::PointerType destCIRTy, bool isRefCast, Address src)

Definition CIRGenItaniumCXXABI.cpp:1998

static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc)

Definition CIRGenItaniumCXXABI.cpp:1899

static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf)

Definition CIRGenItaniumCXXABI.cpp:1965

static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm, const CXXMethodDecl *md)

Definition CIRGenItaniumCXXABI.cpp:257

static cir::FuncOp getBadCastFn(CIRGenFunction &cgf)

Definition CIRGenItaniumCXXABI.cpp:1888

Defines the clang::Expr interface and subclasses for C++ expressions.

cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})

Get constant address of a global variable as an MLIR attribute.

mlir::Value createPtrIsNull(mlir::Value ptr)

cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)

static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block)

cir::PointerType getPointerTo(mlir::Type ty)

mlir::Value createNot(mlir::Value value)

cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)

mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)

mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits)

mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)

cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)

cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)

cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})

Create a yield operation.

llvm::Align getABITypeAlign(mlir::Type ty) const

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

CharUnits getTypeAlignInChars(QualType T) const

Return the ABI-specified alignment of a (complete) type T, in characters.

static CanQualType getCanonicalType(QualType T)

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

Get or compute information about the layout of the specified record (struct/union/class) D,...

QualType getPointerType(QualType T) const

Return the uniqued reference to the type for a pointer to the specified type.

const LangOptions & getLangOpts() const

QualType getPointerDiffType() const

Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.

CharUnits getExnObjectAlignment() const

Return the alignment (in bytes) of the thrown exception object.

CharUnits getPreferredTypeAlignInChars(QualType T) const

Return the PreferredAlignment of a (complete) type T, in characters.

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

CanQualType UnsignedIntTy

const TargetInfo & getTargetInfo() const

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

TargetCXXABI::Kind getCXXABIKind() const

Return the C++ ABI kind that should be used.

CanQualType getCanonicalTagType(const TagDecl *TD) const

ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...

CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const

getBaseClassOffset - Get the offset, in chars, for the given base class.

CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const

getVBaseClassOffset - Get the offset, in chars, for the given base class.

const CXXRecordDecl * getBase() const

getBase - Returns the base class declaration.

mlir::Value getPointer() const

mlir::Type getElementType() const

clang::CharUnits getAlignment() const

mlir::Value emitRawPointer() const

Return the pointer contained in this class after authenticating it and adding offset to it if necessa...

cir::IntType getUInt64Ty()

cir::TypeInfoAttr getTypeInfo(mlir::ArrayAttr fieldsAttr)

cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc)

cir::PointerType getUInt8PtrTy()

mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy, std::optional< size_t > size)

Get a cir::ConstArrayAttr for a string literal.

cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, llvm::MaybeAlign align)

cir::FuncType getFuncType(llvm::ArrayRef< mlir::Type > params, mlir::Type retTy, bool isVarArg=false)

mlir::Value createDynCastToVoid(mlir::Location loc, mlir::Value src, bool vtableUseRelativeLayout)

mlir::Value createDynCast(mlir::Location loc, mlir::Value src, cir::PointerType destType, bool isRefCast, cir::DynamicCastInfoAttr info)

cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})

cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)

mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy, mlir::Value addr, uint64_t offset)

cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)

Implements C++ ABI-specific code generation functions.

clang::MangleContext & getMangleContext()

Gets the mangle context.

static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())

static CIRGenCallee forVirtual(const clang::CallExpr *ce, clang::GlobalDecl md, Address addr, cir::FuncType fTy)

mlir::Type convertType(clang::QualType t)

static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)

Return the cir::TypeEvaluationKind of QualType type.

clang::GlobalDecl curGD

The GlobalDecl for the current function being compiled or the global variable currently being initial...

AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})

const clang::Decl * curFuncDecl

Address getAddrOfLocalVar(const clang::VarDecl *vd)

Return the address of a local variable.

void emitAnyExprToExn(const Expr *e, Address addr)

LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)

mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)

Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.

mlir::Location getLoc(clang::SourceLocation srcLoc)

Helpers to convert Clang's SourceLocation to a MLIR Location.

EHScopeStack ehStack

Tracks function scope overall cleanup handling.

mlir::Type convertTypeForMem(QualType t)

void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)

mlir::Value loadCXXVTT()

Load the VTT parameter to base constructors/destructors have virtual bases.

mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)

Return the Value of the vtable pointer member pointed to by thisAddr.

bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)

Returns whether we should perform a type checked load when loading a virtual function for virtual cal...

CIRGenBuilderTy & getBuilder()

mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)

EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...

mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee, llvm::ArrayRef< mlir::Value > args={})

LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)

void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)

std::optional< mlir::Location > currSrcLoc

Use to track source locations across nested visitor traversals.

clang::ASTContext & getContext() const

void emitAutoVarCleanups(const AutoVarEmission &emission)

This class organizes the cross-function state that is used while generating CIR code.

llvm::StringRef getMangledName(clang::GlobalDecl gd)

DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)

Helpers to emit "not yet implemented" error diagnostics.

clang::ASTContext & getASTContext() const

cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)

cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::ArrayAttr={}, bool isLocal=false, bool assumeConvergent=false)

void addReplacement(llvm::StringRef name, mlir::Operation *op)

mlir::Type convertType(clang::QualType type)

mlir::IntegerAttr getSize(CharUnits size)

CIRGenBuilderTy & getBuilder()

ItaniumVTableContext & getItaniumVTableContext()

void setGVProperties(mlir::Operation *op, const NamedDecl *d) const

Set visibility, dllimport/dllexport and dso_local.

mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)

Get the address of the RTTI descriptor for the given type.

const clang::TargetInfo & getTarget() const

const llvm::Triple & getTriple() const

static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v)

cir::GlobalOp createOrReplaceCXXRuntimeVariable(mlir::Location loc, llvm::StringRef name, mlir::Type ty, cir::GlobalLinkageKind linkage, clang::CharUnits alignment)

Will return a global variable of the given type.

void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op, GlobalDecl aliasGD, cir::FuncOp aliasee, cir::GlobalLinkageKind linkage)

const cir::CIRDataLayout getDataLayout() const

static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)

cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd)

const clang::CodeGenOptions & getCodeGenOpts() const

const clang::LangOptions & getLangOpts() const

cir::FuncOp codegenCXXStructor(clang::GlobalDecl gd)

mlir::Location getLoc(clang::SourceLocation cLoc)

Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.

mlir::Operation * getGlobalValue(llvm::StringRef ref)

mlir::ModuleOp getModule() const

bool supportsCOMDAT() const

mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)

static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::Operation *insertPoint=nullptr)

void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op)

CIRGenCXXABI & getCXXABI() const

void emitGlobal(clang::GlobalDecl gd)

Emit code for a single global function or variable declaration.

CIRGenVTables & getVTables()

cir::GlobalLinkageKind getVTableLinkage(const CXXRecordDecl *rd)

Return the appropriate linkage for the vtable, VTT, and type information of the given class.

const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)

cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)

Get the CIR function type for.

cir::RecordType getVTableType(const clang::VTableLayout &layout)

Returns the type of a vtable with the given layout.

void createVTableInitializer(cir::GlobalOp &vtable, const clang::VTableLayout &layout, mlir::Attribute rtti, bool vtableHasLocalLinkage)

Add vtable components for the given vtable layout to the given global initializer.

void emitVTTDefinition(cir::GlobalOp vttOp, cir::GlobalLinkageKind linkage, const CXXRecordDecl *rd)

Emit the definition of the given vtable.

cir::GlobalOp getAddrOfVTT(const CXXRecordDecl *rd)

Get the address of the VTT for the given record decl.

bool isVTableExternal(const clang::CXXRecordDecl *rd)

At this point in the translation unit, does it appear that can we rely on the vtable being defined el...

uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *rd, BaseSubobject base)

Return the index in the VTT where the virtual pointer for the given subobject is located.

Represents a path from a specific derived class (which is not represented as part of the path) to a p...

BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...

bool isVirtual() const

Determines whether the base class is a virtual base class (or not).

QualType getType() const

Retrieves the type of the base class.

AccessSpecifier getAccessSpecifier() const

Returns the access specifier for this base specifier.

SourceLocation getBeginLoc() const LLVM_READONLY

VarDecl * getExceptionDecl() const

bool isGlobalDelete() const

Represents a static or instance method of a struct/union/class.

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

SourceRange getSourceRange() const

Represents a C++ struct/union/class.

bool isEffectivelyFinal() const

Determine whether it's impossible for a class to be derived from this class.

unsigned getNumBases() const

Retrieves the number of base classes of this class.

base_class_iterator bases_begin()

const CXXBaseSpecifier * base_class_const_iterator

Iterator that traverses the base classes of a class.

bool isAbstract() const

Determine whether this class has a pure virtual function.

bool isDynamicClass() const

bool hasDefinition() const

unsigned getNumVBases() const

Retrieves the number of virtual base classes of this class.

bool isDerivedFrom(const CXXRecordDecl *Base) const

Determine whether this class is derived from the class Base.

const Expr * getSubExpr() const

static CanQual< Type > CreateUnsafe(QualType Other)

CharUnits - This is an opaque type for sizes expressed in character units.

CharUnits alignmentAtOffset(CharUnits offset) const

Given that this is a non-zero alignment value, what is the alignment at the given offset?

bool isZero() const

isZero - Test whether the quantity equals zero.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

static CharUnits fromQuantity(QuantityType Quantity)

fromQuantity - Construct a CharUnits quantity from a raw integer type.

static CharUnits Zero()

Zero - Construct a CharUnits quantity of zero.

DeclContext * getParent()

getParent - Returns the containing DeclContext.

bool isTranslationUnit() const

SourceLocation getLocation() const

DeclContext * getDeclContext()

GlobalDecl - represents a global declaration.

GlobalDecl getWithCtorType(CXXCtorType Type)

CXXCtorType getCtorType() const

GlobalDecl getWithDtorType(CXXDtorType Type)

CXXDtorType getDtorType() const

const Decl * getDecl() const

bool isStr(const char(&Str)[StrLen]) const

Return true if this is the identifier for the specified string.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)

Create implicit parameter.

uint64_t getMethodVTableIndex(GlobalDecl GD)

Locate a virtual function in the vtable.

bool isRelativeLayout() const

const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)

CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)

Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...

virtual void mangleCXXRTTI(QualType T, raw_ostream &)=0

virtual void mangleCXXRTTIName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

QualType getPointeeType() const

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

QualType getCanonicalType() const

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

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool hasConstructorVariants() const

Does this ABI have different entrypoints for complete-object and base-subobject constructors?

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

uint64_t getPointerWidth(LangAS AddrSpace) const

Return the width of pointers on this target, for the specified address space.

virtual bool hasPS4DLLImportExport() const

uint64_t getPointerAlign(LangAS AddrSpace) const

TargetCXXABI getCXXABI() const

Get the C++ ABI currently in use.

unsigned getLongWidth() const

getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...

SourceLocation getBeginLoc() const LLVM_READONLY

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

CXXRecordDecl * castAsCXXRecordDecl() const

Visibility getVisibility() const

Determine the visibility of this type.

Linkage getLinkage() const

Determine the linkage of this type.

TypeClass getTypeClass() const

const T * getAs() const

Member-template getAs'.

AddressPointLocation getAddressPoint(BaseSubobject Base) const

Represents a variable declaration or definition.

TLSKind getTLSKind() const

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool isNoDestroy(const ASTContext &) const

Is destruction of this variable entirely suppressed?

static bool isLocalLinkage(GlobalLinkageKind linkage)

static bool isValidLinkage(GlobalLinkageKind gl)

static bool isWeakForLinker(GlobalLinkageKind linkage)

Whether the definition of this global may be replaced at link time.

static bool isDiscardableIfUnused(GlobalLinkageKind linkage)

Whether the definition of this global may be discarded if it is not used in its compilation unit.

CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)

Creates and Itanium-family ABI.

Definition CIRGenItaniumCXXABI.cpp:1689

llvm::Value * getCXXDestructorImplicitParam(CodeGenModule &CGM, llvm::BasicBlock *InsertBlock, llvm::BasicBlock::iterator InsertPoint, const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating)

const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr

Matches call expressions.

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr

Matches expressions.

constexpr Variable var(Literal L)

Returns the variable of L.

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

RangeSelector name(std::string ID)

Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...

The JSON file list parser is used to communicate input to InstallAPI.

CanQual< Type > CanQualType

Represents a canonical, potentially-qualified type.

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_Complete

Complete object ctor.

bool isa(CodeGen::Address addr)

@ VisibleNone

No linkage according to the standard, but is visible from other translation units because of types de...

@ None

No linkage, which means that the entity is unique and can only be referred to from within its scope.

@ UniqueExternal

External linkage within a unique namespace.

@ Internal

Internal linkage, which indicates that the entity can be referred to from within the translation unit...

@ External

External linkage, which indicates that the entity can be referred to from other translation units.

@ Module

Module linkage, which indicates that the entity can be referred to from other translation units withi...

CXXDtorType

C++ destructor types.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

@ Type

The name was classified as a type.

U cast(CodeGen::Address addr)

@ DefaultVisibility

Objects with "default" visibility are seen by the dynamic linker and act like normal objects.

static bool addressSpace()

static bool opGlobalUnnamedAddr()

static bool vtableEmitMetadata()

static bool emitTypeMetadataCodeForVCall()

static bool opFuncReadOnly()

static bool setDLLStorageClass()

static bool hiddenVisibility()

static bool opFuncNoUnwind()

static bool cxxabiAppleARM64CXXABI()

static bool opGlobalDLLImportExport()

static bool opGlobalPartition()

static bool isTrivialCtorOrDtor()

static bool opFuncCallingConv()

static bool opFuncWillReturn()

static bool protectedVisibility()

static bool deferredVtables()

static bool cxxabiUseARMGuardVarABI()

static bool cxxabiUseARMMethodPtrABI()

static bool setDSOLocal()

static bool vtableRelativeLayout()

const clang::CXXRecordDecl * nearestVBase

clang::CharUnits getPointerAlign() const

clang::CharUnits getSizeSize() const

cir::PointerType uInt8PtrTy

Represents an element in a path from a derived class to a base class.

unsigned AddressPointIndex