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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

32#include "llvm/IR/DataLayout.h"

33#include "llvm/IR/GlobalValue.h"

34#include "llvm/IR/Instructions.h"

35#include "llvm/IR/Intrinsics.h"

36#include "llvm/IR/Value.h"

37#include "llvm/Support/ScopedPrinter.h"

38

39#include

40

41using namespace clang;

42using namespace CodeGen;

43

44namespace {

46

47 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;

48

49

51 ThreadWrappers;

52

53protected:

54 bool UseARMMethodPtrABI;

55 bool UseARMGuardVarABI;

56 bool Use32BitVTableOffsetABI;

57

60 }

61

62public:

64 bool UseARMMethodPtrABI = false,

65 bool UseARMGuardVarABI = false) :

66 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),

67 UseARMGuardVarABI(UseARMGuardVarABI),

68 Use32BitVTableOffsetABI(false) { }

69

71

73

77 }

78

80

81

82 if (isa(GD.getDecl())) {

86 return true;

87

89 return false;

90

92 llvm_unreachable("emitting dtor comdat as function?");

93 }

94 llvm_unreachable("bad dtor kind");

95 }

96 if (isa(GD.getDecl())) {

99 return true;

100

102 return false;

103

106 llvm_unreachable("closure ctors in Itanium ABI?");

107

109 llvm_unreachable("emitting ctor comdat as function?");

110 }

111 llvm_unreachable("bad dtor kind");

112 }

113

114

115 return false;

116 }

117

119

121

126 llvm::Value *&ThisPtrForCall,

127 llvm::Value *MemFnPtr,

129

130 llvm::Value *

133 llvm::Value *MemPtr,

135

138 llvm::Value *Src) override;

140 llvm::Constant *Src) override;

141

143

148 llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,

150

152 llvm::Value *L, llvm::Value *R,

154 bool Inequality) override;

155

157 llvm::Value *Addr,

159

163

166

168

169 llvm::CallInst *

171 llvm::Value *Exn) override;

172

173 void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);

177 QualType CatchHandlerType) override {

179 }

180

185 llvm::Type *StdTypeInfoPtrTy) override;

186

188 QualType SrcRecordTy) override;

189

190

191

192

193

194 bool hasUniqueVTablePointer(QualType RecordTy) {

196

197

198

199 if (!CGM.getCodeGenOpts().AssumeUniqueVTables ||

200 getContext().getLangOpts().AppleKext)

201 return false;

202

203

204

205 if (!CGM.shouldEmitRTTI())

206 return false;

207

208

209

210 if (!llvm::GlobalValue::isWeakForLinker(CGM.getVTableLinkage(RD)))

211 return true;

212

213

214

215

216

217

218 if (CGM.GetLLVMVisibility(RD->getVisibility()) !=

219 llvm::GlobalValue::DefaultVisibility)

220 return false;

221

222 return true;

223 }

224

226 return hasUniqueVTablePointer(DestRecordTy);

227 }

228

232 llvm::BasicBlock *CastEnd) override;

233

237 llvm::BasicBlock *CastSuccess,

238 llvm::BasicBlock *CastFail) override;

239

241 QualType SrcRecordTy) override;

242

244

245 llvm::Value *

249

251

252 AddedStructorArgCounts

255

258

259

260

261 return false;

262 }

263

265

268

270

274 bool ForVirtualBase,

276

280 bool ForVirtualBase,

282

287

290

292 CodeGenFunction::VPtr Vptr) override;

293

295 return true;

296 }

297

298 llvm::Constant *

301

305

306 llvm::Value *getVTableAddressPointInStructorWithVTT(

309

312

314 Address This, llvm::Type *Ty,

316

317 llvm::Value *

320 DeleteOrMemberCallExpr E,

321 llvm::CallBase **CallOrInvoke) override;

322

324

326 bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;

327

330

331

332 if (ForVTable && !Thunk->hasLocalLinkage())

333 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);

334 CGM.setGVProperties(Thunk, GD);

335 }

336

337 bool exportThunk() override { return true; }

338

342

346

349 assert(!Args.empty() && "expected the arglist to not be empty!");

350 return Args.size() - 1;

351 }

352

355 { return "__cxa_deleted_virtual"; }

356

360 llvm::Value *NumElements,

362 QualType ElementType) override;

366

368 llvm::GlobalVariable *DeclPtr,

369 bool PerformInit) override;

371 llvm::FunctionCallee dtor,

372 llvm::Constant *addr) override;

373

374 llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,

375 llvm::Value *Val);

381

385 }

388

390

391 llvm::Constant *

392 getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD);

393

394

395

396protected:

397

398

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

400

401public:

402

403 enum RTTIUniquenessKind {

404

405

406 RUK_Unique,

407

408

409

410 RUK_NonUniqueHidden,

411

412

413

414

415 RUK_NonUniqueVisible

416 };

417

418

419

420 RTTIUniquenessKind

421 classifyRTTIUniqueness(QualType CanTy,

422 llvm::GlobalValue::LinkageTypes Linkage) const;

423 friend class ItaniumRTTIBuilder;

424

426

427 std::pair<llvm::Value *, const CXXRecordDecl *>

430

431 private:

432 llvm::Constant *

433 getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);

434

435 bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {

436 const auto &VtableLayout =

437 CGM.getItaniumVTableContext().getVTableLayout(RD);

438

439 for (const auto &VtableComponent : VtableLayout.vtable_components()) {

440

441 if (!VtableComponent.isUsedFunctionPointerKind())

442 continue;

443

444 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();

446 const bool IsInlined =

448 if (!IsInlined)

449 continue;

450

451 StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());

452 auto *Entry = CGM.GetGlobalValue(Name);

453

454

455

456

457

458 if (!Entry || Entry->isDeclaration())

459 return true;

460 }

461 return false;

462 }

463

464 bool isVTableHidden(const CXXRecordDecl *RD) const {

465 const auto &VtableLayout =

466 CGM.getItaniumVTableContext().getVTableLayout(RD);

467

468 for (const auto &VtableComponent : VtableLayout.vtable_components()) {

469 if (VtableComponent.isRTTIKind()) {

470 const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();

471 if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility)

472 return true;

473 } else if (VtableComponent.isUsedFunctionPointerKind()) {

474 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();

475 if (Method->getVisibility() == Visibility::HiddenVisibility &&

477 return true;

478 }

479 }

480 return false;

481 }

482};

483

484class ARMCXXABI : public ItaniumCXXABI {

485public:

487 ItaniumCXXABI(CGM, true,

488 true) {}

489

490 bool constructorsAndDestructorsReturnThis() const override { return true; }

491

494

498 llvm::Value *NumElements,

500 QualType ElementType) override;

503};

504

505class AppleARM64CXXABI : public ARMCXXABI {

506public:

508 Use32BitVTableOffsetABI = true;

509 }

510

511

512 bool shouldRTTIBeUnique() const override { return false; }

513};

514

515class FuchsiaCXXABI final : public ItaniumCXXABI {

516public:

518 : ItaniumCXXABI(CGM) {}

519

520private:

521 bool constructorsAndDestructorsReturnThis() const override { return true; }

522};

523

524class WebAssemblyCXXABI final : public ItaniumCXXABI {

525public:

527 : ItaniumCXXABI(CGM, true,

528 true) {}

530 llvm::CallInst *

531 emitTerminateForUnexpectedException(CodeGenFunction &CGF,

532 llvm::Value *Exn) override;

533

534private:

535 bool constructorsAndDestructorsReturnThis() const override { return true; }

536 bool canCallMismatchedFunctionType() const override { return false; }

537};

538

539class XLCXXABI final : public ItaniumCXXABI {

540public:

542 : ItaniumCXXABI(CGM) {}

543

545 llvm::FunctionCallee dtor,

546 llvm::Constant *addr) override;

547

548 bool useSinitAndSterm() const override { return true; }

549

550private:

551 void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,

552 llvm::Constant *addr);

553};

554}

555

558

559

560 case TargetCXXABI::GenericARM:

561 case TargetCXXABI::iOS:

562 case TargetCXXABI::WatchOS:

563 return new ARMCXXABI(CGM);

564

565 case TargetCXXABI::AppleARM64:

566 return new AppleARM64CXXABI(CGM);

567

568 case TargetCXXABI::Fuchsia:

569 return new FuchsiaCXXABI(CGM);

570

571

572

573

574 case TargetCXXABI::GenericAArch64:

575 return new ItaniumCXXABI(CGM, true,

576 true);

577

578 case TargetCXXABI::GenericMIPS:

579 return new ItaniumCXXABI(CGM, true);

580

581 case TargetCXXABI::WebAssembly:

582 return new WebAssemblyCXXABI(CGM);

583

584 case TargetCXXABI::XL:

585 return new XLCXXABI(CGM);

586

587 case TargetCXXABI::GenericItanium:

588 return new ItaniumCXXABI(CGM);

589

590 case TargetCXXABI::Microsoft:

591 llvm_unreachable("Microsoft ABI is not Itanium-based");

592 }

593 llvm_unreachable("bad ABI kind");

594}

595

596llvm::Type *

597ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {

599 return CGM.PtrDiffTy;

600 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);

601}

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(

625 llvm::Value *&ThisPtrForCall,

628

631 auto *RD =

633

634 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);

635

636 llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");

637 llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");

638 llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");

639

640

641 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");

642

643

644 llvm::Value *Adj = RawAdj;

645 if (UseARMMethodPtrABI)

646 Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");

647

648

649

651 This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj);

652 ThisPtrForCall = This;

653

654

655 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");

656

657

658

659 llvm::Value *IsVirtual;

660 if (UseARMMethodPtrABI)

661 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);

662 else

663 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);

664 IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");

665 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);

666

667

668

669

671

672

679

680

681

682

683 llvm::Value *VTableOffset = FnAsInt;

684 if (!UseARMMethodPtrABI)

685 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);

686 if (Use32BitVTableOffsetABI) {

687 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);

688 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);

689 }

690

691

692

693 llvm::Constant *CheckSourceLocation;

694 llvm::Constant *CheckTypeDesc;

695 bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) &&

696 CGM.HasHiddenLTOVisibility(RD);

697 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&

698 CGM.HasHiddenLTOVisibility(RD);

699 bool ShouldEmitWPDInfo =

700 CGM.getCodeGenOpts().WholeProgramVTables &&

701

702 !CGM.AlwaysHasLTOVisibilityPublic(RD);

703 llvm::Value *VirtualFn = nullptr;

704

705 {

706 CodeGenFunction::SanitizerScope SanScope(&CGF);

707 llvm::Value *TypeId = nullptr;

708 llvm::Value *CheckResult = nullptr;

709

710 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {

711

712

713 llvm::Metadata *MD =

714 CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));

715 TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);

716 }

717

718 if (ShouldEmitVFEInfo) {

719 llvm::Value *VFPAddr =

720 Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);

721

722

723

724

725

726

727 llvm::Value *CheckedLoad = Builder.CreateCall(

728 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),

729 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});

730 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);

731 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);

732 } else {

733

734

735 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {

736 llvm::Value *VFPAddr =

737 Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);

738 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)

739 ? llvm::Intrinsic::type_test

740 : llvm::Intrinsic::public_type_test;

741

742 CheckResult =

743 Builder.CreateCall(CGM.getIntrinsic(IID), {VFPAddr, TypeId});

744 }

745

746 if (CGM.getItaniumVTableContext().isRelativeLayout()) {

747 VirtualFn = CGF.Builder.CreateCall(

748 CGM.getIntrinsic(llvm::Intrinsic::load_relative,

749 {VTableOffset->getType()}),

750 {VTable, VTableOffset});

751 } else {

752 llvm::Value *VFPAddr =

756 "memptr.virtualfn");

757 }

758 }

759 assert(VirtualFn && "Virtual fuction pointer not created!");

760 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||

761 CheckResult) &&

762 "Check result required but not created!");

763

764 if (ShouldEmitCFICheck) {

765

768 llvm::Constant *StaticData[] = {

769 llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),

770 CheckSourceLocation,

771 CheckTypeDesc,

772 };

773

774 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {

775 CGF.EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);

776 } else {

777 llvm::Value *AllVtables = llvm::MetadataAsValue::get(

778 CGM.getLLVMContext(),

779 llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));

780 llvm::Value *ValidVtable = Builder.CreateCall(

781 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});

782 CGF.EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIMFCall),

783 SanitizerHandler::CFICheckFail, StaticData,

784 {VTable, ValidVtable});

785 }

786

787 FnVirtual = Builder.GetInsertBlock();

788 }

789 }

790

792

793

794

796 llvm::Value *NonVirtualFn =

797 Builder.CreateIntToPtr(FnAsInt, CGF.UnqualPtrTy, "memptr.nonvirtualfn");

798

799

800 if (ShouldEmitCFICheck) {

803 CodeGenFunction::SanitizerScope SanScope(&CGF);

804

805 llvm::Constant *StaticData[] = {

806 llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall),

807 CheckSourceLocation,

808 CheckTypeDesc,

809 };

810

811 llvm::Value *Bit = Builder.getFalse();

813 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(

814 getContext().getMemberPointerType(

817 llvm::Value *TypeId =

818 llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);

819

820 llvm::Value *TypeTest =

821 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),

822 {NonVirtualFn, TypeId});

823 Bit = Builder.CreateOr(Bit, TypeTest);

824 }

825

826 CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::SO_CFIMFCall),

827 SanitizerHandler::CFICheckFail, StaticData,

828 {NonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)});

829

830 FnNonVirtual = Builder.GetInsertBlock();

831 }

832 }

833

834

836 llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.UnqualPtrTy, 2);

837 CalleePtr->addIncoming(VirtualFn, FnVirtual);

838 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);

839

841

842 if (const auto &Schema =

843 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) {

844 llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.IntPtrTy, 2);

845 DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.IntPtrTy, 0),

846 FnVirtual);

847 const auto &AuthInfo =

848 CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0));

849 assert(Schema.getKey() == AuthInfo.getKey() &&

850 "Keys for virtual and non-virtual member functions must match");

851 auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator();

852 DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual);

854 Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(),

855 Schema.authenticatesNullValues(), DiscriminatorPHI);

856 }

857

860}

861

862

863

864llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(

867 assert(MemPtr->getType() == CGM.PtrDiffTy);

868

870

871

872 return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr,

873 "memptr.offset");

874}

875

876

880 const auto *CPA = dyn_castllvm::ConstantPtrAuth(Ptr);

881

882 if (!CPA)

883 return nullptr;

884

885 assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&

886 CPA->getAddrDiscriminator()->isZeroValue() &&

888 "unexpected key or discriminators");

889

891 CPA->getPointer(), NewAuthInfo.getKey(), nullptr,

893}

894

895

896

897

898

899

900

901

902

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918llvm::Value *

919ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,

921 llvm::Value *src) {

922

923 if (isallvm::Constant(src))

924 return EmitMemberPointerConversion(E, castllvm::Constant(src));

925

926 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||

927 E->getCastKind() == CK_BaseToDerivedMemberPointer ||

928 E->getCastKind() == CK_ReinterpretMemberPointer);

929

932

934 if (const auto &NewAuthInfo =

935 CGM.getMemberFunctionPointerAuthInfo(DstType)) {

938 const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType);

939 llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0, "memptr.ptr");

940 llvm::Type *OrigTy = MemFnPtr->getType();

941

942 llvm::BasicBlock *StartBB = Builder.GetInsertBlock();

945

946

947 assert(UseARMMethodPtrABI && "ARM ABI expected");

948 llvm::Value *Adj = Builder.CreateExtractValue(src, 1, "memptr.adj");

949 llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);

950 llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1);

951 llvm::Value *IsVirtualOffset =

952 Builder.CreateIsNotNull(AndVal, "is.virtual.offset");

953 Builder.CreateCondBr(IsVirtualOffset, MergeBB, ResignBB);

954

956 llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.Int8Ty);

957 MemFnPtr = Builder.CreateIntToPtr(MemFnPtr, PtrTy);

958 MemFnPtr =

960 isallvm::Constant(src));

961 MemFnPtr = Builder.CreatePtrToInt(MemFnPtr, OrigTy);

962 llvm::Value *ResignedVal = Builder.CreateInsertValue(src, MemFnPtr, 0);

963 ResignBB = Builder.GetInsertBlock();

964

966 llvm::PHINode *NewSrc = Builder.CreatePHI(src->getType(), 2);

967 NewSrc->addIncoming(src, StartBB);

968 NewSrc->addIncoming(ResignedVal, ResignBB);

969 src = NewSrc;

970 }

971 }

972

973

974 if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;

975

976 llvm::Constant *adj = getMemberPointerAdjustment(E);

977 if (!adj) return src;

978

979 bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);

980

983

984

985

987 llvm::Value *dst;

988 if (isDerivedToBase)

989 dst = Builder.CreateNSWSub(src, adj, "adj");

990 else

991 dst = Builder.CreateNSWAdd(src, adj, "adj");

992

993

994 llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());

995 llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull");

996 return Builder.CreateSelect(isNull, src, dst);

997 }

998

999

1000 if (UseARMMethodPtrABI) {

1001 uint64_t offset = castllvm::ConstantInt(adj)->getZExtValue();

1002 offset <<= 1;

1003 adj = llvm::ConstantInt::get(adj->getType(), offset);

1004 }

1005

1006 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj");

1007 llvm::Value *dstAdj;

1008 if (isDerivedToBase)

1009 dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj");

1010 else

1011 dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj");

1012

1013 return Builder.CreateInsertValue(src, dstAdj, 1);

1014}

1015

1016static llvm::Constant *

1021 "member function pointers expected");

1022 if (DestType == SrcType)

1023 return Src;

1024

1027

1028 if (!NewAuthInfo && !CurAuthInfo)

1029 return Src;

1030

1031 llvm::Constant *MemFnPtr = Src->getAggregateElement(0u);

1032 if (MemFnPtr->getNumOperands() == 0) {

1033

1034 assert(isallvm::ConstantInt(MemFnPtr) && "constant int expected");

1035 return Src;

1036 }

1037

1039 castllvm::User(MemFnPtr)->getOperand(0), CurAuthInfo, NewAuthInfo, CGM);

1040 ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType());

1041 return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0);

1042}

1043

1044llvm::Constant *

1045ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,

1046 llvm::Constant *src) {

1047 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||

1048 E->getCastKind() == CK_BaseToDerivedMemberPointer ||

1049 E->getCastKind() == CK_ReinterpretMemberPointer);

1050

1052

1055 src, DstType, E->getSubExpr()->getType(), CGM);

1056

1057

1058 if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;

1059

1060

1061 llvm::Constant *adj = getMemberPointerAdjustment(E);

1062 if (!adj) return src;

1063

1064 bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);

1065

1068

1069

1070

1072

1073 if (src->isAllOnesValue()) return src;

1074

1075 if (isDerivedToBase)

1076 return llvm::ConstantExpr::getNSWSub(src, adj);

1077 else

1078 return llvm::ConstantExpr::getNSWAdd(src, adj);

1079 }

1080

1081

1082 if (UseARMMethodPtrABI) {

1083 uint64_t offset = castllvm::ConstantInt(adj)->getZExtValue();

1084 offset <<= 1;

1085 adj = llvm::ConstantInt::get(adj->getType(), offset);

1086 }

1087

1088 llvm::Constant *srcAdj = src->getAggregateElement(1);

1089 llvm::Constant *dstAdj;

1090 if (isDerivedToBase)

1091 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);

1092 else

1093 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);

1094

1095 llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);

1096 assert(res != nullptr && "Folding must succeed");

1097 return res;

1098}

1099

1100llvm::Constant *

1101ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {

1102

1103

1105 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, true);

1106

1107 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);

1108 llvm::Constant *Values[2] = { Zero, Zero };

1109 return llvm::ConstantStruct::getAnon(Values);

1110}

1111

1112llvm::Constant *

1113ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,

1115

1116

1117

1118 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());

1119}

1120

1121llvm::Constant *

1122ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {

1124}

1125

1126llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,

1128 assert(MD->isInstance() && "Member function must not be static!");

1129

1131

1132

1133 llvm::Constant *MemPtr[2];

1135 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);

1137 if (CGM.getItaniumVTableContext().isRelativeLayout()) {

1138

1139 VTableOffset = Index * 4;

1140 } else {

1141 const ASTContext &Context = getContext();

1144 VTableOffset = Index * PointerWidth.getQuantity();

1145 }

1146

1147 if (UseARMMethodPtrABI) {

1148

1149

1150

1151

1152

1153

1154

1155

1156

1157

1158

1159

1160

1161

1162

1163

1164

1165

1166

1167

1168

1169 const auto &Schema =

1170 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;

1171 if (Schema)

1172 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(

1173 getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy);

1174 else

1175 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);

1176

1177

1178 MemPtr[1] = llvm::ConstantInt::get(

1179 CGM.PtrDiffTy, 2 * ThisAdjustment.getQuantity() + !Schema);

1180 } else {

1181

1182

1183

1184

1185 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);

1186 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,

1188 }

1189 } else {

1191 llvm::Type *Ty;

1192

1193 if (Types.isFuncTypeConvertible(FPT)) {

1194

1195 Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));

1196 } else {

1197

1198

1199 Ty = CGM.PtrDiffTy;

1200 }

1201 llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);

1202

1203 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);

1204 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,

1205 (UseARMMethodPtrABI ? 2 : 1) *

1207 }

1208

1209 return llvm::ConstantStruct::getAnon(MemPtr);

1210}

1211

1212llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,

1216 if (!MPD)

1217 return EmitNullMemberPointer(MPT);

1218

1220

1221 if (const CXXMethodDecl *MD = dyn_cast(MPD)) {

1222 llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);

1223 QualType SrcType = getContext().getMemberPointerType(

1226 }

1227

1229 getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));

1230 return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);

1231}

1232

1233

1234

1235

1236

1237llvm::Value *

1238ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,

1239 llvm::Value *L,

1240 llvm::Value *R,

1242 bool Inequality) {

1244

1245 llvm::ICmpInst::Predicate Eq;

1246 llvm::Instruction::BinaryOps And, Or;

1247 if (Inequality) {

1248 Eq = llvm::ICmpInst::ICMP_NE;

1249 And = llvm::Instruction::Or;

1250 Or = llvm::Instruction::And;

1251 } else {

1252 Eq = llvm::ICmpInst::ICMP_EQ;

1253 And = llvm::Instruction::And;

1254 Or = llvm::Instruction::Or;

1255 }

1256

1257

1258

1260 return Builder.CreateICmp(Eq, L, R);

1261

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");

1273 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");

1274

1275

1276

1277 llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");

1278

1279

1280

1281

1282 llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());

1283 llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");

1284

1285

1286

1287 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");

1288 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");

1289 llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");

1290

1291

1292

1293 if (UseARMMethodPtrABI) {

1294 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);

1295

1296

1297 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");

1298 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);

1299 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,

1300 "cmp.or.adj");

1301 EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);

1302 }

1303

1304

1305 llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);

1306 Result = Builder.CreateBinOp(And, PtrEq, Result,

1307 Inequality ? "memptr.ne" : "memptr.eq");

1308 return Result;

1309}

1310

1311llvm::Value *

1312ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,

1313 llvm::Value *MemPtr,

1316

1317

1319 assert(MemPtr->getType() == CGM.PtrDiffTy);

1320 llvm::Value *NegativeOne =

1321 llvm::Constant::getAllOnesValue(MemPtr->getType());

1322 return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");

1323 }

1324

1325

1326 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");

1327

1328 llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);

1329 llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");

1330

1331

1332

1333 if (UseARMMethodPtrABI) {

1334 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);

1335 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");

1336 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");

1337 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,

1338 "memptr.isvirtual");

1339 Result = Builder.CreateOr(Result, IsVirtual);

1340 }

1341

1342 return Result;

1343}

1344

1345bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {

1347 if (!RD)

1348 return false;

1349

1350

1352 auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());

1354 return true;

1355 }

1356 return false;

1357}

1358

1359

1360

1361bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {

1363}

1364

1365

1366

1367void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,

1373 if (UseGlobalDelete) {

1374

1375

1376

1377

1378 auto *ClassDecl =

1381

1382

1383 llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(

1384 CGF.IntPtrTy, VTable, -2, "complete-offset.ptr");

1387

1388

1390 CompletePtr =

1392

1393

1394

1396 ElementType);

1397 }

1398

1399

1400

1402 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,

1403 nullptr);

1404

1405 if (UseGlobalDelete)

1407}

1408

1409void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {

1410

1411

1412 llvm::FunctionType *FTy =

1413 llvm::FunctionType::get(CGM.VoidTy, false);

1414

1415 llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");

1416

1417 if (isNoReturn)

1419 else

1421}

1422

1424

1425

1426 llvm::FunctionType *FTy =

1427 llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, false);

1428

1430}

1431

1433

1434

1435

1437 llvm::FunctionType *FTy =

1438 llvm::FunctionType::get(CGM.VoidTy, Args, false);

1439

1441}

1442

1445

1446 llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType());

1447 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();

1448

1451 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");

1452

1455 E->getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));

1456

1457

1458 llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,

1459 true);

1460

1461

1462

1463 llvm::Constant *Dtor = nullptr;

1466 if (Record->hasTrivialDestructor()) {

1467

1468

1469

1470 const ASTContext &Ctx = getContext();

1473

1476 Dtor = CGM.getFunctionPointer(Dtor, DtorTy);

1477 }

1478 }

1479 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);

1480

1481 llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };

1483}

1484

1486

1487

1488

1489

1490

1491 llvm::Type *Int8PtrTy = CGF.Int8PtrTy;

1493 llvm::Type *PtrDiffTy =

1495

1496 llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };

1497

1498 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);

1499

1500

1502 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);

1503 FuncAttrs.addAttribute(llvm::Attribute::WillReturn);

1504 FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());

1505 llvm::AttributeList Attrs = llvm::AttributeList::get(

1506 CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);

1507

1509}

1510

1512

1513 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);

1515}

1516

1517

1518

1522 CXXBasePaths Paths(true, true,

1523 false);

1524

1525

1526

1529

1530 unsigned NumPublicPaths = 0;

1532

1533

1535 if (Path.Access != AS_public)

1536 continue;

1537

1538 ++NumPublicPaths;

1539

1541

1542

1543 if (PathElement.Base->isVirtual())

1545

1546 if (NumPublicPaths > 1)

1547 continue;

1548

1549

1552 PathElement.Base->getType()->getAsCXXRecordDecl());

1553 }

1554 }

1555

1556

1557 if (NumPublicPaths == 0)

1559

1560

1561 if (NumPublicPaths > 1)

1563

1564

1565

1566 return Offset;

1567}

1568

1570

1571 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);

1572

1574}

1575

1576bool ItaniumCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {

1577 return true;

1578}

1579

1580void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {

1583 Call->setDoesNotReturn();

1584 CGF.Builder.CreateUnreachable();

1585}

1586

1587llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,

1590 llvm::Type *StdTypeInfoPtrTy) {

1591 auto *ClassDecl =

1593 llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,

1594 ClassDecl);

1595

1596 if (CGM.getItaniumVTableContext().isRelativeLayout()) {

1597

1599 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),

1600 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});

1601 } else {

1602

1604 CGF.Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy, Value, -1ULL);

1605 }

1608}

1609

1610bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,

1612 return SrcIsPtr;

1613}

1614

1615llvm::Value *ItaniumCXXABI::emitDynamicCastCall(

1617 QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {

1618 llvm::Type *PtrDiffLTy =

1620

1621 llvm::Value *SrcRTTI =

1623 llvm::Value *DestRTTI =

1625

1626

1629 llvm::Value *OffsetHint = llvm::ConstantInt::get(

1630 PtrDiffLTy,

1632

1633

1635 if (CGM.getCodeGenOpts().PointerAuth.CXXVTablePointers) {

1636

1637

1638

1639

1640

1641 llvm::Value *Vtable =

1642 CGF.GetVTablePtr(ThisAddr, CGM.Int8PtrTy, SrcDecl,

1643 CodeGenFunction::VTableAuthMode::MustTrap);

1644 assert(Vtable);

1645 (void)Vtable;

1646 }

1647

1648 llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};

1650

1651

1652

1654 llvm::BasicBlock *BadCastBlock =

1656

1658 CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);

1659

1661 EmitBadCastCall(CGF);

1662 }

1663

1665}

1666

1667llvm::Value *ItaniumCXXABI::emitExactDynamicCast(

1669 QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess,

1670 llvm::BasicBlock *CastFail) {

1672

1673

1676 CXXBasePaths Paths(true, true,

1677 false);

1679

1680

1681

1682 std::optional Offset;

1684

1686 continue;

1687

1690

1692 PathElement.Base->getType()->getAsCXXRecordDecl();

1693 if (PathElement.Base->isVirtual()) {

1694

1695

1698 } else {

1702 }

1703 }

1704

1705 if (!Offset)

1706 Offset = PathOffset;

1707 else if (Offset != PathOffset) {

1708

1709

1710

1711

1712 ThisAddr = Address(emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy),

1714 SrcDecl = DestDecl;

1716 break;

1717 }

1718 }

1719

1720 if (!Offset) {

1721

1723 return llvm::PoisonValue::get(CGF.VoidPtrTy);

1724 }

1725

1726

1727

1728

1729

1732 CGM.DecorateInstructionWithTBAA(

1733 VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy));

1735 VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl));

1737 if (!Offset->isZero())

1740 {llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset->getQuantity())});

1741 CGF.Builder.CreateCondBr(Success, CastSuccess, CastFail);

1742 return Result;

1743}

1744

1745llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,

1748 auto *ClassDecl =

1750 llvm::Value *OffsetToTop;

1751 if (CGM.getItaniumVTableContext().isRelativeLayout()) {

1752

1753 llvm::Value *VTable =

1755

1756

1757 OffsetToTop =

1758 CGF.Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);

1761 } else {

1762 llvm::Type *PtrDiffLTy =

1764

1765

1766 llvm::Value *VTable =

1768

1769

1770 OffsetToTop =

1771 CGF.Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);

1773 PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top");

1774 }

1775

1777 OffsetToTop);

1778}

1779

1780bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {

1783 Call->setDoesNotReturn();

1784 CGF.Builder.CreateUnreachable();

1785 return true;

1786}

1787

1788llvm::Value *

1789ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,

1793 llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);

1795 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,

1796 BaseClassDecl);

1797 llvm::Value *VBaseOffsetPtr =

1798 CGF.Builder.CreateConstGEP1_64(

1800 "vbase.offset.ptr");

1801

1802 llvm::Value *VBaseOffset;

1803 if (CGM.getItaniumVTableContext().isRelativeLayout()) {

1806 "vbase.offset");

1807 } else {

1809 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");

1810 }

1811 return VBaseOffset;

1812}

1813

1815

1816 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());

1817

1818

1819

1821

1822

1823

1824 if (D->getParent()->isAbstract()) {

1825

1827 }

1828}

1829

1831ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,

1834

1835

1836

1837

1838

1841 cast(GD.getDecl())->getParent()->getNumVBases() != 0) {

1842 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);

1844 ArgTys.insert(ArgTys.begin() + 1,

1846 return AddedStructorArgCounts::prefix(1);

1847 }

1848 return AddedStructorArgCounts{};

1849}

1850

1852

1853

1855

1856

1857

1859

1860

1861

1862

1863 if (D->isVirtual())

1865}

1866

1867void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,

1871 assert(isa(MD) || isa(MD));

1872

1873

1874 if (NeedsVTTParameter(CGF.CurGD)) {

1876

1877

1878 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);

1883 T, ImplicitParamKind::CXXVTT);

1884 Params.insert(Params.begin() + 1, VTTDecl);

1885 getStructorImplicitParamDecl(CGF) = VTTDecl;

1886 }

1887}

1888

1889void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {

1890

1892 return;

1893

1894

1895

1896 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));

1897

1898

1899 if (getStructorImplicitParamDecl(CGF)) {

1901 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), "vtt");

1902 }

1903

1904

1905

1906

1907

1908

1909

1910

1911

1912 if (HasThisReturn(CGF.CurGD))

1914}

1915

1918 bool ForVirtualBase, bool Delegating) {

1920 return AddedStructorArgs{};

1921

1922

1923

1924

1925 llvm::Value *VTT =

1927 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);

1928 QualType Q = getContext().getAddrSpaceQualType(getContext().VoidPtrTy, AS);

1929 QualType VTTTy = getContext().getPointerType(Q);

1930 return AddedStructorArgs::prefix({{VTT, VTTTy}});

1931}

1932

1933llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(

1935 bool ForVirtualBase, bool Delegating) {

1938}

1939

1940void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,

1946 llvm::Value *VTT =

1948 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);

1949

1951 if (getContext().getLangOpts().AppleKext &&

1954 else

1956

1958 ThisTy, VTT, VTTTy, nullptr);

1959}

1960

1961

1962template

1965 if (const auto *FD = dyn_cast(D)) {

1968 continue;

1970 return true;

1971 }

1972 }

1973

1974 return false;

1975}

1976

1978 llvm::GlobalVariable *VTable,

1980 if (VTable->getDLLStorageClass() !=

1981 llvm::GlobalVariable::DefaultStorageClass ||

1982 RD->hasAttr() || RD->hasAttr())

1983 return;

1984

1986 if (CXXRecordNonInlineHasAttr(RD))

1987 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);

1988 } else if (CXXRecordNonInlineHasAttr(RD))

1989 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);

1990}

1991

1992void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,

1994 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());

1995 if (VTable->hasInitializer())

1996 return;

1997

2000 llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);

2001 llvm::Constant *RTTI =

2002 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));

2003

2004

2006 auto components = builder.beginStruct();

2008 llvm::GlobalValue::isLocalLinkage(Linkage));

2009 components.finishAndSetAsInitializer(VTable);

2010

2011

2012 VTable->setLinkage(Linkage);

2013

2014 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())

2015 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));

2016

2017 if (CGM.getTarget().hasPS4DLLImportExport())

2019

2020

2021 CGM.setGVProperties(VTable, RD);

2022

2023

2024

2025

2029 isa(DC) && cast(DC)->getIdentifier() &&

2030 cast(DC)->getIdentifier()->isStr("__cxxabiv1") &&

2032 EmitFundamentalRTTIDescriptors(RD);

2033

2034

2035

2036

2037

2038

2039 if (!VTable->isDeclarationForLinker() ||

2040 CGM.getCodeGenOpts().WholeProgramVTables) {

2041 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);

2042

2043

2044

2045 if (VTable->isDeclarationForLinker()) {

2046 assert(CGM.getCodeGenOpts().WholeProgramVTables);

2047 CGM.addCompilerUsedGlobal(VTable);

2048 }

2049 }

2050

2053 if (!VTable->isDSOLocal())

2055 }

2056}

2057

2058bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(

2060 if (Vptr.NearestVBase == nullptr)

2061 return false;

2062 return NeedsVTTParameter(CGF.CurGD);

2063}

2064

2065llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(

2068

2069 if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&

2070 NeedsVTTParameter(CGF.CurGD)) {

2071 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,

2072 NearestVBase);

2073 }

2074 return getVTableAddressPoint(Base, VTableClass);

2075}

2076

2077llvm::Constant *

2080 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());

2081

2082

2083

2085 CGM.getItaniumVTableContext().getVTableLayout(VTableClass);

2088 llvm::Value *Indices[] = {

2089 llvm::ConstantInt::get(CGM.Int32Ty, 0),

2090 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),

2091 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),

2092 };

2093

2094

2095

2096 unsigned ComponentSize =

2097 CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType());

2098 unsigned VTableSize =

2100 unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;

2101 llvm::ConstantRange InRange(

2102 llvm::APInt(32, (int)-Offset, true),

2103 llvm::APInt(32, (int)(VTableSize - Offset), true));

2104 return llvm::ConstantExpr::getGetElementPtr(

2105 VTable->getValueType(), VTable, Indices, true, InRange);

2106}

2107

2108llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(

2111 assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&

2112 NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT");

2113

2114

2115 uint64_t VirtualPointerIndex =

2116 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);

2117

2118

2119 llvm::Value *VTT = CGF.LoadCXXVTT();

2120 if (VirtualPointerIndex)

2122 VirtualPointerIndex);

2123

2124

2125 llvm::Value *AP =

2128

2134 }

2135

2136 return AP;

2137}

2138

2139llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,

2141 assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");

2142

2143 llvm::GlobalVariable *&VTable = VTables[RD];

2144 if (VTable)

2145 return VTable;

2146

2147

2148 CGM.addDeferredVTable(RD);

2149

2151 llvm::raw_svector_ostream Out(Name);

2152 getMangleContext().mangleCXXVTable(RD, Out);

2153

2155 CGM.getItaniumVTableContext().getVTableLayout(RD);

2156 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);

2157

2158

2159

2160

2161 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);

2162 unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()

2163 ? 32

2164 : CGM.getTarget().getPointerAlign(AS);

2165

2166 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(

2167 Name, VTableType, llvm::GlobalValue::ExternalLinkage,

2168 getContext().toCharUnitsFromBits(PAlign).getAsAlign());

2169 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

2170

2171 if (CGM.getTarget().hasPS4DLLImportExport())

2173

2174 CGM.setGVProperties(VTable, RD);

2175 return VTable;

2176}

2177

2181 llvm::Type *Ty,

2183 llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;

2184 auto *MethodDecl = cast(GD.getDecl());

2185 llvm::Value *VTable = CGF.GetVTablePtr(This, PtrTy, MethodDecl->getParent());

2186

2187 uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);

2188 llvm::Value *VFunc, *VTableSlotPtr = nullptr;

2189 auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers;

2192 MethodDecl->getParent(), VTable, PtrTy,

2193 VTableIndex *

2194 CGM.getContext().getTargetInfo().getPointerWidth(LangAS::Default) /

2195 8);

2196 } else {

2198

2199 llvm::Value *VFuncLoad;

2200 if (CGM.getItaniumVTableContext().isRelativeLayout()) {

2201 VFuncLoad = CGF.Builder.CreateCall(

2202 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),

2203 {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});

2204 } else {

2205 VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64(

2206 PtrTy, VTable, VTableIndex, "vfn");

2209 }

2210

2211

2212

2213

2214

2215

2216

2217 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&

2218 CGM.getCodeGenOpts().StrictVTablePointers) {

2219 if (auto *VFuncLoadInstr = dyn_castllvm::Instruction(VFuncLoad)) {

2220 VFuncLoadInstr->setMetadata(

2221 llvm::LLVMContext::MD_invariant_load,

2222 llvm::MDNode::get(CGM.getLLVMContext(),

2224 }

2225 }

2226 VFunc = VFuncLoad;

2227 }

2228

2230 if (Schema) {

2231 assert(VTableSlotPtr && "virtual function pointer not set");

2232 GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());

2234 }

2237}

2238

2239llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(

2241 Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke) {

2244 assert((CE != nullptr) ^ (D != nullptr));

2245 assert(CE == nullptr || CE->arg_begin() == CE->arg_end());

2247

2250 &CGM.getTypes().arrangeCXXStructorDeclaration(GD);

2253

2255 if (CE) {

2256 ThisTy = CE->getObjectType();

2257 } else {

2258 ThisTy = D->getDestroyedType();

2259 }

2260

2262 nullptr, QualType(), nullptr, CallOrInvoke);

2263 return nullptr;

2264}

2265

2266void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {

2268 llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);

2270}

2271

2272bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(

2274

2275

2276 if (CGM.getLangOpts().AppleKext)

2277 return false;

2278

2279

2280

2281 if (isVTableHidden(RD))

2282 return false;

2283

2284 if (CGM.getCodeGenOpts().ForceEmitVTables)

2285 return true;

2286

2287

2288

2289

2290

2291

2292

2293

2294

2295

2296

2297

2298

2299

2300

2301 if (hasAnyUnusedVirtualInlineFunction(RD))

2302 return false;

2303

2304

2305

2306

2307

2309 for (const auto &B : RD->bases()) {

2310 auto *BRD = B.getType()->getAsCXXRecordDecl();

2311 assert(BRD && "no class for base specifier");

2312 if (B.isVirtual() || !BRD->isDynamicClass())

2313 continue;

2314 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))

2315 return false;

2316 }

2317 }

2318

2319 return true;

2320}

2321

2322bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {

2323 if (!canSpeculativelyEmitVTableAsBaseClass(RD))

2324 return false;

2325

2327 return false;

2328

2329

2330

2331 for (const auto &B : RD->vbases()) {

2332 auto *BRD = B.getType()->getAsCXXRecordDecl();

2333 assert(BRD && "no class for base specifier");

2334 if (!BRD->isDynamicClass())

2335 continue;

2336 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))

2337 return false;

2338 }

2339

2340 return true;

2341}

2345 int64_t NonVirtualAdjustment,

2346 int64_t VirtualAdjustment,

2347 bool IsReturnAdjustment) {

2348 if (!NonVirtualAdjustment && !VirtualAdjustment)

2350

2352

2353

2354 if (NonVirtualAdjustment && !IsReturnAdjustment) {

2357 }

2358

2359

2360 llvm::Value *ResultPtr;

2361 if (VirtualAdjustment) {

2362 llvm::Value *VTablePtr =

2364

2365 llvm::Value *Offset;

2366 llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(

2367 CGF.Int8Ty, VTablePtr, VirtualAdjustment);

2369

2370 Offset =

2373 } else {

2374 llvm::Type *PtrDiffTy =

2376

2377

2380 }

2381

2383 V.emitRawPointer(CGF), Offset);

2384 } else {

2385 ResultPtr = V.emitRawPointer(CGF);

2386 }

2387

2388

2389

2390 if (NonVirtualAdjustment && IsReturnAdjustment) {

2391 ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.Int8Ty, ResultPtr,

2392 NonVirtualAdjustment);

2393 }

2394

2395 return ResultPtr;

2396}

2397

2398llvm::Value *

2404 false);

2405}

2406

2407llvm::Value *

2413 true);

2414}

2415

2416void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,

2418 if (!isa(CGF.CurGD.getDecl()))

2419 return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);

2420

2421

2424 return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);

2425}

2426

2427

2428

2429CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {

2430

2431

2433 CGM.getContext().getPreferredTypeAlignInChars(elementType));

2434}

2435

2438 llvm::Value *NumElements,

2441 assert(requiresArrayCookie(expr));

2442

2444

2447

2448

2451 assert(CookieSize == getArrayCookieSizeImpl(ElementType));

2452

2453

2454 Address CookiePtr = NewPtr;

2455 CharUnits CookieOffset = CookieSize - SizeSize;

2456 if (!CookieOffset.isZero())

2458

2459

2461 llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr);

2462

2463

2464 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&

2465 (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||

2466 CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {

2467

2468 SI->setNoSanitizeMetadata();

2469 llvm::FunctionType *FTy =

2470 llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false);

2471 llvm::FunctionCallee F =

2472 CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie");

2474 }

2475

2476

2477

2479}

2480

2481llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,

2484

2485 Address numElementsPtr = allocPtr;

2487 if (!numElementsOffset.isZero())

2488 numElementsPtr =

2490

2493 if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)

2495

2496

2497

2498

2499

2500 llvm::FunctionType *FTy =

2502 llvm::FunctionCallee F =

2503 CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie");

2505}

2506

2507CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {

2508

2509

2510

2511

2512

2513

2514

2515

2517 CGM.getContext().getTypeAlignInChars(elementType));

2518}

2519

2522 llvm::Value *numElements,

2525 assert(requiresArrayCookie(expr));

2526

2527

2528 Address cookie = newPtr;

2529

2530

2532 llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,

2533 getContext().getTypeSizeInChars(elementType).getQuantity());

2535

2536

2539

2540

2541

2542 CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);

2544}

2545

2546llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,

2549

2550

2553

2556}

2557

2558

2559

2561 llvm::PointerType *GuardPtrTy) {

2562

2563 llvm::FunctionType *FTy =

2565 GuardPtrTy, false);

2567 FTy, "__cxa_guard_acquire",

2569 llvm::AttributeList::FunctionIndex,

2570 llvm::Attribute::NoUnwind));

2571}

2572

2574 llvm::PointerType *GuardPtrTy) {

2575

2576 llvm::FunctionType *FTy =

2577 llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, false);

2579 FTy, "__cxa_guard_release",

2581 llvm::AttributeList::FunctionIndex,

2582 llvm::Attribute::NoUnwind));

2583}

2584

2586 llvm::PointerType *GuardPtrTy) {

2587

2588 llvm::FunctionType *FTy =

2589 llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, false);

2591 FTy, "__cxa_guard_abort",

2593 llvm::AttributeList::FunctionIndex,

2594 llvm::Attribute::NoUnwind));

2595}

2596

2597namespace {

2599 llvm::GlobalVariable *Guard;

2600 CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}

2601

2604 Guard);

2605 }

2606 };

2607}

2608

2609

2610

2611void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,

2613 llvm::GlobalVariable *var,

2614 bool shouldPerformInit) {

2616

2617

2618

2619 bool NonTemplateInline =

2620 D.isInline() &&

2622

2623

2624

2625

2626 bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&

2627 (D.isLocalVarDecl() || NonTemplateInline) &&

2628 D.getTLSKind();

2629

2630

2631

2632 bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage();

2633

2634 llvm::IntegerType *guardTy;

2636 if (useInt8GuardVariable) {

2637 guardTy = CGF.Int8Ty;

2639 } else {

2640

2641

2642 if (UseARMGuardVarABI) {

2643 guardTy = CGF.SizeTy;

2645 } else {

2647 guardAlignment =

2649 }

2650 }

2651 llvm::PointerType *guardPtrTy = llvm::PointerType::get(

2654

2655

2656

2657 llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);

2658 if (!guard) {

2659

2661 {

2662 llvm::raw_svector_ostream out(guardName);

2663 getMangleContext().mangleStaticGuardVariable(&D, out);

2664 }

2665

2666

2667

2668

2669 guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,

2670 false, var->getLinkage(),

2671 llvm::ConstantInt::get(guardTy, 0),

2672 guardName.str());

2673 guard->setDSOLocal(var->isDSOLocal());

2674 guard->setVisibility(var->getVisibility());

2675 guard->setDLLStorageClass(var->getDLLStorageClass());

2676

2677 guard->setThreadLocalMode(var->getThreadLocalMode());

2678 guard->setAlignment(guardAlignment.getAsAlign());

2679

2680

2681

2682

2683 llvm::Comdat *C = var->getComdat();

2684 if (D.isLocalVarDecl() && C &&

2685 (CGM.getTarget().getTriple().isOSBinFormatELF() ||

2686 CGM.getTarget().getTriple().isOSBinFormatWasm())) {

2687 guard->setComdat(C);

2688 } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {

2689 guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));

2690 }

2691

2692 CGM.setStaticLocalDeclGuardAddress(&D, guard);

2693 }

2694

2695 Address guardAddr = Address(guard, guard->getValueType(), guardAlignment);

2696

2697

2698

2699

2700

2701

2702

2703

2704

2705

2706

2707

2708

2709

2710

2711

2712

2713

2714

2715

2716

2717

2719 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");

2720 if (!threadsafe || MaxInlineWidthInBits) {

2721

2722 llvm::LoadInst *LI =

2723 Builder.CreateLoad(guardAddr.withElementType(CGM.Int8Ty));

2724

2725

2726

2727

2728

2729

2730

2731 if (threadsafe)

2732 LI->setAtomic(llvm::AtomicOrdering::Acquire);

2733

2734

2735

2736

2737

2738

2739

2740

2741

2742

2743

2744

2745

2746

2747

2748

2749

2750

2751

2752

2753

2754 llvm::Value *V =

2755 (UseARMGuardVarABI && !useInt8GuardVariable)

2756 ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))

2757 : LI;

2758 llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");

2759

2760 llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");

2761

2762

2764 CodeGenFunction::GuardKind::VariableGuard, &D);

2765

2767 }

2768

2769

2770

2771

2772

2773

2774

2775

2776

2777

2778

2779

2780

2781

2782

2783

2784

2785 if (threadsafe) {

2786

2787 llvm::Value *V

2789

2791

2792 Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),

2793 InitBlock, EndBlock);

2794

2795

2797

2799 } else if (D.isLocalVarDecl()) {

2800

2801

2802

2803 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),

2805 }

2806

2807

2809

2810 if (threadsafe) {

2811

2813

2814

2817 } else if (D.isLocalVarDecl()) {

2818

2819

2820

2821 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),

2823 }

2824

2826}

2827

2828

2830 llvm::FunctionCallee dtor,

2831 llvm::Constant *addr, bool TLS) {

2833 "unexpected call to emitGlobalDtorWithCXAAtExit");

2835 "__cxa_atexit is disabled");

2836 const char *Name = "__cxa_atexit";

2837 if (TLS) {

2839 Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";

2840 }

2841

2842

2843

2845

2846

2847 auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;

2848 auto AddrPtrTy = AddrAS ? llvm::PointerType::get(CGF.getLLVMContext(), AddrAS)

2850

2851

2852 llvm::Constant *handle =

2854 auto *GV = castllvm::GlobalValue(handle->stripPointerCasts());

2855 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);

2856

2857

2858 llvm::Type *paramTys[] = {dtorTy, AddrPtrTy, handle->getType()};

2859 llvm::FunctionType *atexitTy =

2860 llvm::FunctionType::get(CGF.IntTy, paramTys, false);

2861

2862

2864 if (llvm::Function *fn = dyn_castllvm::Function(atexit.getCallee()))

2865 fn->setDoesNotThrow();

2866

2869 false, false));

2872 llvm::Constant *dtorCallee = castllvm::Constant(dtor.getCallee());

2874

2875 if (!addr)

2876

2877

2878

2879

2880 addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);

2881

2882 llvm::Value *args[] = {dtorCallee, addr, handle};

2884}

2885

2887 StringRef FnName) {

2888

2889

2890 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);

2893

2894 return GlobalInitOrCleanupFn;

2895}

2896

2897void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {

2898 for (const auto &I : DtorsUsingAtExit) {

2900 std::string GlobalCleanupFnName =

2901 std::string("__GLOBAL_cleanup_") + llvm::to_string(Priority);

2902

2903 llvm::Function *GlobalCleanupFn =

2905

2911

2912

2913 llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.VoidTy, false);

2914

2915

2916

2917 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;

2918 auto itv = Dtors.rbegin();

2919 while (itv != Dtors.rend()) {

2920 llvm::Function *Dtor = *itv;

2921

2922

2923

2925 llvm::Value *NeedsDestruct =

2927

2928 llvm::BasicBlock *DestructCallBlock =

2931 (itv + 1) != Dtors.rend() ? "unatexit.call" : "destruct.end");

2932

2933

2934 CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);

2935

2936 CGF.EmitBlock(DestructCallBlock);

2937

2938

2939 llvm::CallInst *CI = CGF.Builder.CreateCall(dtorFuncTy, Dtor);

2940

2941 CI->setCallingConv(Dtor->getCallingConv());

2942

2944

2945 itv++;

2946 }

2947

2950 }

2951}

2952

2953void CodeGenModule::registerGlobalDtorsWithAtExit() {

2954 for (const auto &I : DtorsUsingAtExit) {

2956 std::string GlobalInitFnName =

2957 std::string("__GLOBAL_init_") + llvm::to_string(Priority);

2958 llvm::Function *GlobalInitFn =

2960

2966

2967

2968

2969

2970

2971

2972 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;

2973 for (auto *Dtor : Dtors) {

2974

2975

2978 } else {

2979

2980

2982 }

2983 }

2984

2987 }

2988

2989 if (getCXXABI().useSinitAndSterm())

2990 unregisterGlobalDtorsWithUnAtExit();

2991}

2992

2993

2995 llvm::FunctionCallee dtor,

2996 llvm::Constant *addr) {

2997 if (D.isNoDestroy(CGM.getContext()))

2998 return;

2999

3000

3001 if (CGM.getLangOpts().HLSL)

3002 return CGM.AddCXXDtorEntry(dtor, addr);

3003

3004

3005

3006

3007

3008

3009 if (!CGM.getLangOpts().hasAtExit() && D.isStaticLocal())

3011

3012

3013

3014

3015

3016 if (CGM.getCodeGenOpts().CXAAtExit || D.getTLSKind())

3018

3019

3020

3021 if (CGM.getLangOpts().AppleKext) {

3022

3023 return CGM.AddCXXDtorEntry(dtor, addr);

3024 }

3025

3027}

3028

3031 assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!");

3032

3033

3036}

3037

3038

3039

3040

3041static llvm::GlobalValue::LinkageTypes

3043 llvm::GlobalValue::LinkageTypes VarLinkage =

3045

3046

3047 if (llvm::GlobalValue::isLocalLinkage(VarLinkage))

3048 return VarLinkage;

3049

3050

3052 if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&

3053 !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))

3054 return VarLinkage;

3055 return llvm::GlobalValue::WeakODRLinkage;

3056}

3057

3058llvm::Function *

3059ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,

3060 llvm::Value *Val) {

3061

3063 {

3064 llvm::raw_svector_ostream Out(WrapperName);

3065 getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);

3066 }

3067

3068

3069

3070 if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName))

3071 return castllvm::Function(V);

3072

3076

3077 const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(

3079

3080 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);

3081 llvm::Function *Wrapper =

3083 WrapperName.str(), &CGM.getModule());

3084

3085 if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())

3086 Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));

3087

3088 CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper, false);

3089

3090

3091 if (!Wrapper->hasLocalLinkage())

3093 llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||

3094 llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||

3096 Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);

3097

3099 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);

3100 Wrapper->addFnAttr(llvm::Attribute::NoUnwind);

3101 }

3102

3103 ThreadWrappers.push_back({VD, Wrapper});

3104 return Wrapper;

3105}

3106

3107void ItaniumCXXABI::EmitThreadLocalInitFuncs(

3111 llvm::Function *InitFunc = nullptr;

3112

3113

3114

3116 llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;

3117 for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {

3120 UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =

3121 CXXThreadLocalInits[I];

3122 else

3123 OrderedInits.push_back(CXXThreadLocalInits[I]);

3124 }

3125

3126 if (!OrderedInits.empty()) {

3127

3128 llvm::FunctionType *FTy =

3129 llvm::FunctionType::get(CGM.VoidTy, false);

3133 true);

3134 llvm::GlobalVariable *Guard = new llvm::GlobalVariable(

3136 llvm::GlobalVariable::InternalLinkage,

3137 llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");

3138 Guard->setThreadLocal(true);

3140

3142 Guard->setAlignment(GuardAlign.getAsAlign());

3143

3146

3148 InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);

3149 InitFunc->addFnAttr(llvm::Attribute::NoUnwind);

3150 }

3151 }

3152

3153

3154

3155 for (const VarDecl *VD : CXXThreadLocals) {

3159 getOrCreateThreadLocalWrapper(VD, GV);

3160 }

3161 }

3162

3163

3164 for (auto VDAndWrapper : ThreadWrappers) {

3165 const VarDecl *VD = VDAndWrapper.first;

3166 llvm::GlobalVariable *Var =

3168 llvm::Function *Wrapper = VDAndWrapper.second;

3169

3170

3171

3172

3175 Wrapper->setLinkage(llvm::Function::ExternalLinkage);

3176 continue;

3177 }

3178

3179

3180

3181 if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)

3182 Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);

3183 }

3184

3186

3187

3189 {

3190 llvm::raw_svector_ostream Out(InitFnName);

3191 getMangleContext().mangleItaniumThreadLocalInit(VD, Out);

3192 }

3193

3194 llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.VoidTy, false);

3195

3196

3197

3198

3199 llvm::GlobalValue *Init = nullptr;

3200 bool InitIsInitFunc = false;

3201 bool HasConstantInitialization = false;

3202 if (!usesThreadWrapperFunction(VD)) {

3203 HasConstantInitialization = true;

3205 InitIsInitFunc = true;

3206 llvm::Function *InitFuncToUse = InitFunc;

3208 InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl());

3209 if (InitFuncToUse)

3210 Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),

3211 InitFuncToUse);

3212 } else {

3213

3214

3215

3216

3217 Init = llvm::Function::Create(InitFnTy,

3218 llvm::GlobalVariable::ExternalWeakLinkage,

3219 InitFnName.str(), &CGM.getModule());

3222 GlobalDecl(), FI, castllvm::Function(Init), false);

3223 }

3224

3226 Init->setVisibility(Var->getVisibility());

3227

3228 if (!CGM.getTriple().isOSWindows() || Init->hasExternalWeakLinkage())

3229 Init->setDSOLocal(Var->isDSOLocal());

3230 }

3231

3232 llvm::LLVMContext &Context = CGM.getModule().getContext();

3233

3234

3235

3236

3237

3238

3240 isEmittedWithConstantInitializer(VD, true) &&

3241 !mayNeedDestruction(VD)) {

3242

3243

3244

3245

3246 assert(Init == nullptr && "Expected Init to be null.");

3247

3248 llvm::Function *Func = llvm::Function::Create(

3249 InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.getModule());

3252 castllvm::Function(Func),

3253 false);

3254

3255 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Func);

3257 Builder.CreateRetVoid();

3258 }

3259

3260 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);

3262 if (HasConstantInitialization) {

3263

3264 } else if (InitIsInitFunc) {

3266 llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);

3268 CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);

3269 llvm::Function *Fn =

3270 castllvm::Function(castllvm::GlobalAlias(Init)->getAliasee());

3271 Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);

3272 }

3273 }

3274 } else if (CGM.getTriple().isOSAIX()) {

3275

3276

3277

3278

3279

3280

3281

3282 Builder.CreateCall(InitFnTy, Init);

3283 } else {

3284

3285 llvm::Value *Have = Builder.CreateIsNotNull(Init);

3286 llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper);

3287 llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper);

3288 Builder.CreateCondBr(Have, InitBB, ExitBB);

3289

3290 Builder.SetInsertPoint(InitBB);

3291 Builder.CreateCall(InitFnTy, Init);

3292 Builder.CreateBr(ExitBB);

3293

3294 Builder.SetInsertPoint(ExitBB);

3295 }

3296

3297

3298

3299 llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);

3300

3303 Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);

3304 }

3305 Val = Builder.CreateAddrSpaceCast(Val, Wrapper->getReturnType());

3306

3307 Builder.CreateRet(Val);

3308 }

3309}

3310

3315 llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);

3316

3317 llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);

3318 CallVal->setCallingConv(Wrapper->getCallingConv());

3319

3323 else

3326

3327 return LV;

3328}

3329

3330

3331

3332bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {

3334

3335

3337 return false;

3338

3339

3341 return true;

3342

3343

3345 return true;

3346

3347 return false;

3348}

3349

3350llvm::Constant *

3351ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {

3353 llvm::raw_svector_ostream Out(MethodName);

3354 getMangleContext().mangleCXXName(MD, Out);

3355 MethodName += "_vfpthunk_";

3356 StringRef ThunkName = MethodName.str();

3357 llvm::Function *ThunkFn;

3358 if ((ThunkFn = cast_or_nullllvm::Function(

3359 CGM.getModule().getNamedValue(ThunkName))))

3360 return ThunkFn;

3361

3364 llvm::GlobalValue::LinkageTypes Linkage =

3366 : llvm::GlobalValue::InternalLinkage;

3367 ThunkFn =

3368 llvm::Function::Create(ThunkTy, Linkage, ThunkName, &CGM.getModule());

3369 if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)

3370 ThunkFn->setVisibility(llvm::GlobalValue::HiddenVisibility);

3371 assert(ThunkFn->getName() == ThunkName && "name was uniqued!");

3372

3375

3376

3377 ThunkFn->removeFnAttr(llvm::Attribute::StackProtect);

3378 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectStrong);

3379 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectReq);

3380

3381

3385

3386

3389

3392 llvm::Value *ThisVal = loadIncomingCXXThis(CGF);

3393 setCXXABIThisValue(CGF, ThisVal);

3394

3396 for (const VarDecl *VD : FunctionArgs)

3398

3404 getThisAddress(CGF), ThunkTy);

3405 llvm::CallBase *CallOrInvoke;

3408 auto *Call = castllvm::CallInst(CallOrInvoke);

3409 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);

3410 if (Call->getType()->isVoidTy())

3411 CGF.Builder.CreateRetVoid();

3412 else

3414

3415

3416

3419 return ThunkFn;

3420}

3421

3422namespace {

3423class ItaniumRTTIBuilder {

3425 llvm::LLVMContext &VMContext;

3426 const ItaniumCXXABI &CXXABI;

3427

3428

3430

3431

3432 llvm::GlobalVariable *

3433 GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);

3434

3435

3436

3437 llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);

3438

3439

3440 void BuildVTablePointer(const Type *Ty, llvm::Constant *StorageAddress);

3441

3442

3443

3444 void BuildSIClassTypeInfo(const CXXRecordDecl *RD);

3445

3446

3447

3448

3449 void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);

3450

3451

3452

3453 void BuildPointerTypeInfo(QualType PointeeTy);

3454

3455

3456

3457 void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);

3458

3459

3460

3462

3463public:

3464 ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)

3465 : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}

3466

3467

3468 enum {

3469

3470 PTI_Const = 0x1,

3471

3472

3473 PTI_Volatile = 0x2,

3474

3475

3476 PTI_Restrict = 0x4,

3477

3478

3479 PTI_Incomplete = 0x8,

3480

3481

3482

3483 PTI_ContainingClassIncomplete = 0x10,

3484

3485

3486

3487

3488

3489 PTI_Noexcept = 0x40,

3490 };

3491

3492

3493 enum {

3494

3495 VMI_NonDiamondRepeat = 0x1,

3496

3497

3498 VMI_DiamondShaped = 0x2

3499 };

3500

3501

3502 enum {

3503

3504 BCTI_Virtual = 0x1,

3505

3506

3507 BCTI_Public = 0x2

3508 };

3509

3510

3511

3512 llvm::Constant *BuildTypeInfo(QualType Ty);

3513

3514

3515 llvm::Constant *BuildTypeInfo(

3517 llvm::GlobalVariable::LinkageTypes Linkage,

3518 llvm::GlobalValue::VisibilityTypes Visibility,

3519 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);

3520};

3521}

3522

3523llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(

3524 QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {

3526 llvm::raw_svector_ostream Out(Name);

3528

3529

3530

3531

3532 llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,

3533 Name.substr(4));

3535

3538

3539 GV->setInitializer(Init);

3540

3541 return GV;

3542}

3543

3544llvm::Constant *

3545ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {

3546

3548 llvm::raw_svector_ostream Out(Name);

3550

3551

3552 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);

3553

3554 if (!GV) {

3555

3556

3557

3558

3559 GV = new llvm::GlobalVariable(

3561 true, llvm::GlobalValue::ExternalLinkage, nullptr, Name);

3564

3565

3567 if (RD && CXXRecordNonInlineHasAttr(RD)) {

3568 GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);

3570 }

3571 }

3572 }

3573

3574 return GV;

3575}

3576

3577

3578

3580

3581

3582

3583

3584

3585

3586

3587

3588

3589

3590

3591

3592

3593

3594 switch (Ty->getKind()) {

3595 case BuiltinType::Void:

3596 case BuiltinType::NullPtr:

3597 case BuiltinType::Bool:

3598 case BuiltinType::WChar_S:

3599 case BuiltinType::WChar_U:

3600 case BuiltinType::Char_U:

3601 case BuiltinType::Char_S:

3602 case BuiltinType::UChar:

3603 case BuiltinType::SChar:

3604 case BuiltinType::Short:

3605 case BuiltinType::UShort:

3606 case BuiltinType::Int:

3607 case BuiltinType::UInt:

3608 case BuiltinType::Long:

3609 case BuiltinType::ULong:

3610 case BuiltinType::LongLong:

3611 case BuiltinType::ULongLong:

3612 case BuiltinType::Half:

3613 case BuiltinType::Float:

3614 case BuiltinType::Double:

3615 case BuiltinType::LongDouble:

3616 case BuiltinType::Float16:

3617 case BuiltinType::Float128:

3618 case BuiltinType::Ibm128:

3619 case BuiltinType::Char8:

3620 case BuiltinType::Char16:

3621 case BuiltinType::Char32:

3622 case BuiltinType::Int128:

3623 case BuiltinType::UInt128:

3624 return true;

3625

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

3627 case BuiltinType::Id:

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

3629#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \

3630 case BuiltinType::Id:

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

3632 case BuiltinType::OCLSampler:

3633 case BuiltinType::OCLEvent:

3634 case BuiltinType::OCLClkEvent:

3635 case BuiltinType::OCLQueue:

3636 case BuiltinType::OCLReserveID:

3637#define SVE_TYPE(Name, Id, SingletonId) \

3638 case BuiltinType::Id:

3639#include "clang/Basic/AArch64SVEACLETypes.def"

3640#define PPC_VECTOR_TYPE(Name, Id, Size) \

3641 case BuiltinType::Id:

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

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

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

3645#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:

3646#include "clang/Basic/WebAssemblyReferenceTypes.def"

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

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

3649#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:

3650#include "clang/Basic/HLSLIntangibleTypes.def"

3651 case BuiltinType::ShortAccum:

3652 case BuiltinType::Accum:

3653 case BuiltinType::LongAccum:

3654 case BuiltinType::UShortAccum:

3655 case BuiltinType::UAccum:

3656 case BuiltinType::ULongAccum:

3657 case BuiltinType::ShortFract:

3658 case BuiltinType::Fract:

3659 case BuiltinType::LongFract:

3660 case BuiltinType::UShortFract:

3661 case BuiltinType::UFract:

3662 case BuiltinType::ULongFract:

3663 case BuiltinType::SatShortAccum:

3664 case BuiltinType::SatAccum:

3665 case BuiltinType::SatLongAccum:

3666 case BuiltinType::SatUShortAccum:

3667 case BuiltinType::SatUAccum:

3668 case BuiltinType::SatULongAccum:

3669 case BuiltinType::SatShortFract:

3670 case BuiltinType::SatFract:

3671 case BuiltinType::SatLongFract:

3672 case BuiltinType::SatUShortFract:

3673 case BuiltinType::SatUFract:

3674 case BuiltinType::SatULongFract:

3675 case BuiltinType::BFloat16:

3676 return false;

3677

3678 case BuiltinType::Dependent:

3679#define BUILTIN_TYPE(Id, SingletonId)

3680#define PLACEHOLDER_TYPE(Id, SingletonId) \

3681 case BuiltinType::Id:

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

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

3684

3685 case BuiltinType::ObjCId:

3686 case BuiltinType::ObjCClass:

3687 case BuiltinType::ObjCSel:

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

3689 }

3690

3691 llvm_unreachable("Invalid BuiltinType Kind!");

3692}

3693

3696 const BuiltinType *BuiltinTy = dyn_cast(PointeeTy);

3697 if (!BuiltinTy)

3698 return false;

3699

3700

3703

3704 if (!Quals.empty())

3705 return false;

3706

3708}

3709

3710

3711

3713

3714 if (const BuiltinType *BuiltinTy = dyn_cast(Ty))

3716

3717

3718

3719 if (const PointerType *PointerTy = dyn_cast(Ty))

3721

3722 return false;

3723}

3724

3725

3726

3727

3728

3732

3733

3734

3735 if (!Context.getLangOpts().RTTI) return false;

3736

3737 if (const RecordType *RecordTy = dyn_cast(Ty)) {

3738 const CXXRecordDecl *RD = cast(RecordTy->getDecl());

3740 return false;

3741

3743 return false;

3744

3745

3746

3747

3748

3749 bool IsDLLImport = RD->hasAttr();

3750

3751

3752 if (CGM.getTriple().isWindowsGNUEnvironment())

3753 return false;

3754

3757 return true;

3758

3759 return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()

3761 : true;

3762 }

3763 if (IsDLLImport)

3764 return true;

3765 }

3766

3767 return false;

3768}

3769

3770

3773}

3774

3775

3776

3777

3778

3779

3780

3781

3782

3783

3784

3785

3787 if (const RecordType *RecordTy = dyn_cast(Ty)) {

3789 return true;

3790 }

3791

3792 if (const PointerType *PointerTy = dyn_cast(Ty))

3794

3796 dyn_cast(Ty)) {

3797

3798 const RecordType *ClassType = cast(MemberPointerTy->getClass());

3800 return true;

3801

3803 }

3804

3805 return false;

3806}

3807

3808

3809

3810

3812

3814 return false;

3815

3816

3818

3819

3820 if (Base->isVirtual())

3821 return false;

3822

3823

3825 return false;

3826

3827

3828 auto *BaseDecl =

3830 if (!BaseDecl->isEmpty() &&

3832 return false;

3833

3834 return true;

3835}

3836

3837void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,

3838 llvm::Constant *StorageAddress) {

3839

3840 static const char * const ClassTypeInfo =

3841 "_ZTVN10__cxxabiv117__class_type_infoE";

3842

3843 static const char * const SIClassTypeInfo =

3844 "_ZTVN10__cxxabiv120__si_class_type_infoE";

3845

3846 static const char * const VMIClassTypeInfo =

3847 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";

3848

3849 const char *VTableName = nullptr;

3850

3852#define TYPE(Class, Base)

3853#define ABSTRACT_TYPE(Class, Base)

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

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

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

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

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

3859

3860 case Type::LValueReference:

3861 case Type::RValueReference:

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

3863

3864 case Type::Auto:

3865 case Type::DeducedTemplateSpecialization:

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

3867

3868 case Type::Pipe:

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

3870

3871 case Type::ArrayParameter:

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

3873

3874 case Type::Builtin:

3875 case Type::BitInt:

3876

3877 case Type::Vector:

3878 case Type::ExtVector:

3879 case Type::ConstantMatrix:

3880 case Type::Complex:

3881 case Type::Atomic:

3882

3883 case Type::BlockPointer:

3884

3885 VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";

3886 break;

3887

3888 case Type::ConstantArray:

3889 case Type::IncompleteArray:

3890 case Type::VariableArray:

3891

3892 VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";

3893 break;

3894

3895 case Type::FunctionNoProto:

3896 case Type::FunctionProto:

3897

3898 VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";

3899 break;

3900

3901 case Type::Enum:

3902

3903 VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";

3904 break;

3905

3906 case Type::Record: {

3908 cast(cast(Ty)->getDecl());

3909

3911 VTableName = ClassTypeInfo;

3913 VTableName = SIClassTypeInfo;

3914 } else {

3915 VTableName = VMIClassTypeInfo;

3916 }

3917

3918 break;

3919 }

3920

3921 case Type::ObjCObject:

3922

3923 Ty = cast(Ty)->getBaseType().getTypePtr();

3924

3925

3926 if (isa(Ty)) {

3927 VTableName = ClassTypeInfo;

3928 break;

3929 }

3930

3931 assert(isa(Ty));

3932 [[fallthrough]];

3933

3934 case Type::ObjCInterface:

3935 if (cast(Ty)->getDecl()->getSuperClass()) {

3936 VTableName = SIClassTypeInfo;

3937 } else {

3938 VTableName = ClassTypeInfo;

3939 }

3940 break;

3941

3942 case Type::ObjCObjectPointer:

3943 case Type::Pointer:

3944

3945 VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";

3946 break;

3947

3948 case Type::MemberPointer:

3949

3950 VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";

3951 break;

3952

3953 case Type::HLSLAttributedResource:

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

3955 }

3956

3957 llvm::Constant *VTable = nullptr;

3958

3959

3961 VTable = CGM.getModule().getNamedAlias(VTableName);

3962 if (!VTable) {

3963 llvm::Type *Ty = llvm::ArrayType::get(CGM.GlobalsInt8PtrTy, 0);

3964 VTable = CGM.getModule().getOrInsertGlobal(VTableName, Ty);

3965 }

3966

3967 CGM.setDSOLocal(castllvm::GlobalValue(VTable->stripPointerCasts()));

3968

3969 llvm::Type *PtrDiffTy =

3971

3972

3974

3975

3976 llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);

3977 VTable =

3978 llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);

3979 } else {

3980 llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);

3981 VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.GlobalsInt8PtrTy,

3982 VTable, Two);

3983 }

3984

3985 if (const auto &Schema =

3988 VTable, Schema,

3989 Schema.isAddressDiscriminated() ? StorageAddress : nullptr,

3991

3992 Fields.push_back(VTable);

3993}

3994

3995

3996

3999

4000

4001

4002

4003

4004

4005

4006

4007

4009 return llvm::GlobalValue::InternalLinkage;

4010

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

4014

4018 return llvm::GlobalValue::InternalLinkage;

4019

4023

4024

4026 return llvm::GlobalValue::LinkOnceODRLinkage;

4027

4030 if (RD->hasAttr())

4031 return llvm::GlobalValue::WeakODRLinkage;

4032 if (CGM.getTriple().isWindowsItaniumEnvironment())

4033 if (RD->hasAttr() &&

4035 return llvm::GlobalValue::ExternalLinkage;

4036

4041 .isWindowsGNUEnvironment())

4043 }

4044

4045 return llvm::GlobalValue::LinkOnceODRLinkage;

4046 }

4047

4048 llvm_unreachable("Invalid linkage!");

4049}

4050

4051llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {

4052

4054

4055

4057 llvm::raw_svector_ostream Out(Name);

4059

4060 llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);

4061 if (OldGV && !OldGV->isDeclaration()) {

4062 assert(!OldGV->hasAvailableExternallyLinkage() &&

4063 "available_externally typeinfos not yet implemented");

4064

4065 return OldGV;

4066 }

4067

4068

4071 return GetAddrOfExternalRTTIDescriptor(Ty);

4072

4073

4075

4076

4077

4078 llvm::GlobalValue::VisibilityTypes llvmVisibility;

4079 if (llvm::GlobalValue::isLocalLinkage(Linkage))

4080

4081 llvmVisibility = llvm::GlobalValue::DefaultVisibility;

4082 else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) ==

4083 ItaniumCXXABI::RUK_NonUniqueHidden)

4084 llvmVisibility = llvm::GlobalValue::HiddenVisibility;

4085 else

4087

4088 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =

4089 llvm::GlobalValue::DefaultStorageClass;

4091 if ((CGM.getTriple().isWindowsItaniumEnvironment() &&

4092 RD->hasAttr()) ||

4094 !llvm::GlobalValue::isLocalLinkage(Linkage) &&

4095 llvmVisibility == llvm::GlobalValue::DefaultVisibility))

4096 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;

4097 }

4098 return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass);

4099}

4100

4101llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(

4103 llvm::GlobalVariable::LinkageTypes Linkage,

4104 llvm::GlobalValue::VisibilityTypes Visibility,

4105 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {

4107 llvm::raw_svector_ostream Out(Name);

4109 llvm::Module &M = CGM.getModule();

4110 llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);

4111

4112 llvm::GlobalVariable *GV =

4113 new llvm::GlobalVariable(M, CGM.Int8Ty, true, Linkage,

4114 nullptr, Name);

4115

4116

4117 BuildVTablePointer(cast(Ty), GV);

4118

4119

4120 llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);

4121 llvm::Constant *TypeNameField;

4122

4123

4124

4125 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =

4127 if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {

4128

4129

4130 TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty);

4131 llvm::Constant *flag =

4132 llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);

4133 TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);

4134 TypeNameField =

4135 llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.GlobalsInt8PtrTy);

4136 } else {

4138 }

4139 Fields.push_back(TypeNameField);

4140

4142#define TYPE(Class, Base)

4143#define ABSTRACT_TYPE(Class, Base)

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

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

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

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

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

4149

4150

4151 case Type::Builtin:

4152 case Type::Vector:

4153 case Type::ExtVector:

4154 case Type::ConstantMatrix:

4155 case Type::Complex:

4156 case Type::BlockPointer:

4157

4158

4159 break;

4160

4161 case Type::LValueReference:

4162 case Type::RValueReference:

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

4164

4165 case Type::Auto:

4166 case Type::DeducedTemplateSpecialization:

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

4168

4169 case Type::Pipe:

4170 break;

4171

4172 case Type::BitInt:

4173 break;

4174

4175 case Type::ConstantArray:

4176 case Type::IncompleteArray:

4177 case Type::VariableArray:

4178 case Type::ArrayParameter:

4179

4180

4181 break;

4182

4183 case Type::FunctionNoProto:

4184 case Type::FunctionProto:

4185

4186

4187 break;

4188

4189 case Type::Enum:

4190

4191

4192 break;

4193

4194 case Type::Record: {

4196 cast(cast(Ty)->getDecl());

4198

4199 break;

4200 }

4201

4203 BuildSIClassTypeInfo(RD);

4204 else

4205 BuildVMIClassTypeInfo(RD);

4206

4207 break;

4208 }

4209

4210 case Type::ObjCObject:

4211 case Type::ObjCInterface:

4212 BuildObjCObjectTypeInfo(cast(Ty));

4213 break;

4214

4215 case Type::ObjCObjectPointer:

4216 BuildPointerTypeInfo(cast(Ty)->getPointeeType());

4217 break;

4218

4219 case Type::Pointer:

4220 BuildPointerTypeInfo(cast(Ty)->getPointeeType());

4221 break;

4222

4223 case Type::MemberPointer:

4224 BuildPointerToMemberTypeInfo(cast(Ty));

4225 break;

4226

4227 case Type::Atomic:

4228

4229 break;

4230

4231 case Type::HLSLAttributedResource:

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

4233 }

4234

4235 GV->replaceInitializer(llvm::ConstantStruct::getAnon(Fields));

4236

4237

4238 auto GVDLLStorageClass = DLLStorageClass;

4240 GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) {

4241 if (const RecordType *RecordTy = dyn_cast(Ty)) {

4242 const CXXRecordDecl *RD = cast(RecordTy->getDecl());

4243 if (RD->hasAttr() ||

4244 CXXRecordNonInlineHasAttr(RD))

4245 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;

4246 }

4247 }

4248

4249

4250 if (OldGV) {

4251 GV->takeName(OldGV);

4252 OldGV->replaceAllUsesWith(GV);

4253 OldGV->eraseFromParent();

4254 }

4255

4257 GV->setComdat(M.getOrInsertComdat(GV->getName()));

4258

4261 GV->setAlignment(Align.getAsAlign());

4262

4263

4264

4265

4266

4267

4268

4269

4270

4271

4272

4273

4274

4275

4276

4277

4280

4283

4284 TypeName->setDLLStorageClass(DLLStorageClass);

4285 GV->setDLLStorageClass(GVDLLStorageClass);

4286

4289

4290 return GV;

4291}

4292

4293

4294

4295void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {

4296

4298 assert(isa(T) || isa(T));

4299

4300

4301

4302 if (isa(T)) return;

4303

4306

4307

4308 if (!Super) return;

4309

4311

4312

4313 llvm::Constant *BaseTypeInfo =

4314 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy);

4315 Fields.push_back(BaseTypeInfo);

4316}

4317

4318

4319

4320void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {

4321

4322

4323

4324 llvm::Constant *BaseTypeInfo =

4326 Fields.push_back(BaseTypeInfo);

4327}

4328

4329namespace {

4330

4331

4332 struct SeenBases {

4335 };

4336}

4337

4338

4339

4340

4342 SeenBases &Bases) {

4343

4344 unsigned Flags = 0;

4345

4346 auto *BaseDecl =

4348

4349 if (Base->isVirtual()) {

4350

4351 if (!Bases.VirtualBases.insert(BaseDecl).second) {

4352

4353

4354 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;

4355 } else {

4356 if (Bases.NonVirtualBases.count(BaseDecl))

4357 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;

4358 }

4359 } else {

4360

4361 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {

4362

4363

4364 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;

4365 } else {

4366 if (Bases.VirtualBases.count(BaseDecl))

4367 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;

4368 }

4369 }

4370

4371

4372 for (const auto &I : BaseDecl->bases())

4374

4375 return Flags;

4376}

4377

4379 unsigned Flags = 0;

4380 SeenBases Bases;

4381

4382

4383 for (const auto &I : RD->bases())

4385

4386 return Flags;

4387}

4388

4389

4390

4391

4392void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {

4393 llvm::Type *UnsignedIntLTy =

4395

4396

4397

4398

4399

4401 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));

4402

4403

4404

4405

4406 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));

4407

4409 return;

4410

4411

4412

4413

4414

4415

4416

4417

4418

4419

4420

4421

4422

4423

4424

4425

4426

4427

4428

4429

4430

4431

4432

4433

4436 if (TI.getTriple().isOSCygMing() &&

4439 llvm::Type *OffsetFlagsLTy =

4441

4442 for (const auto &Base : RD->bases()) {

4443

4444 Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));

4445

4446 auto *BaseDecl =

4448

4449 int64_t OffsetFlags = 0;

4450

4451

4452

4453

4454

4456 if (Base.isVirtual())

4457 Offset =

4459 else {

4462 };

4463

4464 OffsetFlags = uint64_t(Offset.getQuantity()) << 8;

4465

4466

4467

4468 if (Base.isVirtual())

4469 OffsetFlags |= BCTI_Virtual;

4471 OffsetFlags |= BCTI_Public;

4472

4473 Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));

4474 }

4475}

4476

4477

4478

4480 unsigned Flags = 0;

4481

4482 if (Type.isConstQualified())

4483 Flags |= ItaniumRTTIBuilder::PTI_Const;

4484 if (Type.isVolatileQualified())

4485 Flags |= ItaniumRTTIBuilder::PTI_Volatile;

4486 if (Type.isRestrictQualified())

4487 Flags |= ItaniumRTTIBuilder::PTI_Restrict;

4488 Type = Type.getUnqualifiedType();

4489

4490

4491

4492

4494 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;

4495

4497 if (Proto->isNothrow()) {

4498 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;

4500 }

4501 }

4502

4503 return Flags;

4504}

4505

4506

4507

4508void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {

4509

4510

4511

4513

4514 llvm::Type *UnsignedIntLTy =

4516 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));

4517

4518

4519

4520

4521 llvm::Constant *PointeeTypeInfo =

4522 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);

4523 Fields.push_back(PointeeTypeInfo);

4524}

4525

4526

4527

4528void

4529ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {

4531

4532

4533

4534

4536

4539 Flags |= PTI_ContainingClassIncomplete;

4540

4541 llvm::Type *UnsignedIntLTy =

4543 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));

4544

4545

4546

4547

4548 llvm::Constant *PointeeTypeInfo =

4549 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);

4550 Fields.push_back(PointeeTypeInfo);

4551

4552

4553

4554

4555

4556 Fields.push_back(

4557 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0)));

4558}

4559

4560llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {

4561 return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);

4562}

4563

4564void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {

4565

4566 QualType FundamentalTypes[] = {

4567 getContext().VoidTy, getContext().NullPtrTy,

4568 getContext().BoolTy, getContext().WCharTy,

4569 getContext().CharTy, getContext().UnsignedCharTy,

4570 getContext().SignedCharTy, getContext().ShortTy,

4571 getContext().UnsignedShortTy, getContext().IntTy,

4572 getContext().UnsignedIntTy, getContext().LongTy,

4573 getContext().UnsignedLongTy, getContext().LongLongTy,

4574 getContext().UnsignedLongLongTy, getContext().Int128Ty,

4575 getContext().UnsignedInt128Ty, getContext().HalfTy,

4576 getContext().FloatTy, getContext().DoubleTy,

4577 getContext().LongDoubleTy, getContext().Float128Ty,

4578 getContext().Char8Ty, getContext().Char16Ty,

4579 getContext().Char32Ty

4580 };

4581 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =

4583 ? llvm::GlobalValue::DLLExportStorageClass

4584 : llvm::GlobalValue::DefaultStorageClass;

4585 llvm::GlobalValue::VisibilityTypes Visibility =

4587 for (const QualType &FundamentalType : FundamentalTypes) {

4589 QualType PointerTypeConst = getContext().getPointerType(

4590 FundamentalType.withConst());

4592 ItaniumRTTIBuilder(*this).BuildTypeInfo(

4593 Type, llvm::GlobalValue::ExternalLinkage,

4595 }

4596}

4597

4598

4599

4600ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(

4601 QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const {

4602 if (shouldRTTIBeUnique())

4603 return RUK_Unique;

4604

4605

4606 if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&

4607 Linkage != llvm::GlobalValue::WeakODRLinkage)

4608 return RUK_Unique;

4609

4610

4612 return RUK_Unique;

4613

4614

4615 if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)

4616 return RUK_NonUniqueHidden;

4617

4618

4619

4620

4621 assert(Linkage == llvm::GlobalValue::WeakODRLinkage);

4622 return RUK_NonUniqueVisible;

4623}

4624

4625

4626namespace {

4627enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };

4628}

4632 return StructorCodegen::Emit;

4633

4634

4635

4637 return StructorCodegen::Emit;

4638

4640 if (const auto *DD = dyn_cast(MD)) {

4642 } else {

4643 const auto *CD = cast(MD);

4645 }

4647

4648 if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))

4649 return StructorCodegen::RAUW;

4650

4651

4652 if (!llvm::GlobalAlias::isValidLinkage(Linkage))

4653 return StructorCodegen::RAUW;

4654

4655 if (llvm::GlobalValue::isWeakForLinker(Linkage)) {

4656

4659 return StructorCodegen::COMDAT;

4660 return StructorCodegen::Emit;

4661 }

4662

4663 return StructorCodegen::Alias;

4664}

4665

4670

4672 llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName);

4673 if (Entry && !Entry->isDeclaration())

4674 return;

4675

4676 auto *Aliasee = castllvm::GlobalValue(CGM.GetAddrOfGlobal(TargetDecl));

4677

4678

4679 auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee);

4680

4681

4682 Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

4683

4684

4685 if (Entry) {

4686 assert(Entry->getType() == Aliasee->getType() &&

4687 "declaration exists with different type");

4688 Alias->takeName(Entry);

4689 Entry->replaceAllUsesWith(Alias);

4690 Entry->eraseFromParent();

4691 } else {

4692 Alias->setName(MangledName);

4693 }

4694

4695

4697}

4698

4699void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {

4700 auto *MD = cast(GD.getDecl());

4701 auto *CD = dyn_cast(MD);

4702 const CXXDestructorDecl *DD = CD ? nullptr : cast(MD);

4703

4705

4709 if (CD)

4711 else

4713

4714 if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {

4716 return;

4717 }

4718

4719 if (CGType == StructorCodegen::RAUW) {

4723 return;

4724 }

4725 }

4726

4727

4728

4729

4730

4732 CGType != StructorCodegen::COMDAT &&

4734 return;

4735

4736

4737

4738

4739

4740

4741

4742

4743

4744

4745

4746

4747

4749

4750 if (CGType == StructorCodegen::COMDAT) {

4752 llvm::raw_svector_ostream Out(Buffer);

4753 if (DD)

4754 getMangleContext().mangleCXXDtorComdat(DD, Out);

4755 else

4756 getMangleContext().mangleCXXCtorComdat(CD, Out);

4757 llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());

4758 Fn->setComdat(C);

4759 } else {

4761 }

4762}

4763

4765

4766 llvm::FunctionType *FTy = llvm::FunctionType::get(

4768

4770}

4771

4773

4774 llvm::FunctionType *FTy =

4775 llvm::FunctionType::get(CGM.VoidTy, false);

4776

4778}

4779

4781

4782 llvm::FunctionType *FTy = llvm::FunctionType::get(

4784

4786}

4787

4788namespace {

4789

4790

4791

4792

4793

4794

4795

4796

4797

4798

4799

4800

4802 CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}

4803 bool MightThrow;

4804

4806 if (!MightThrow) {

4808 return;

4809 }

4810

4812 }

4813 };

4814}

4815

4816

4817

4818

4819

4820

4821

4823 llvm::Value *Exn,

4824 bool EndMightThrow) {

4825 llvm::CallInst *call =

4827

4828 CGF.EHStack.pushCleanup(

4830 EndMightThrow && !CGF.CGM.getLangOpts().AssumeNothrowExceptionDtor);

4831

4832 return call;

4833}

4834

4835

4836

4838 const VarDecl &CatchParam,

4841

4843

4847

4848

4849

4850 if (isa(CatchType)) {

4852 bool EndCatchMightThrow = CaughtType->isRecordType();

4853

4854

4855 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);

4856

4857

4858

4859

4860 if (const PointerType *PT = dyn_cast(CaughtType)) {

4862

4863

4864

4866

4867

4868

4869 unsigned HeaderSize =

4871 AdjustedExn =

4872 CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);

4873

4874

4875

4876

4877

4878

4879

4880

4881

4882

4883

4884

4885

4886

4887

4888 } else {

4889

4891

4892

4895 llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);

4897

4898

4900 }

4901 }

4902

4903 llvm::Value *ExnCast =

4904 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");

4906 return;

4907 }

4908

4909

4912 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);

4913

4914

4915

4916 if (CatchType->hasPointerRepresentation()) {

4917 llvm::Value *CastExn =

4918 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");

4919

4923 [[fallthrough]];

4924

4929 return;

4930

4933 return;

4934 }

4935 llvm_unreachable("bad ownership qualifier!");

4936 }

4937

4938

4939

4942 switch (TEK) {

4945 true);

4946 return;

4950 return;

4951 }

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

4954 }

4955 llvm_unreachable("bad evaluation kind");

4956 }

4957

4958 assert(isa(CatchType) && "unexpected catch type!");

4959 auto catchRD = CatchType->getAsCXXRecordDecl();

4961

4962 llvm::Type *PtrTy = CGF.UnqualPtrTy;

4963

4964

4965

4966 const Expr *copyExpr = CatchParam.getInit();

4967 if (!copyExpr) {

4968 llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);

4969 Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),

4970 LLVMCatchTy, caughtExnAlignment);

4974 return;

4975 }

4976

4977

4978

4979 llvm::CallInst *rawAdjustedExn =

4981

4982

4983 Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),

4984 LLVMCatchTy, caughtExnAlignment);

4985

4986

4987

4988 CodeGenFunction::OpaqueValueMapping

4991

4992

4994

4995

5002

5003

5005

5006

5007 opaque.pop();

5008

5009

5011}

5012

5013

5014

5017

5018

5019

5020

5021

5022

5023

5024

5025

5026

5027

5028

5029

5030

5031

5032

5033

5034

5035

5036

5037

5038

5039

5040 VarDecl *CatchParam = S->getExceptionDecl();

5041 if (!CatchParam) {

5044 return;

5045 }

5046

5047

5049 InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());

5051}

5052

5053

5054

5055

5059 C.VoidTy, {C.getPointerType(C.CharTy)});

5062 fnTy, "__clang_call_terminate", llvm::AttributeList(), true);

5063 llvm::Function *fn =

5064 castllvm::Function(fnRef.getCallee()->stripPointerCasts());

5065 if (fn->empty()) {

5068 fn->setDoesNotThrow();

5069 fn->setDoesNotReturn();

5070

5071

5072

5073

5074 fn->addFnAttr(llvm::Attribute::NoInline);

5075

5076

5077

5078 fn->setLinkage(llvm::Function::LinkOnceODRLinkage);

5079 fn->setVisibility(llvm::Function::HiddenVisibility);

5081 fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));

5082

5083

5084 llvm::BasicBlock *entry =

5085 llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);

5087

5088

5089 llvm::Value *exn = &*fn->arg_begin();

5090

5091

5092 llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);

5093 catchCall->setDoesNotThrow();

5094 catchCall->setCallingConv(CGM.getRuntimeCC());

5095

5096

5097 llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());

5098 termCall->setDoesNotThrow();

5099 termCall->setDoesNotReturn();

5100 termCall->setCallingConv(CGM.getRuntimeCC());

5101

5102

5103 builder.CreateUnreachable();

5104 }

5105 return fnRef;

5106}

5107

5108llvm::CallInst *

5109ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,

5110 llvm::Value *Exn) {

5111

5112 if (Exn) {

5115 }

5117}

5118

5119std::pair<llvm::Value *, const CXXRecordDecl *>

5123}

5124

5125llvm::Constant *

5126ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) {

5131 llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);

5135}

5136

5137void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,

5142 ItaniumCXXABI::emitBeginCatch(CGF, C);

5143}

5144

5145llvm::CallInst *

5146WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,

5147 llvm::Value *Exn) {

5148

5149

5150

5151

5152

5153

5155}

5156

5157

5159 llvm::FunctionCallee Dtor,

5160 llvm::Constant *Addr) {

5162 llvm::PointerType *PtrTy = CGF.UnqualPtrTy;

5163

5164

5165 llvm::FunctionType *AtExitTy =

5166 llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy, PtrTy}, true);

5167

5168

5169 llvm::FunctionCallee AtExit =

5171

5172

5174

5175

5176

5177 llvm::Value *NV = llvm::Constant::getNullValue(CGM.IntTy);

5179

5180

5181 return;

5182 }

5183

5184

5185 llvm::Function *DtorStub =

5187

5188

5190

5191

5192

5193 emitCXXStermFinalizer(D, DtorStub, Addr);

5194}

5195

5196void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,

5197 llvm::Constant *addr) {

5198 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);

5200 {

5201 llvm::raw_svector_ostream Out(FnName);

5202 getMangleContext().mangleDynamicStermFinalizer(&D, Out);

5203 }

5204

5205

5209

5211

5214 D.getInit()->getExprLoc());

5215

5216

5217

5218

5219

5221

5223

5224 llvm::BasicBlock *DestructCallBlock = CGF.createBasicBlock("destruct.call");

5225 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end");

5226

5227

5228

5229 CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);

5230

5231 CGF.EmitBlock(DestructCallBlock);

5232

5233

5234 llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub);

5235

5236

5237 CI->setCallingConv(dtorStub->getCallingConv());

5238

5240

5242

5243 if (auto *IPA = D.getAttr()) {

5245 IPA->getPriority());

5248

5249

5250

5251

5253 } else {

5255 }

5256}

static StructorCodegen getCodegenToUse(CodeGenModule &CGM, const CXXMethodDecl *MD)

static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF)

static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM)

Get or define the following function: void @__clang_call_terminate(i8* exn) nounwind noreturn This co...

static bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD)

static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type)

Compute the flags for a __pbase_type_info, and remove the corresponding pieces from Type.

static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty)

ShouldUseExternalRTTIDescriptor - Returns whether the type information for the given type exists some...

static bool IsIncompleteClassType(const RecordType *RecordTy)

IsIncompleteClassType - Returns whether the given record type is incomplete.

static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, SeenBases &Bases)

ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in abi::__vmi_class_type_info.

static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF)

static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, llvm::FunctionCallee dtor, llvm::Constant *addr, bool TLS)

Register a global destructor using __cxa_atexit.

static llvm::FunctionCallee getBadCastFn(CodeGenFunction &CGF)

static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM)

static llvm::Constant * pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType, QualType SrcType, CodeGenModule &CGM)

static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty)

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

static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)

static llvm::Value * performTypeAdjustment(CodeGenFunction &CGF, Address InitialPtr, const CXXRecordDecl *UnadjustedClass, int64_t NonVirtualAdjustment, int64_t VirtualAdjustment, bool IsReturnAdjustment)

static llvm::Function * createGlobalInitOrCleanupFn(CodeGen::CodeGenModule &CGM, StringRef FnName)

static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM)

static bool IsStandardLibraryRTTIDescriptor(QualType Ty)

IsStandardLibraryRTTIDescriptor - Returns whether the type information for the given type exists in t...

static llvm::Value * CallBeginCatch(CodeGenFunction &CGF, llvm::Value *Exn, bool EndMightThrow)

Emits a call to __cxa_begin_catch and enters a cleanup to call __cxa_end_catch.

static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)

static CharUnits computeOffsetHint(ASTContext &Context, const CXXRecordDecl *Src, const CXXRecordDecl *Dst)

Compute the src2dst_offset hint as described in the Itanium C++ ABI [2.9.7].

static bool isThreadWrapperReplaceable(const VarDecl *VD, CodeGen::CodeGenModule &CGM)

static void InitCatchParam(CodeGenFunction &CGF, const VarDecl &CatchParam, Address ParamAddr, SourceLocation Loc)

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

static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty)

TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type info for that type is de...

static bool CanUseSingleInheritance(const CXXRecordDecl *RD)

static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM)

static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM)

Get the appropriate linkage for the wrapper function.

static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM)

static void setVTableSelectiveDLLImportExport(CodeGenModule &CGM, llvm::GlobalVariable *VTable, const CXXRecordDecl *RD)

static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)

static bool ContainsIncompleteClassType(QualType Ty)

ContainsIncompleteClassType - Returns whether the given type contains an incomplete class type.

static llvm::Constant * pointerAuthResignConstant(llvm::Value *Ptr, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, CodeGenModule &CGM)

static void emitConstructorDestructorAlias(CodeGenModule &CGM, GlobalDecl AliasDecl, GlobalDecl TargetDecl)

static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM)

static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)

llvm::MachO::Record Record

static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)

static const RecordType * getRecordType(QualType QT)

Checks that the passed in QualType either is of RecordType or points to RecordType.

static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D)

Determine what kind of template specialization the given declaration is.

static QualType getPointeeType(const MemRegion *R)

#define CXXABI(Name, Str)

C Language Family Type Representation.

APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...

const ValueDecl * getMemberPointerDecl() 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.

QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const

getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.

QualType getMemberPointerType(QualType T, const Type *Cls) const

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

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

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

CanQualType getCanonicalType(QualType T) const

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

CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod, bool IsBuiltin=false) const

Retrieves the default calling convention for the current target.

QualType getPointerType(QualType T) const

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

const LangOptions & getLangOpts() const

QualType getFunctionTypeWithExceptionSpec(QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const

Get a function type and produce the equivalent function type with the specified exception specificati...

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 getDeclAlign(const Decl *D, bool ForAlignof=false) const

Return a conservative estimate of the alignment of the specified decl D.

CharUnits getPreferredTypeAlignInChars(QualType T) const

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

CanQualType UnsignedIntTy

QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const

Return a normal function type with a typed argument list.

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.

QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const

Return the uniqued reference to the type for an address space qualified type with the specified type ...

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.

This class is used for builtin types like 'int'.

Implements C++ ABI-specific semantic analysis functions.

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

Represents a base class of a C++ class.

QualType getType() const

Retrieves the type of the base class.

CXXCatchStmt - This represents a C++ catch block.

Represents a C++ constructor within a class.

Represents a delete expression for memory deallocation and destructor calls, e.g.

FunctionDecl * getOperatorDelete() const

bool isGlobalDelete() const

Represents a C++ destructor within a class.

Represents a call to a member function that may be written either with member call syntax (e....

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.

CXXMethodDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".

Represents a C++ struct/union/class.

unsigned getNumBases() const

Retrieves the number of base classes of this class.

base_class_iterator bases_begin()

base_class_range vbases()

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.

A C++ throw-expression (C++ [except.throw]).

static CanQual< Type > CreateUnsafe(QualType Other)

Builds a canonical type from a QualType.

Qualifiers getQualifiers() const

Retrieve all qualifiers.

CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...

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

bool isZero() const

isZero - Test whether the quantity equals zero.

llvm::Align getAsAlign() const

getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

static CharUnits One()

One - Construct a CharUnits quantity of one.

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.

PointerAuthOptions PointerAuth

Configuration for pointer-signing.

std::string SymbolPartition

The name of the partition that symbols are assigned to, specified with -fsymbol-partition (see https:...

static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)

Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...

llvm::Value * emitRawPointer(CodeGenFunction &CGF) const

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

CharUnits getAlignment() const

llvm::Type * getElementType() const

Return the type of the values stored in this address.

Address withElementType(llvm::Type *ElemTy) const

Return address with different element type, but same pointer and alignment.

unsigned getAddressSpace() const

Return the address space that this address resides in.

llvm::PointerType * getType() const

Return the type of the pointer value.

static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)

forAddr - Make a slot for an aggregate value.

static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)

Apply TemporaryLocation if it is valid.

llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)

Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")

Given a pointer to i8, adjust it by a given constant offset.

llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")

Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")

llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")

llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")

Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")

Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...

Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")

Implements C++ ABI-specific code generation functions.

virtual bool shouldEmitExactDynamicCast(QualType DestRecordTy)=0

virtual void EmitCXXConstructors(const CXXConstructorDecl *D)=0

Emit constructor variants required by this ABI.

virtual llvm::Constant * getAddrOfRTTIDescriptor(QualType Ty)=0

virtual llvm::Value * getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base, const CXXRecordDecl *NearestVBase)=0

Get the address point of the vtable for the given base subobject while building a constructor or a de...

virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C)=0

virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn)=0

virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0

virtual bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr)=0

Checks if ABI requires extra virtual offset for vtable field.

virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, llvm::GlobalVariable *DeclPtr, bool PerformInit)=0

Emits the guarded initializer and destructor setup for the given variable, given that it couldn't be ...

virtual void EmitCXXDestructors(const CXXDestructorDecl *D)=0

Emit destructor variants required by this ABI.

virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF)=0

Emit the ABI-specific prolog for the function.

virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, CXXDtorType DT) const =0

Returns true if the given destructor type should be emitted as a linkonce delegating thunk,...

virtual bool NeedsVTTParameter(GlobalDecl GD)

Return whether the given global decl needs a VTT parameter.

virtual llvm::CallInst * emitTerminateForUnexpectedException(CodeGenFunction &CGF, llvm::Value *Exn)

@ RAA_Default

Pass it using the normal C aggregate rules for the ABI, potentially introducing extra copies and pass...

@ RAA_Indirect

Pass it as a pointer to temporary memory.

virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy)=0

virtual llvm::Type * ConvertMemberPointerType(const MemberPointerType *MPT)

Find the LLVM type used to represent the given member pointer type.

virtual llvm::Value * performThisAdjustment(CodeGenFunction &CGF, Address This, const CXXRecordDecl *UnadjustedClass, const ThunkInfo &TI)=0

virtual llvm::Constant * EmitNullMemberPointer(const MemberPointerType *MPT)

Create a null member pointer of the given type.

virtual StringRef GetPureVirtualCallName()=0

Gets the pure virtual member call function.

virtual CharUnits getArrayCookieSizeImpl(QualType elementType)

Returns the extra size required in order to store the array cookie for the given type.

virtual void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr)=0

Emit code to force the execution of a destructor during global teardown.

virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const =0

Determine whether it's possible to emit a vtable for RD, even though we do not know that the vtable h...

virtual StringRef GetDeletedVirtualCallName()=0

Gets the deleted virtual member call name.

virtual llvm::Value * EmitMemberPointerIsNotNull(CodeGenFunction &CGF, llvm::Value *MemPtr, const MemberPointerType *MPT)

Determine if a member pointer is non-null. Returns an i1.

virtual llvm::Value * performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const CXXRecordDecl *UnadjustedClass, const ReturnAdjustment &RA)=0

virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, QualType LValType)=0

Emit a reference to a non-local thread_local variable (including triggering the initialization of all...

bool isEmittedWithConstantInitializer(const VarDecl *VD, bool InspectInitForWeakDef=false) const

Determine whether we will definitely emit this variable with a constant initializer,...

virtual llvm::Value * EmitMemberPointerComparison(CodeGenFunction &CGF, llvm::Value *L, llvm::Value *R, const MemberPointerType *MPT, bool Inequality)

Emit a comparison between two member pointers. Returns an i1.

virtual llvm::Constant * EmitMemberPointer(const APValue &MP, QualType MPT)

Create a member pointer for the given member pointer constant.

virtual llvm::Constant * getVTableAddressPoint(BaseSubobject Base, const CXXRecordDecl *VTableClass)=0

Get the address point of the vtable for the given base subobject.

virtual void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params)=0

Insert any ABI-specific implicit parameters into the parameter list for a function.

virtual llvm::Value * readArrayCookieImpl(CodeGenFunction &IGF, Address ptr, CharUnits cookieSize)

Reads the array cookie for an allocation which is known to have one.

virtual llvm::Value * EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, const MemberPointerType *MPT)

Calculate an l-value from an object and a data member pointer.

virtual llvm::Value * getCXXDestructorImplicitParam(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating)=0

Get the implicit (second) parameter that comes after the "this" pointer, or nullptr if there is isn't...

virtual std::pair< llvm::Value *, const CXXRecordDecl * > LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD)=0

Load a vtable from This, an object of polymorphic type RD, or from one of its virtual bases if it doe...

virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment)=0

bool mayNeedDestruction(const VarDecl *VD) const

virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass)=0

Checks if ABI requires to initialize vptrs for given dynamic class.

virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E)=0

virtual llvm::Value * GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl)=0

virtual bool isThisCompleteObject(GlobalDecl GD) const =0

Determine whether there's something special about the rules of the ABI tell us that 'this' is a compl...

virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, Address This, llvm::Type *Ty, SourceLocation Loc)=0

Build a virtual function pointer in the ABI-specific way.

virtual bool classifyReturnType(CGFunctionInfo &FI) const =0

If the C++ ABI requires the given type be returned in a particular way, this method sets RetAI and re...

virtual void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, const CXXDestructorDecl *Dtor)=0

virtual CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType)=0

virtual void EmitThreadLocalInitFuncs(CodeGenModule &CGM, ArrayRef< const VarDecl * > CXXThreadLocals, ArrayRef< llvm::Function * > CXXThreadLocalInits, ArrayRef< const VarDecl * > CXXThreadLocalInitVars)=0

Emits ABI-required functions necessary to initialize thread_local variables in this translation unit.

virtual bool usesThreadWrapperFunction(const VarDecl *VD) const =0

virtual RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const =0

Returns how an argument of the given record type should be passed.

virtual llvm::Value * emitExactDynamicCast(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess, llvm::BasicBlock *CastFail)=0

Emit a dynamic_cast from SrcRecordTy to DestRecordTy.

virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)=0

Emit the destructor call.

virtual llvm::GlobalVariable * getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset)=0

Get the address of the vtable for the given record decl which should be used for the vptr at the give...

virtual bool EmitBadCastCall(CodeGenFunction &CGF)=0

virtual llvm::Constant * EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset)

Create a member pointer for the given field.

virtual llvm::Value * EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy)=0

virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD)=0

Emit any tables needed to implement virtual inheritance.

virtual void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD)=0

Emits the VTable definitions required for the given record type.

virtual CGCallee EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, Address This, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, const MemberPointerType *MPT)

Load a member function from an object and a member function pointer.

virtual void emitCXXStructor(GlobalDecl GD)=0

Emit a single constructor/destructor with the given type from a C++ constructor Decl.

virtual llvm::Value * EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke)=0

Emit the ABI-specific virtual destructor call.

virtual bool exportThunk()=0

virtual void EmitBadTypeidCall(CodeGenFunction &CGF)=0

virtual llvm::Value * emitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy)=0

virtual bool isZeroInitializable(const MemberPointerType *MPT)

Return true if the given member pointer can be zero-initialized (in the C++ sense) with an LLVM zeroi...

virtual llvm::Value * EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src)

Perform a derived-to-base, base-to-derived, or bitcast member pointer conversion.

virtual llvm::Constant * EmitMemberFunctionPointer(const CXXMethodDecl *MD)

Create a member pointer for the given method.

virtual llvm::Value * emitDynamicCastCall(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd)=0

virtual Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr, llvm::Value *NumElements, const CXXNewExpr *expr, QualType ElementType)

Initialize the array cookie for the given allocation.

virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, QualType SrcRecordTy)=0

virtual AddedStructorArgCounts buildStructorSignature(GlobalDecl GD, SmallVectorImpl< CanQualType > &ArgTys)=0

Build the signature of the given constructor or destructor variant by adding any required parameters.

MangleContext & getMangleContext()

Gets the mangle context.

virtual AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating)=0

All available information about a concrete callee.

static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)

static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())

CGFunctionInfo - Class to encapsulate the information about a function definition.

ABIArgInfo & getReturnInfo()

CanQualType getReturnType() const

llvm::Value * getDiscriminator() const

CallArgList - Type for representing both the value and type of arguments in a call.

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

void GenerateCXXGlobalInitFunc(llvm::Function *Fn, ArrayRef< llvm::Function * > CXXThreadLocals, ConstantAddress Guard=ConstantAddress::invalid())

GenerateCXXGlobalInitFunc - Generates code for initializing global variables.

llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)

void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr, QualType ElementType)

void FinishFunction(SourceLocation EndLoc=SourceLocation())

FinishFunction - Complete IR generation of the current function.

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass, VTableAuthMode AuthMode=VTableAuthMode::Authenticate)

GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.

static TypeEvaluationKind getEvaluationKind(QualType T)

getEvaluationKind - Return the TypeEvaluationKind of QualType T.

SanitizerSet SanOpts

Sanitizers enabled for this function.

llvm::Constant * createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)

void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false)

Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...

bool CurFuncIsThunk

In C++, whether we are code generating a thunk.

void EmitAnyExprToExn(const Expr *E, Address Addr)

void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)

llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)

llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)

createBasicBlock - Create an LLVM basic block.

llvm::Constant * EmitCheckTypeDescriptor(QualType T)

Emit a description of a type in a format suitable for passing to a runtime sanitizer handler.

void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)

EmitBlock - Emit the given block.

llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)

CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...

llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)

Emit a type checked load from the given vtable.

llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)

GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...

llvm::Type * ConvertTypeForMem(QualType T)

llvm::Function * createTLSAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr, llvm::FunctionCallee &AtExit)

void registerGlobalDtorWithLLVM(const VarDecl &D, llvm::FunctionCallee fn, llvm::Constant *addr)

Registers the dtor using 'llvm.global_dtors' for platforms that do not support an 'atexit()' function...

const TargetInfo & getTarget() const

void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit)

EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.

llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)

bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)

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

void EmitCheck(ArrayRef< std::pair< llvm::Value *, SanitizerKind::SanitizerOrdinal > > Checked, SanitizerHandler Check, ArrayRef< llvm::Constant * > StaticArgs, ArrayRef< llvm::Value * > DynamicArgs)

Create a basic block that will either trap or call a handler function in the UBSan runtime with the p...

CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, const CXXRecordDecl *RD)

void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())

Emit code for the start of a function.

void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)

EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...

ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)

EmitLoadOfComplex - Load a complex number from the specified l-value.

llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)

Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...

void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::FunctionCallee fn, llvm::Constant *addr)

Call atexit() with a function that passes the given argument to the given function.

void EmitBranch(llvm::BasicBlock *Block)

EmitBranch - Emit a branch to the specified basic block from the current insert block,...

LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)

Same as MakeAddrLValue above except that the pointer is known to be unsigned.

void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)

EmitAggregateCopy - Emit an aggregate copy.

llvm::Value * unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub)

Call unatexit() with function dtorStub.

LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)

void EmitAggExpr(const Expr *E, AggValueSlot AS)

EmitAggExpr - Emit the computation of the specified expression of aggregate type.

RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)

EmitCall - Generate a call of the given function, expecting the given result type,...

llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")

ASTContext & getContext() const

llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)

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

const Decl * CurFuncDecl

CurFuncDecl - Holds the Decl for the current outermost non-closure context.

llvm::Value * LoadCXXVTT()

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

AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)

void EmitAutoVarCleanups(const AutoVarEmission &emission)

void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)

PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.

void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc)

If whole-program virtual table optimization is enabled, emit an assumption that VTable is a member of...

llvm::Type * ConvertType(QualType T)

void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)

CodeGenTypes & getTypes() const

void EmitARCInitWeak(Address addr, llvm::Value *value)

llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")

QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)

llvm::Value * EmitARCRetainNonBlock(llvm::Value *value)

LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)

void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)

EmitStoreOfComplex - Store a complex number into the specified l-value.

LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

llvm::Instruction * CurrentFuncletPad

llvm::LLVMContext & getLLVMContext()

llvm::Value * getExceptionFromSlot()

Returns the contents of the function's exception object and selector slots.

void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)

EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...

CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)

void EmitCXXGuardedInitBranch(llvm::Value *NeedsInit, llvm::BasicBlock *InitBlock, llvm::BasicBlock *NoInitBlock, GuardKind Kind, const VarDecl *D)

Emit a branch to select whether or not to perform guarded initialization.

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

void AddCXXPrioritizedStermFinalizerEntry(llvm::Function *StermFinalizer, int Priority)

void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const

Set visibility, dllimport/dllexport and dso_local.

void AddCXXStermFinalizerToGlobalDtor(llvm::Function *StermFinalizer, int Priority)

Add an sterm finalizer to its own llvm.global_dtors entry.

llvm::GlobalVariable::ThreadLocalMode GetDefaultLLVMTLSModel() const

Get LLVM TLS mode from CodeGenOptions.

void setDSOLocal(llvm::GlobalValue *GV) const

llvm::Module & getModule() const

llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)

Create or return a runtime function declaration with the specified type and name.

CodeGenVTables & getVTables()

void AddCXXStermFinalizerEntry(llvm::FunctionCallee DtorFn)

Add an sterm finalizer to the C++ global cleanup function.

llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)

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

llvm::Constant * getFunctionPointer(GlobalDecl GD, llvm::Type *Ty=nullptr)

Return the ABI-correct function pointer value for a reference to the given function.

CGPointerAuthInfo getMemberFunctionPointerAuthInfo(QualType FT)

const LangOptions & getLangOpts() const

CodeGenTypes & getTypes()

bool shouldMapVisibilityToDLLExport(const NamedDecl *D) const

const TargetInfo & getTarget() const

bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D)

Try to emit a base destructor as an alias to its primary base-class destructor.

llvm::GlobalValue::LinkageTypes getLLVMLinkageVarDefinition(const VarDecl *VD)

Returns LLVM linkage for a declarator.

const llvm::DataLayout & getDataLayout() const

CGCXXABI & getCXXABI() const

static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V)

llvm::Constant * getMemberFunctionPointer(const FunctionDecl *FD, llvm::Type *Ty=nullptr)

llvm::Function * codegenCXXStructor(GlobalDecl GD)

CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)

Returns the assumed alignment of an opaque pointer to the given class.

const llvm::Triple & getTriple() const

llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD)

void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535, bool IsDtorAttrFunc=false)

AddGlobalDtor - Add a function to the list that will be called when the module is unloaded.

llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)

Create a new runtime global variable with the specified type and name.

CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign, const CXXRecordDecl *Class, CharUnits ExpectedTargetAlign)

Given a class pointer with an actual known alignment, and the expected alignment of an object at a dy...

llvm::Constant * GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition=NotForDefinition)

ItaniumVTableContext & getItaniumVTableContext()

ASTContext & getContext() const

llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)

Return the llvm::Constant for the address of the given global variable.

bool supportsCOMDAT() const

const TargetCodeGenInfo & getTargetCodeGenInfo()

const CodeGenOptions & getCodeGenOpts() const

StringRef getMangledName(GlobalDecl GD)

void SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV)

Set attributes which are common to any form of a global definition (alias, Objective-C method,...

llvm::GlobalVariable * CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage, llvm::Align Alignment)

Will return a global variable of the given type.

llvm::FunctionCallee getTerminateFn()

Get the declaration of std::terminate for the platform.

llvm::LLVMContext & getLLVMContext()

llvm::GlobalValue * GetGlobalValue(StringRef Ref)

void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO)

LangAS GetGlobalVarAddressSpace(const VarDecl *D)

Return the AST address space of the underlying global variable for D, as determined by its declaratio...

llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD)

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

void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk)

Set the LLVM function attributes (sext, zext, etc).

void addReplacement(StringRef Name, llvm::Constant *C)

llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, llvm::Constant *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)

Sign a constant pointer using the given scheme, producing a constant with the same IR type.

void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535, unsigned LexOrder=~0U, llvm::Constant *AssociatedData=nullptr)

AddGlobalCtor - Add a function to the list that will be called before main() runs.

void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)

Set the LLVM function attributes which only apply to a function definition.

llvm::Function * CreateGlobalInitOrCleanUpFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc=SourceLocation(), bool TLS=false, llvm::GlobalVariable::LinkageTypes Linkage=llvm::GlobalVariable::InternalLinkage)

This class organizes the cross-module state that is used while lowering AST types to LLVM types.

llvm::Type * ConvertType(QualType T)

ConvertType - Convert type T into a llvm::Type.

const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)

C++ methods have some special rules and also have implicit parameters.

const CodeGenOptions & getCodeGenOpts() const

llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)

GetFunctionType - Get the LLVM function type for.

const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)

A builtin function is a freestanding function using the default C conventions.

const CGFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs)

Arrange a call to a C++ method, passing the given arguments.

const CGFunctionInfo & arrangeNullaryFunction()

A nullary function is a freestanding function of type 'void ()'.

llvm::GlobalVariable * GetAddrOfVTT(const CXXRecordDecl *RD)

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

void createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti, bool vtableHasLocalLinkage)

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

void GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, llvm::StringRef AliasNameRef)

Generate a public facing alias for the vtable and make the vtable either hidden or private.

bool isVTableExternal(const CXXRecordDecl *RD)

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

void RemoveHwasanMetadata(llvm::GlobalValue *GV) const

Specify a global should not be instrumented with hwasan.

void EmitVTTDefinition(llvm::GlobalVariable *VTT, llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD)

EmitVTTDefinition - Emit the definition of the given vtable.

A specialization of Address that requires the address to be an LLVM Constant.

The standard implementation of ConstantInitBuilder used in Clang.

Information for lazily generating a cleanup.

void popTerminate()

Pops a terminate handler off the stack.

void pushTerminate()

Push a terminate handler on the stack.

FunctionArgList - Type for representing both the decl and type of parameters to a function.

LValue - This represents an lvalue references.

RValue - This trivial value class is used to represent the result of an expression that is evaluated.

static RValue get(llvm::Value *V)

A class for recording the number of arguments that a function signature requires.

static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)

Compute the arguments required by the given formal prototype, given that there may be some additional...

ReturnValueSlot - Contains the address where the return value of a function can be stored,...

virtual unsigned getSizeOfUnwindException() const

Determines the size of struct _Unwind_Exception on this platform, in 8-bit units.

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

DeclContext * getParent()

getParent - Returns the containing DeclContext.

bool isTranslationUnit() const

decl_range noload_decls() const

noload_decls_begin/end - Iterate over the declarations stored in this context that are currently load...

SourceLocation getLocation() const

DeclContext * getDeclContext()

bool shouldEmitInExternalSource() const

Whether the definition of the declaration should be emitted in external sources.

This represents one expression.

Represents a function declaration or definition.

bool isInlined() const

Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...

bool doesThisDeclarationHaveABody() const

Returns whether this specific declaration of the function has a body.

bool isPureVirtual() const

Whether this virtual function is pure, i.e.

FunctionDecl * getDefinition()

Get the definition for this declaration.

bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const

Returns true if the function has a definition that does not need to be instantiated.

Represents a prototype with parameter type info, e.g.

GlobalDecl - represents a global declaration.

GlobalDecl getWithCtorType(CXXCtorType Type)

CXXCtorType getCtorType() const

GlobalDecl getCanonicalDecl() 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.

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

GlobalDecl findOriginalMethod(GlobalDecl GD)

Return the method that added the v-table slot that will be used to call the given method.

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

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

A pointer to member type per C++ 8.3.3 - Pointers to members.

QualType getPointeeType() const

bool isMemberFunctionPointer() const

Returns true if the member type (i.e.

bool isMemberDataPointer() const

Returns true if the member type (i.e.

const Type * getClass() const

IdentifierInfo * getIdentifier() const

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

Visibility getVisibility() const

Determines the visibility of this entity.

bool isExternallyVisible() const

Represents an ObjC class declaration.

Represents a class type in Objective C.

QualType getBaseType() const

Gets the base type of this object type.

static const OpaqueValueExpr * findInCopyConstruct(const Expr *expr)

Given an expression which invokes a copy constructor — i.e.

PointerType - C99 6.7.5.1 - Pointer Declarators.

QualType getPointeeType() const

A (possibly-)qualified type.

const Type * getTypePtr() const

Retrieves a pointer to the underlying (unqualified) type.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

QualType getNonReferenceType() const

If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...

QualType getCanonicalType() const

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

The collection of all-type qualifiers we support.

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

ObjCLifetime getObjCLifetime() const

bool canPassInRegisters() const

Determine whether this class can be passed in registers.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

RecordDecl * getDecl() const

Encodes a location in the source.

SourceLocation getBeginLoc() const LLVM_READONLY

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

Exposes information about the current target.

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

unsigned getMaxAtomicInlineWidth() const

Return the maximum width lock-free atomic operation which can be inlined given the supported features...

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

unsigned getLongWidth() const

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

virtual bool hasFeature(StringRef Feature) const

Determine whether the given target has the given feature.

const Type * getTypeForDecl() const

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

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

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

Visibility getVisibility() const

Determine the visibility of this type.

bool isMemberFunctionPointerType() const

Linkage getLinkage() const

Determine the linkage of this type.

TypeClass getTypeClass() const

const T * getAs() const

Member-template getAs'.

bool isRecordType() const

AddressPointLocation getAddressPoint(BaseSubobject Base) const

size_t getVTableSize(size_t i) const

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

Represents a variable declaration or definition.

TLSKind getTLSKind() const

VarDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

bool isStaticLocal() const

Returns true if a variable with function scope is a static local variable.

const Expr * getInit() const

@ TLS_Dynamic

TLS with a dynamic initializer.

@ TLS_None

Not a TLS variable.

DefinitionKind hasDefinition(ASTContext &) const

Check whether this variable is defined in this translation unit.

TemplateSpecializationKind getTemplateSpecializationKind() const

If this variable is an instantiation of a variable template or a static data member of a class templa...

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

TypeEvaluationKind

The kind of evaluation to perform on values of a particular type.

@ NormalCleanup

Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...

@ EHCleanup

Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...

CGCXXABI * CreateItaniumCXXABI(CodeGenModule &CGM)

Creates an Itanium-family ABI.

const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr

Matches expressions.

constexpr Variable var(Literal L)

Returns the variable of L.

bool This(InterpState &S, CodePtr OpPC)

bool Zero(InterpState &S, CodePtr OpPC)

bool InRange(InterpState &S, CodePtr OpPC)

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

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_DefaultClosure

Default closure variant of a ctor.

@ Ctor_CopyingClosure

Copying closure variant of a ctor.

@ Ctor_Complete

Complete object ctor.

@ Ctor_Comdat

The COMDAT used for ctors.

bool isTemplateInstantiation(TemplateSpecializationKind Kind)

Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...

Linkage

Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.

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

The COMDAT used for dtors.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

bool isDiscardableGVALinkage(GVALinkage L)

LangAS

Defines the address space values used by the address space qualifier of QualType.

const FunctionProtoType * T

@ Success

Template argument deduction was successful.

@ Class

The "class" keyword introduces the elaborated-type-specifier.

@ EST_None

no exception specification

Visibility

Describes the different kinds of visibility that a declaration may have.

@ HiddenVisibility

Objects with "hidden" visibility are not seen by the dynamic linker.

@ DefaultVisibility

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

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

Similar to AddedStructorArgs, but only notes the number of additional arguments.

Additional implicit arguments to add to the beginning (Prefix) and end (Suffix) of a constructor / de...

The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...

llvm::PointerType * VoidPtrTy

llvm::IntegerType * Int64Ty

llvm::PointerType * GlobalsVoidPtrTy

llvm::IntegerType * Int8Ty

i8, i16, i32, and i64

llvm::IntegerType * CharTy

char

llvm::CallingConv::ID getRuntimeCC() const

llvm::IntegerType * SizeTy

llvm::PointerType * VoidPtrPtrTy

llvm::PointerType * GlobalsInt8PtrTy

llvm::IntegerType * Int32Ty

llvm::IntegerType * IntPtrTy

llvm::IntegerType * IntTy

int

CharUnits getSizeSize() const

CharUnits getSizeAlign() const

llvm::PointerType * Int8PtrTy

llvm::PointerType * UnqualPtrTy

CharUnits getPointerAlign() const

Extra information about a function prototype.

PointerAuthSchema CXXVTTVTablePointers

The ABI for C++ virtual table pointers as installed in a VTT.

PointerAuthSchema CXXTypeInfoVTablePointer

TypeInfo has external ABI requirements and is emitted without actually having parsed the libcxx defin...

union clang::ReturnAdjustment::VirtualAdjustment Virtual

int64_t NonVirtual

The non-virtual adjustment from the derived object to its nearest virtual base.

bool has(SanitizerMask K) const

Check if a certain (single) sanitizer is enabled.

A this pointer adjustment.

union clang::ThisAdjustment::VirtualAdjustment Virtual

int64_t NonVirtual

The non-virtual adjustment from the derived object to its nearest virtual base.

The this pointer adjustment as well as an optional return adjustment for a thunk.

ThisAdjustment This

The this pointer adjustment.

unsigned AddressPointIndex

struct clang::ReturnAdjustment::VirtualAdjustment::@192 Itanium

int64_t VBaseOffsetOffset

The offset (in bytes), relative to the address point of the virtual base class offset.

int64_t VCallOffsetOffset

The offset (in bytes), relative to the address point, of the virtual call offset.

struct clang::ThisAdjustment::VirtualAdjustment::@194 Itanium