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

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

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

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

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

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

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

39

40#include

41

42using namespace clang;

44

45namespace {

47

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

49

50

51 llvm::SmallVector<std::pair<const VarDecl *, llvm::Function *>, 8>

52 ThreadWrappers;

53

54protected:

55 bool UseARMMethodPtrABI;

56 bool UseARMGuardVarABI;

57 bool Use32BitVTableOffsetABI;

58

59 ItaniumMangleContext &getMangleContext() {

61 }

62

63public:

64 ItaniumCXXABI(CodeGen::CodeGenModule &CGM,

65 bool UseARMMethodPtrABI = false,

66 bool UseARMGuardVarABI = false) :

67 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),

68 UseARMGuardVarABI(UseARMGuardVarABI),

69 Use32BitVTableOffsetABI(false) { }

70

72

73 RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {

74

76 return RAA_Indirect;

77 return RAA_Default;

78 }

79

80 bool isThisCompleteObject(GlobalDecl GD) const override {

81

82

87 return true;

88

90 return false;

91

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

95 llvm_unreachable("emitting unified dtor as function?");

97 llvm_unreachable("unexpected dtor kind for this ABI");

98 }

99 llvm_unreachable("bad dtor kind");

100 }

104 return true;

105

107 return false;

108

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

112

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

115

117 llvm_unreachable("emitting unified ctor as function?");

118 }

119 llvm_unreachable("bad dtor kind");

120 }

121

122

123 return false;

124 }

125

126 bool isZeroInitializable(const MemberPointerType *MPT) override;

127

128 llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;

129

130 CGCallee

131 EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,

132 const Expr *E,

133 Address This,

134 llvm::Value *&ThisPtrForCall,

135 llvm::Value *MemFnPtr,

136 const MemberPointerType *MPT) override;

137

138 llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,

139 Address Base, llvm::Value *MemPtr,

140 const MemberPointerType *MPT,

141 bool IsInBounds) override;

142

143 llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,

145 llvm::Value *Src) override;

146 llvm::Constant *EmitMemberPointerConversion(const CastExpr *E,

147 llvm::Constant *Src) override;

148

149 llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;

150

151 llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override;

152 llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,

153 CharUnits offset) override;

154 llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override;

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

156 CharUnits ThisAdjustment);

157

158 llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,

159 llvm::Value *L, llvm::Value *R,

160 const MemberPointerType *MPT,

161 bool Inequality) override;

162

163 llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,

164 llvm::Value *Addr,

165 const MemberPointerType *MPT) override;

166

167 void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,

168 Address Ptr, QualType ElementType,

169 const CXXDestructorDecl *Dtor) override;

170

171 void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;

172 void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override;

173

174 void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;

175

176 llvm::CallInst *

177 emitTerminateForUnexpectedException(CodeGenFunction &CGF,

178 llvm::Value *Exn) override;

179

180 void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);

181 llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;

182 CatchTypeInfo

183 getAddrOfCXXCatchHandlerType(QualType Ty,

184 QualType CatchHandlerType) override {

185 return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0};

186 }

187

188 bool shouldTypeidBeNullChecked(QualType SrcRecordTy) override;

189 void EmitBadTypeidCall(CodeGenFunction &CGF) override;

190 llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,

191 Address ThisPtr,

192 llvm::Type *StdTypeInfoPtrTy) override;

193

194 bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,

195 QualType SrcRecordTy) override;

196

197

198

199

200

201 bool hasUniqueVTablePointer(QualType RecordTy) {

203

204

205

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

207 getContext().getLangOpts().AppleKext)

208 return false;

209

210

211

212 if (!CGM.shouldEmitRTTI())

213 return false;

214

215

216

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

218 return true;

219

220

221

222

223

224

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

226 llvm::GlobalValue::DefaultVisibility)

227 return false;

228

229 return true;

230 }

231

232 bool shouldEmitExactDynamicCast(QualType DestRecordTy) override {

233 return hasUniqueVTablePointer(DestRecordTy);

234 }

235

236 std::optional

237 getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,

238 QualType DestRecordTy) override;

239

240 llvm::Value *emitDynamicCastCall(CodeGenFunction &CGF, Address Value,

241 QualType SrcRecordTy, QualType DestTy,

242 QualType DestRecordTy,

243 llvm::BasicBlock *CastEnd) override;

244

246 QualType SrcRecordTy, QualType DestTy,

247 QualType DestRecordTy,

248 const ExactDynamicCastInfo &CastInfo,

249 llvm::BasicBlock *CastSuccess,

250 llvm::BasicBlock *CastFail) override;

251

253 QualType SrcRecordTy) override;

254

255 bool EmitBadCastCall(CodeGenFunction &CGF) override;

256

257 llvm::Value *

258 GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,

259 const CXXRecordDecl *ClassDecl,

260 const CXXRecordDecl *BaseClassDecl) override;

261

262 void EmitCXXConstructors(const CXXConstructorDecl *D) override;

263

264 AddedStructorArgCounts

265 buildStructorSignature(GlobalDecl GD,

266 SmallVectorImpl &ArgTys) override;

267

268 bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,

270

271

272

273 return false;

274 }

275

276 void EmitCXXDestructors(const CXXDestructorDecl *D) override;

277

278 void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,

279 FunctionArgList &Params) override;

280

281 void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;

282

283 AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,

284 const CXXConstructorDecl *D,

286 bool ForVirtualBase,

288

290 const CXXDestructorDecl *DD,

292 bool ForVirtualBase,

294

295 void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,

298 QualType ThisTy) override;

299

300 void emitVTableDefinitions(CodeGenVTables &CGVT,

301 const CXXRecordDecl *RD) override;

302

303 bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,

304 CodeGenFunction::VPtr Vptr) override;

305

306 bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {

307 return true;

308 }

309

310 llvm::Constant *

311 getVTableAddressPoint(BaseSubobject Base,

312 const CXXRecordDecl *VTableClass) override;

313

314 llvm::Value *getVTableAddressPointInStructor(

315 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,

316 BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;

317

318 llvm::Value *getVTableAddressPointInStructorWithVTT(

319 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,

320 BaseSubobject Base, const CXXRecordDecl *NearestVBase);

321

322 llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,

323 CharUnits VPtrOffset) override;

324

325 CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,

326 Address This, llvm::Type *Ty,

327 SourceLocation Loc) override;

328

329 llvm::Value *

330 EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor,

332 DeleteOrMemberCallExpr E,

333 llvm::CallBase **CallOrInvoke) override;

334

335 void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;

336

337 bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;

338 bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;

339

340 void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,

341 bool ReturnAdjustment) override {

342

343

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

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

346 CGM.setGVProperties(Thunk, GD);

347 }

348

349 bool exportThunk() override { return true; }

350

351 llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,

352 const CXXRecordDecl *UnadjustedThisClass,

353 const ThunkInfo &TI) override;

354

355 llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,

356 const CXXRecordDecl *UnadjustedRetClass,

357 const ReturnAdjustment &RA) override;

358

359 size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,

360 FunctionArgList &Args) const override {

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

362 return Args.size() - 1;

363 }

364

365 StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }

366 StringRef GetDeletedVirtualCallName() override

367 { return "__cxa_deleted_virtual"; }

368

369 CharUnits getArrayCookieSizeImpl(QualType elementType) override;

370 Address InitializeArrayCookie(CodeGenFunction &CGF,

371 Address NewPtr,

372 llvm::Value *NumElements,

373 const CXXNewExpr *expr,

374 QualType ElementType) override;

375 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,

376 Address allocPtr,

377 CharUnits cookieSize) override;

378

379 void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,

380 llvm::GlobalVariable *DeclPtr,

381 bool PerformInit) override;

382 void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,

383 llvm::FunctionCallee dtor,

384 llvm::Constant *addr) override;

385

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

387 llvm::Value *Val);

388 void EmitThreadLocalInitFuncs(

389 CodeGenModule &CGM,

390 ArrayRef<const VarDecl *> CXXThreadLocals,

391 ArrayRef<llvm::Function *> CXXThreadLocalInits,

392 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;

393

394 bool usesThreadWrapperFunction(const VarDecl *VD) const override {

395 return !isEmittedWithConstantInitializer(VD) ||

396 mayNeedDestruction(VD);

397 }

398 LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,

399 QualType LValType) override;

400

401 bool NeedsVTTParameter(GlobalDecl GD) override;

402

403 llvm::Constant *

404 getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD);

405

406

407

408protected:

409

410

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

412

413public:

414

415 enum RTTIUniquenessKind {

416

417

418 RUK_Unique,

419

420

421

422 RUK_NonUniqueHidden,

423

424

425

426

427 RUK_NonUniqueVisible

428 };

429

430

431

432 RTTIUniquenessKind

433 classifyRTTIUniqueness(QualType CanTy,

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

435 friend class ItaniumRTTIBuilder;

436

437 void emitCXXStructor(GlobalDecl GD) override;

438

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

440 LoadVTablePtr(CodeGenFunction &CGF, Address This,

441 const CXXRecordDecl *RD) override;

442

443 private:

444 llvm::Constant *

445 getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);

446

447 bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {

448 const auto &VtableLayout =

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

450

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

452

453 if (!VtableComponent.isUsedFunctionPointerKind())

454 continue;

455

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

457 const FunctionDecl *FD = Method->getDefinition();

458 const bool IsInlined =

459 Method->getCanonicalDecl()->isInlined() || (FD && FD->isInlined());

460 if (!IsInlined)

461 continue;

462

463 StringRef Name = CGM.getMangledName(

464 VtableComponent.getGlobalDecl(false));

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

466

467

468

469

470

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

472 return true;

473 }

474 return false;

475 }

476

477 bool isVTableHidden(const CXXRecordDecl *RD) const {

478 const auto &VtableLayout =

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

480

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

482 if (VtableComponent.isRTTIKind()) {

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

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

485 return true;

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

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

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

489 Method->isDefined())

490 return true;

491 }

492 }

493 return false;

494 }

495};

496

497class ARMCXXABI : public ItaniumCXXABI {

498public:

499 ARMCXXABI(CodeGen::CodeGenModule &CGM) :

500 ItaniumCXXABI(CGM, true,

501 true) {}

502

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

504

505 void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV,

506 QualType ResTy) override;

507

508 CharUnits getArrayCookieSizeImpl(QualType elementType) override;

509 Address InitializeArrayCookie(CodeGenFunction &CGF,

510 Address NewPtr,

511 llvm::Value *NumElements,

512 const CXXNewExpr *expr,

513 QualType ElementType) override;

514 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,

515 CharUnits cookieSize) override;

516};

517

518class AppleARM64CXXABI : public ARMCXXABI {

519public:

520 AppleARM64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {

521 Use32BitVTableOffsetABI = true;

522 }

523

524

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

526};

527

528class FuchsiaCXXABI final : public ItaniumCXXABI {

529public:

530 explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)

531 : ItaniumCXXABI(CGM) {}

532

533private:

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

535};

536

537class WebAssemblyCXXABI final : public ItaniumCXXABI {

538public:

539 explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM)

540 : ItaniumCXXABI(CGM, true,

541 true) {}

542 void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;

543 llvm::CallInst *

544 emitTerminateForUnexpectedException(CodeGenFunction &CGF,

545 llvm::Value *Exn) override;

546

547private:

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

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

550};

551

552class XLCXXABI final : public ItaniumCXXABI {

553public:

554 explicit XLCXXABI(CodeGen::CodeGenModule &CGM)

555 : ItaniumCXXABI(CGM) {}

556

557 void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,

558 llvm::FunctionCallee dtor,

559 llvm::Constant *addr) override;

560

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

562

563private:

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

565 llvm::Constant *addr);

566};

567}

568

571

572

573 case TargetCXXABI::GenericARM:

574 case TargetCXXABI::iOS:

575 case TargetCXXABI::WatchOS:

576 return new ARMCXXABI(CGM);

577

578 case TargetCXXABI::AppleARM64:

579 return new AppleARM64CXXABI(CGM);

580

581 case TargetCXXABI::Fuchsia:

582 return new FuchsiaCXXABI(CGM);

583

584

585

586

587 case TargetCXXABI::GenericAArch64:

588 return new ItaniumCXXABI(CGM, true,

589 true);

590

591 case TargetCXXABI::GenericMIPS:

592 return new ItaniumCXXABI(CGM, true);

593

594 case TargetCXXABI::WebAssembly:

595 return new WebAssemblyCXXABI(CGM);

596

597 case TargetCXXABI::XL:

598 return new XLCXXABI(CGM);

599

600 case TargetCXXABI::GenericItanium:

601 return new ItaniumCXXABI(CGM);

602

603 case TargetCXXABI::Microsoft:

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

605 }

606 llvm_unreachable("bad ABI kind");

607}

608

609llvm::Type *

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

612 return CGM.PtrDiffTy;

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

614}

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(

638 llvm::Value *&ThisPtrForCall,

641

645

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

647

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

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

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

651

652

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

654

655

656 llvm::Value *Adj = RawAdj;

657 if (UseARMMethodPtrABI)

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

659

660

661

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

664 ThisPtrForCall = This;

665

666

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

668

669

670

671 llvm::Value *IsVirtual;

672 if (UseARMMethodPtrABI)

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

674 else

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

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

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

678

679

680

681

683

684

691

692

693

694

695 llvm::Value *VTableOffset = FnAsInt;

696 if (!UseARMMethodPtrABI)

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

698 if (Use32BitVTableOffsetABI) {

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

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

701 }

702

703

704

705 llvm::Constant *CheckSourceLocation;

706 llvm::Constant *CheckTypeDesc;

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

708 CGM.HasHiddenLTOVisibility(RD);

709

710 if (ShouldEmitCFICheck) {

711 if (const auto *BinOp = dyn_cast(E)) {

712 if (BinOp->isPtrMemOp() &&

713 BinOp->getRHS()

714 ->getType()

715 ->hasPointeeToCFIUncheckedCalleeFunctionType())

716 ShouldEmitCFICheck = false;

717 }

718 }

719

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

721 CGM.HasHiddenLTOVisibility(RD);

722

723

724

725 bool ShouldEmitWPDInfo =

726 (CGM.getCodeGenOpts().WholeProgramVTables &&

727

728 !CGM.AlwaysHasLTOVisibilityPublic(RD)) ||

729 CGM.getCodeGenOpts().DevirtualizeSpeculatively;

730 llvm::Value *VirtualFn = nullptr;

731

732 {

733 auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;

734 auto CheckHandler = SanitizerHandler::CFICheckFail;

735 SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);

736

737 llvm::Value *TypeId = nullptr;

738 llvm::Value *CheckResult = nullptr;

739

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

741

742

743 llvm::Metadata *MD =

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

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

746 }

747

748 if (ShouldEmitVFEInfo) {

749 llvm::Value *VFPAddr =

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

751

752

753

754

755

756

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

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

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

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

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

762 } else {

763

764

765 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {

766 llvm::Value *VFPAddr =

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

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

769 ? llvm::Intrinsic::type_test

770 : llvm::Intrinsic::public_type_test;

771

772 CheckResult =

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

774 }

775

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

777 VirtualFn = CGF.Builder.CreateCall(

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

779 {VTableOffset->getType()}),

780 {VTable, VTableOffset});

781 } else {

782 llvm::Value *VFPAddr =

786 "memptr.virtualfn");

787 }

788 }

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

790 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||

791 CheckResult) &&

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

793

794 if (ShouldEmitCFICheck) {

795

798 llvm::Constant *StaticData[] = {

800 CheckSourceLocation,

801 CheckTypeDesc,

802 };

803

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

806 } else {

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

808 CGM.getLLVMContext(),

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

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

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

812 CGF.EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler,

813 StaticData, {VTable, ValidVtable});

814 }

815

816 FnVirtual = Builder.GetInsertBlock();

817 }

818 }

819

821

822

823

825 llvm::Value *NonVirtualFn =

826 Builder.CreateIntToPtr(FnAsInt, CGF.DefaultPtrTy, "memptr.nonvirtualfn");

827

828

829 if (ShouldEmitCFICheck) {

832 auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;

833 auto CheckHandler = SanitizerHandler::CFICheckFail;

834 SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);

835

836 llvm::Constant *StaticData[] = {

838 CheckSourceLocation,

839 CheckTypeDesc,

840 };

841

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

843 for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {

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

845 getContext().getMemberPointerType(MPT->getPointeeType(),

846 std::nullopt,

847 Base->getCanonicalDecl()));

848 llvm::Value *TypeId =

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

850

851 llvm::Value *TypeTest =

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

853 {NonVirtualFn, TypeId});

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

855 }

856

857 CGF.EmitCheck(std::make_pair(Bit, CheckOrdinal), CheckHandler, StaticData,

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

859

860 FnNonVirtual = Builder.GetInsertBlock();

861 }

862 }

863

864

866 llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.DefaultPtrTy, 2);

867 CalleePtr->addIncoming(VirtualFn, FnVirtual);

868 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);

869

870 CGPointerAuthInfo PointerAuth;

871

872 if (const auto &Schema =

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

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

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

876 FnVirtual);

877 const auto &AuthInfo =

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

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

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

881 auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator();

882 DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual);

883 PointerAuth = CGPointerAuthInfo(

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

885 Schema.authenticatesNullValues(), DiscriminatorPHI);

886 }

887

888 CGCallee Callee(FPT, CalleePtr, PointerAuth);

890}

891

892

893

894llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(

895 CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr,

896 const MemberPointerType *MPT, bool IsInBounds) {

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

898

899 CGBuilderTy &Builder = CGF.Builder;

900

901

902 llvm::Value *BaseAddr = Base.emitRawPointer(CGF);

903 return Builder.CreateGEP(CGF.Int8Ty, BaseAddr, MemPtr, "memptr.offset",

904 IsInBounds ? llvm::GEPNoWrapFlags::inBounds()

905 : llvm::GEPNoWrapFlags::none());

906}

907

908

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

913

914 if (!CPA)

915 return nullptr;

916

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

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

920 "unexpected key or discriminators");

921

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

925}

926

927

928

929

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949

950llvm::Value *

951ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,

953 llvm::Value *src) {

954

957

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

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

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

961

962 CGBuilderTy &Builder = CGF.Builder;

963 QualType DstType = E->getType();

964

966 if (const auto &NewAuthInfo =

967 CGM.getMemberFunctionPointerAuthInfo(DstType)) {

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

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

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

973

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

977

978

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

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

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

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

983 llvm::Value *IsVirtualOffset =

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

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

986

988 llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());

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

990 MemFnPtr =

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

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

995 ResignBB = Builder.GetInsertBlock();

996

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

999 NewSrc->addIncoming(src, StartBB);

1000 NewSrc->addIncoming(ResignedVal, ResignBB);

1001 src = NewSrc;

1002 }

1003 }

1004

1005

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

1007

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

1009 if (!adj) return src;

1010

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

1012

1013 const MemberPointerType *destTy =

1015

1016

1017

1019 llvm::Value *dst;

1020 if (isDerivedToBase)

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

1022 else

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

1024

1025

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

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

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

1029 }

1030

1031

1032 if (UseARMMethodPtrABI) {

1034 offset <<= 1;

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

1036 }

1037

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

1039 llvm::Value *dstAdj;

1040 if (isDerivedToBase)

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

1042 else

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

1044

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

1046}

1047

1048static llvm::Constant *

1053 "member function pointers expected");

1054 if (DestType == SrcType)

1055 return Src;

1056

1059

1060 if (!NewAuthInfo && !CurAuthInfo)

1061 return Src;

1062

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

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

1065

1067 return Src;

1068 }

1069

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

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

1073 return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0);

1074}

1075

1076llvm::Constant *

1077ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,

1078 llvm::Constant *src) {

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

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

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

1082

1083 QualType DstType = E->getType();

1084

1088

1089

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

1091

1092

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

1094 if (!adj) return src;

1095

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

1097

1098 const MemberPointerType *destTy =

1100

1101

1102

1104

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

1106

1107 if (isDerivedToBase)

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

1109 else

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

1111 }

1112

1113

1114 if (UseARMMethodPtrABI) {

1116 offset <<= 1;

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

1118 }

1119

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

1121 llvm::Constant *dstAdj;

1122 if (isDerivedToBase)

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

1124 else

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

1126

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

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

1129 return res;

1130}

1131

1132llvm::Constant *

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

1134

1135

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

1138

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

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

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

1142}

1143

1144llvm::Constant *

1145ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,

1146 CharUnits offset) {

1147

1148

1149

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

1151}

1152

1153llvm::Constant *

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

1156}

1157

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

1159 CharUnits ThisAdjustment) {

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

1161

1162 CodeGenTypes &Types = CGM.getTypes();

1163

1164

1165 llvm::Constant *MemPtr[2];

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

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

1170

1171 VTableOffset = Index * 4;

1172 } else {

1173 const ASTContext &Context = getContext();

1176 VTableOffset = Index * PointerWidth.getQuantity();

1177 }

1178

1179 if (UseARMMethodPtrABI) {

1180

1181

1182

1183

1184

1185

1186

1187

1188

1189

1190

1191

1192

1193

1194

1195

1196

1197

1198

1199

1200

1201 const auto &Schema =

1202 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;

1203 if (Schema)

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

1205 getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy);

1206 else

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

1208

1209

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

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

1212 } else {

1213

1214

1215

1216

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

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

1220 }

1221 } else {

1222 const FunctionProtoType *FPT = MD->getType()->castAs();

1223 llvm::Type *Ty;

1224

1226

1228 } else {

1229

1230

1231 Ty = CGM.PtrDiffTy;

1232 }

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

1234

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

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

1237 (UseARMMethodPtrABI ? 2 : 1) *

1239 }

1240

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

1242}

1243

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

1245 QualType MPType) {

1246 const MemberPointerType *MPT = MPType->castAs();

1248 if (!MPD)

1249 return EmitNullMemberPointer(MPT);

1250

1251 CharUnits ThisAdjustment = getContext().getMemberPointerPathAdjustment(MP);

1252

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

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

1255 QualType SrcType = getContext().getMemberPointerType(

1256 MD->getType(), std::nullopt, MD->getParent());

1258 }

1259

1260 CharUnits FieldOffset =

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

1262 return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);

1263}

1264

1265

1266

1267

1268

1269llvm::Value *

1270ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,

1271 llvm::Value *L,

1272 llvm::Value *R,

1273 const MemberPointerType *MPT,

1274 bool Inequality) {

1275 CGBuilderTy &Builder = CGF.Builder;

1276

1277 llvm::ICmpInst::Predicate Eq;

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

1279 if (Inequality) {

1280 Eq = llvm::ICmpInst::ICMP_NE;

1281 And = llvm::Instruction::Or;

1282 Or = llvm::Instruction::And;

1283 } else {

1284 Eq = llvm::ICmpInst::ICMP_EQ;

1285 And = llvm::Instruction::And;

1286 Or = llvm::Instruction::Or;

1287 }

1288

1289

1290

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

1293

1294

1295

1296

1297

1298

1299

1300

1301

1302

1303

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

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

1306

1307

1308

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

1310

1311

1312

1313

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

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

1316

1317

1318

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

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

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

1322

1323

1324

1325 if (UseARMMethodPtrABI) {

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

1327

1328

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

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

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

1332 "cmp.or.adj");

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

1334 }

1335

1336

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

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

1341}

1342

1343llvm::Value *

1344ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,

1345 llvm::Value *MemPtr,

1346 const MemberPointerType *MPT) {

1347 CGBuilderTy &Builder = CGF.Builder;

1348

1349

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

1352 llvm::Value *NegativeOne =

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

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

1355 }

1356

1357

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

1359

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

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

1362

1363

1364

1365 if (UseARMMethodPtrABI) {

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

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

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

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

1370 "memptr.isvirtual");

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

1372 }

1373

1375}

1376

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

1378 const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();

1379 if (!RD)

1380 return false;

1381

1382

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

1386 Align, CGM.getDataLayout().getAllocaAddrSpace(),

1387 false);

1388 return true;

1389 }

1390 return false;

1391}

1392

1393

1394

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

1397}

1398

1399

1400

1401void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,

1402 const CXXDeleteExpr *DE,

1403 Address Ptr,

1404 QualType ElementType,

1405 const CXXDestructorDecl *Dtor) {

1407 if (UseGlobalDelete) {

1408

1409

1410

1411

1414

1415

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

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

1420

1421

1423 CompletePtr =

1425

1426

1427

1429 ElementType);

1430 }

1431

1432

1433

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

1436 nullptr);

1437

1438 if (UseGlobalDelete)

1440}

1441

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

1443

1444

1445 llvm::FunctionType *FTy =

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

1447

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

1449

1450 if (isNoReturn)

1452 else

1454}

1455

1457

1458

1459 llvm::FunctionType *FTy =

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

1461

1463}

1464

1466

1467

1468

1470 llvm::FunctionType *FTy =

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

1472

1474}

1475

1476void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {

1478

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

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

1481

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

1485

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

1489

1490

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

1492 true);

1493

1494

1495

1496 llvm::Constant *Dtor = nullptr;

1499

1500

1501

1502 const ASTContext &Ctx = getContext();

1504 FunctionProtoType::ExtProtoInfo());

1505

1506 CXXDestructorDecl *DtorD = Record->getDestructor();

1507 Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));

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

1509 }

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

1511

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

1514}

1515

1517

1518

1519

1520

1521

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

1524 llvm::Type *PtrDiffTy =

1526

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

1528

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

1530

1531

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

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

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

1536 llvm::AttributeList Attrs = llvm::AttributeList::get(

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

1538

1540}

1541

1543

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

1546}

1547

1548

1549

1553 CXXBasePaths Paths(true, true,

1554 false);

1555

1556

1557

1560

1561 unsigned NumPublicPaths = 0;

1563

1564

1566 if (Path.Access != AS_public)

1567 continue;

1568

1569 ++NumPublicPaths;

1570

1572

1573

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

1576

1577 if (NumPublicPaths > 1)

1578 continue;

1579

1580

1581 const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class);

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

1584 }

1585 }

1586

1587

1588 if (NumPublicPaths == 0)

1590

1591

1592 if (NumPublicPaths > 1)

1594

1595

1596

1597 return Offset;

1598}

1599

1601

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

1603

1605}

1606

1607bool ItaniumCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {

1608 return true;

1609}

1610

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

1614 Call->setDoesNotReturn();

1615 CGF.Builder.CreateUnreachable();

1616}

1617

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

1619 QualType SrcRecordTy,

1620 Address ThisPtr,

1621 llvm::Type *StdTypeInfoPtrTy) {

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

1624 ClassDecl);

1625

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

1627

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

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

1631 } else {

1632

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

1635 }

1638}

1639

1640bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,

1641 QualType SrcRecordTy) {

1642 return SrcIsPtr;

1643}

1644

1645llvm::Value *ItaniumCXXABI::emitDynamicCastCall(

1646 CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,

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

1648 llvm::Type *PtrDiffLTy =

1650

1651 llvm::Value *SrcRTTI =

1653 llvm::Value *DestRTTI =

1655

1656

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

1660 PtrDiffLTy,

1662

1663

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

1666

1667

1668

1669

1670

1671 llvm::Value *Vtable =

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

1673 CodeGenFunction::VTableAuthMode::MustTrap);

1674 assert(Vtable);

1675 (void)Vtable;

1676 }

1677

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

1680

1681

1682

1684 llvm::BasicBlock *BadCastBlock =

1686

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

1689

1691 EmitBadCastCall(CGF);

1692 }

1693

1695}

1696

1697std::optionalCGCXXABI::ExactDynamicCastInfo

1698ItaniumCXXABI::getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,

1699 QualType DestRecordTy) {

1700 assert(shouldEmitExactDynamicCast(DestRecordTy));

1701

1702 ASTContext &Context = getContext();

1703

1704

1707 CXXBasePaths Paths(true, true,

1708 false);

1710

1711

1712

1713 std::optional Offset;

1714 for (const CXXBasePath &Path : Paths) {

1715

1717 continue;

1718

1719 CharUnits PathOffset;

1720 for (const CXXBasePathElement &PathElement : Path) {

1721

1722 const CXXRecordDecl *Base =

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

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

1725

1726

1729 } else {

1730 const ASTRecordLayout &L =

1733 }

1734 }

1735

1736 if (!Offset)

1737 Offset = PathOffset;

1738 else if (Offset != PathOffset) {

1739

1740 return ExactDynamicCastInfo{true,

1742 }

1743 }

1744 if (!Offset)

1745 return std::nullopt;

1746 return ExactDynamicCastInfo{false, *Offset};

1747}

1748

1749llvm::Value *ItaniumCXXABI::emitExactDynamicCast(

1750 CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,

1751 QualType DestTy, QualType DestRecordTy,

1752 const ExactDynamicCastInfo &ExactCastInfo, llvm::BasicBlock *CastSuccess,

1753 llvm::BasicBlock *CastFail) {

1756 auto AuthenticateVTable = [&](Address ThisAddr, const CXXRecordDecl *Decl) {

1757 if (!CGF.getLangOpts().PointerAuthCalls)

1758 return;

1760 CodeGenFunction::VTableAuthMode::MustTrap);

1761 };

1762

1763 bool PerformPostCastAuthentication = false;

1764 llvm::Value *VTable = nullptr;

1765 if (ExactCastInfo.RequiresCastToPrimaryBase) {

1766

1767

1768

1769

1770 llvm::Value *PrimaryBase =

1773 SrcDecl = DestDecl;

1774

1775

1776

1777 PerformPostCastAuthentication = CGF.getLangOpts().PointerAuthCalls;

1778 CGPointerAuthInfo StrippingAuthInfo(0, PointerAuthenticationMode::Strip,

1779 false, false, nullptr);

1782 if (PerformPostCastAuthentication)

1784 } else

1786

1787

1788

1789 llvm::Constant *ExpectedVTable = getVTableAddressPoint(

1790 BaseSubobject(SrcDecl, ExactCastInfo.Offset), DestDecl);

1791 llvm::Value *Success = CGF.Builder.CreateICmpEQ(VTable, ExpectedVTable);

1792 llvm::Value *AdjustedThisPtr = ThisAddr.emitRawPointer(CGF);

1793

1794 if (!ExactCastInfo.Offset.isZero()) {

1796 llvm::Constant *OffsetConstant =

1797 llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset);

1799 OffsetConstant);

1800 PerformPostCastAuthentication = CGF.getLangOpts().PointerAuthCalls;

1801 }

1802

1803 if (PerformPostCastAuthentication) {

1804

1805

1806 llvm::BasicBlock *NonNullBlock = CGF.Builder.GetInsertBlock();

1807 llvm::BasicBlock *PostCastAuthSuccess =

1809 llvm::BasicBlock *PostCastAuthComplete =

1811 CGF.Builder.CreateCondBr(Success, PostCastAuthSuccess,

1812 PostCastAuthComplete);

1813 CGF.EmitBlock(PostCastAuthSuccess);

1814 Address AdjustedThisAddr =

1816 AuthenticateVTable(AdjustedThisAddr, DestDecl);

1817 CGF.EmitBranch(PostCastAuthComplete);

1818 CGF.EmitBlock(PostCastAuthComplete);

1819 llvm::PHINode *PHI = CGF.Builder.CreatePHI(AdjustedThisPtr->getType(), 2);

1820 PHI->addIncoming(AdjustedThisPtr, PostCastAuthSuccess);

1821 llvm::Value *NullValue =

1822 llvm::Constant::getNullValue(AdjustedThisPtr->getType());

1823 PHI->addIncoming(NullValue, NonNullBlock);

1824 AdjustedThisPtr = PHI;

1825 }

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

1827 return AdjustedThisPtr;

1828}

1829

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

1831 Address ThisAddr,

1832 QualType SrcRecordTy) {

1834 llvm::Value *OffsetToTop;

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

1836

1837 llvm::Value *VTable =

1839

1840

1841 OffsetToTop =

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

1845 } else {

1846 llvm::Type *PtrDiffLTy =

1848

1849

1850 llvm::Value *VTable =

1852

1853

1854 OffsetToTop =

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

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

1858 }

1859

1861 OffsetToTop);

1862}

1863

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

1867 Call->setDoesNotReturn();

1868 CGF.Builder.CreateUnreachable();

1869 return true;

1870}

1871

1872llvm::Value *

1873ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,

1874 Address This,

1875 const CXXRecordDecl *ClassDecl,

1876 const CXXRecordDecl *BaseClassDecl) {

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

1878 CharUnits VBaseOffsetOffset =

1879 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,

1880 BaseClassDecl);

1881 llvm::Value *VBaseOffsetPtr =

1882 CGF.Builder.CreateConstGEP1_64(

1884 "vbase.offset.ptr");

1885

1886 llvm::Value *VBaseOffset;

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

1890 "vbase.offset");

1891 } else {

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

1894 }

1895 return VBaseOffset;

1896}

1897

1898void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {

1899

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

1901

1902

1903

1904 CGM.EmitGlobal(GlobalDecl(D, Ctor_Base));

1905

1906

1907

1909

1911 }

1912}

1913

1914CGCXXABI::AddedStructorArgCounts

1915ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,

1916 SmallVectorImpl &ArgTys) {

1917 ASTContext &Context = getContext();

1918

1919

1920

1921

1922

1926 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);

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

1930 return AddedStructorArgCounts::prefix(1);

1931 }

1932 return AddedStructorArgCounts{};

1933}

1934

1935void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {

1936

1937

1938 CGM.EmitGlobal(GlobalDecl(D, Dtor_Base));

1939

1940

1941

1943

1944

1945

1946

1949}

1950

1951void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,

1952 QualType &ResTy,

1953 FunctionArgList &Params) {

1956

1957

1958 if (NeedsVTTParameter(CGF.CurGD)) {

1959 ASTContext &Context = getContext();

1960

1961

1962 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);

1967 T, ImplicitParamKind::CXXVTT);

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

1969 getStructorImplicitParamDecl(CGF) = VTTDecl;

1970 }

1971}

1972

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

1974

1976 return;

1977

1978

1979

1980 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));

1981

1982

1983 if (getStructorImplicitParamDecl(CGF)) {

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

1986 }

1987

1988

1989

1990

1991

1992

1993

1994

1995

1996 if (HasThisReturn(CGF.CurGD))

1998}

1999

2000CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(

2001 CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,

2002 bool ForVirtualBase, bool Delegating) {

2003 if (!NeedsVTTParameter(GlobalDecl(D, Type)))

2004 return AddedStructorArgs{};

2005

2006

2007

2008

2009 llvm::Value *VTT =

2011 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);

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

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

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

2015}

2016

2017llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(

2018 CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type,

2019 bool ForVirtualBase, bool Delegating) {

2020 GlobalDecl GD(DD, Type);

2022}

2023

2024void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,

2025 const CXXDestructorDecl *DD,

2028 QualType ThisTy) {

2029 GlobalDecl GD(DD, Type);

2030 llvm::Value *VTT =

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

2033

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

2038 else

2040

2042 ThisTy, VTT, VTTTy, nullptr);

2043}

2044

2045

2046template

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

2052 continue;

2054 return true;

2055 }

2056 }

2057

2058 return false;

2059}

2060

2062 llvm::GlobalVariable *VTable,

2064 if (VTable->getDLLStorageClass() !=

2065 llvm::GlobalVariable::DefaultStorageClass ||

2066 RD->hasAttr() || RD->hasAttr())

2067 return;

2068

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

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

2074}

2075

2076void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,

2077 const CXXRecordDecl *RD) {

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

2079 if (VTable->hasInitializer())

2080 return;

2081

2082 ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();

2083 const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);

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

2085 llvm::Constant *RTTI =

2086 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getCanonicalTagType(RD));

2087

2088

2089 ConstantInitBuilder builder(CGM);

2090 auto components = builder.beginStruct();

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

2093 components.finishAndSetAsInitializer(VTable);

2094

2095

2096 VTable->setLinkage(Linkage);

2097

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

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

2100

2101 if (CGM.getTarget().hasPS4DLLImportExport())

2103

2104

2105 CGM.setGVProperties(VTable, RD);

2106

2107

2108

2109

2116 EmitFundamentalRTTIDescriptors(RD);

2117

2118

2119

2120

2121

2122

2123

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

2125 CGM.getCodeGenOpts().WholeProgramVTables ||

2126 CGM.getCodeGenOpts().DevirtualizeSpeculatively) {

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

2128

2129

2130

2131 if (VTable->isDeclarationForLinker()) {

2132 assert(CGM.getCodeGenOpts().WholeProgramVTables ||

2133 CGM.getCodeGenOpts().DevirtualizeSpeculatively);

2134 CGM.addCompilerUsedGlobal(VTable);

2135 }

2136 }

2137

2140 if (!VTable->isDSOLocal())

2142 }

2143

2144

2145 if (CGDebugInfo *DI = CGM.getModuleDebugInfo())

2146 DI->emitVTableSymbol(VTable, RD);

2147}

2148

2149bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(

2150 CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {

2152 return false;

2153 return NeedsVTTParameter(CGF.CurGD);

2154}

2155

2156llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(

2157 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,

2158 const CXXRecordDecl *NearestVBase) {

2159

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

2161 NeedsVTTParameter(CGF.CurGD)) {

2162 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,

2163 NearestVBase);

2164 }

2165 return getVTableAddressPoint(Base, VTableClass);

2166}

2167

2168llvm::Constant *

2169ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,

2170 const CXXRecordDecl *VTableClass) {

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

2172

2173

2174

2175 const VTableLayout &Layout =

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

2177 VTableLayout::AddressPointLocation AddressPoint =

2179 llvm::Value *Indices[] = {

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

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

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

2183 };

2184

2185

2186

2187 unsigned ComponentSize =

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

2189 unsigned VTableSize =

2191 unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;

2192 llvm::ConstantRange InRange(

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

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

2195 return llvm::ConstantExpr::getGetElementPtr(

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

2197}

2198

2199llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(

2200 CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,

2201 const CXXRecordDecl *NearestVBase) {

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

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

2204

2205

2206 uint64_t VirtualPointerIndex =

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

2208

2209

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

2211 if (VirtualPointerIndex)

2213 VirtualPointerIndex);

2214

2215

2216 llvm::Value *AP =

2219

2222 GlobalDecl(),

2223 QualType());

2225 }

2226

2227 return AP;

2228}

2229

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

2231 CharUnits VPtrOffset) {

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

2233

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

2235 if (VTable)

2236 return VTable;

2237

2238

2239 CGM.addDeferredVTable(RD);

2240

2241 SmallString<256> Name;

2242 llvm::raw_svector_ostream Out(Name);

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

2244

2245 const VTableLayout &VTLayout =

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

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

2248

2249

2250

2251

2252 unsigned PAlign = CGM.getVtableGlobalVarAlignment();

2253

2254 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(

2255 Name, VTableType, llvm::GlobalValue::ExternalLinkage,

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

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

2258

2259 if (CGM.getTarget().hasPS4DLLImportExport())

2261

2262 CGM.setGVProperties(VTable, RD);

2263 return VTable;

2264}

2265

2266CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,

2267 GlobalDecl GD,

2268 Address This,

2269 llvm::Type *Ty,

2270 SourceLocation Loc) {

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

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

2274

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

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

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

2278

2279 llvm::Type *ComponentTy = CGM.getVTables().getVTableComponentType();

2281 VTableIndex * CGM.getDataLayout().getTypeSizeInBits(ComponentTy) / 8;

2282

2285 PtrTy, ByteOffset);

2286 } else {

2288

2289 llvm::Value *VFuncLoad;

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

2291 VFuncLoad = CGF.Builder.CreateCall(

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

2293 {VTable, llvm::ConstantInt::get(CGM.Int32Ty, ByteOffset)});

2294 } else {

2295 VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64(

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

2299 }

2300

2301

2302

2303

2304

2305

2306

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

2308 CGM.getCodeGenOpts().StrictVTablePointers) {

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

2310 VFuncLoadInstr->setMetadata(

2311 llvm::LLVMContext::MD_invariant_load,

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

2313 llvm::ArrayRef<llvm::Metadata *>()));

2314 }

2315 }

2316 VFunc = VFuncLoad;

2317 }

2318

2319 CGPointerAuthInfo PointerAuth;

2320 if (Schema) {

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

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

2323 PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType());

2324 }

2325 CGCallee Callee(GD, VFunc, PointerAuth);

2327}

2328

2329llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(

2330 CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,

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

2332 auto *CE = dyn_cast<const CXXMemberCallExpr *>(E);

2333 auto *D = dyn_cast<const CXXDeleteExpr *>(E);

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

2335 assert(CE == nullptr || CE->arguments().empty());

2337

2338 GlobalDecl GD(Dtor, DtorType);

2339 const CGFunctionInfo *FInfo =

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

2343

2344 QualType ThisTy;

2345 if (CE) {

2346 ThisTy = CE->getObjectType();

2347 } else {

2348 ThisTy = D->getDestroyedType();

2349 }

2350

2352 nullptr, QualType(), nullptr, CallOrInvoke);

2353 return nullptr;

2354}

2355

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

2357 CodeGenVTables &VTables = CGM.getVTables();

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

2360}

2361

2362bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(

2363 const CXXRecordDecl *RD) const {

2364

2365

2366 if (CGM.getLangOpts().AppleKext)

2367 return false;

2368

2369

2370

2371 if (isVTableHidden(RD))

2372 return false;

2373

2374 if (CGM.getCodeGenOpts().ForceEmitVTables)

2375 return true;

2376

2377

2378

2379

2380

2381

2382

2383

2384

2385

2386

2387

2388

2389

2390

2391 if (hasAnyUnusedVirtualInlineFunction(RD))

2392 return false;

2393

2394

2395

2396

2397

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

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

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

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

2403 continue;

2404 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))

2405 return false;

2406 }

2407 }

2408

2409 return true;

2410}

2411

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

2413 if (!canSpeculativelyEmitVTableAsBaseClass(RD))

2414 return false;

2415

2417 return false;

2418

2419

2420

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

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

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

2424 if (!BRD->isDynamicClass())

2425 continue;

2426 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))

2427 return false;

2428 }

2429

2430 return true;

2431}

2435 int64_t NonVirtualAdjustment,

2436 int64_t VirtualAdjustment,

2437 bool IsReturnAdjustment) {

2438 if (!NonVirtualAdjustment && !VirtualAdjustment)

2440

2442

2443

2444 if (NonVirtualAdjustment && !IsReturnAdjustment) {

2447 }

2448

2449

2450 llvm::Value *ResultPtr;

2451 if (VirtualAdjustment) {

2452 llvm::Value *VTablePtr =

2454

2455 llvm::Value *Offset;

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

2457 CGF.Int8Ty, VTablePtr, VirtualAdjustment);

2459

2460 Offset =

2463 } else {

2464 llvm::Type *PtrDiffTy =

2466

2467

2470 }

2471

2473 V.emitRawPointer(CGF), Offset);

2474 } else {

2475 ResultPtr = V.emitRawPointer(CGF);

2476 }

2477

2478

2479

2480 if (NonVirtualAdjustment && IsReturnAdjustment) {

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

2482 NonVirtualAdjustment);

2483 }

2484

2485 return ResultPtr;

2486}

2487

2488llvm::Value *

2489ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This,

2490 const CXXRecordDecl *UnadjustedClass,

2491 const ThunkInfo &TI) {

2494 false);

2495}

2496

2497llvm::Value *

2498ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,

2499 const CXXRecordDecl *UnadjustedClass,

2500 const ReturnAdjustment &RA) {

2503 true);

2504}

2505

2506void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,

2507 RValue RV, QualType ResultType) {

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

2510

2511

2513 RValue Undef = RValue::get(llvm::UndefValue::get(T));

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

2515}

2516

2517

2518

2519CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {

2520

2521

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

2524}

2525

2526Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,

2527 Address NewPtr,

2528 llvm::Value *NumElements,

2529 const CXXNewExpr *expr,

2530 QualType ElementType) {

2531 assert(requiresArrayCookie(expr));

2532

2534

2535 ASTContext &Ctx = getContext();

2537

2538

2539 CharUnits CookieSize =

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

2542

2543

2544 Address CookiePtr = NewPtr;

2545 CharUnits CookieOffset = CookieSize - SizeSize;

2546 if (!CookieOffset.isZero())

2548

2549

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

2552

2553

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

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

2556 CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {

2557

2558 SI->setNoSanitizeMetadata();

2559 llvm::FunctionType *FTy =

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

2561 llvm::FunctionCallee F =

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

2564 }

2565

2566

2567

2569}

2570

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

2572 Address allocPtr,

2573 CharUnits cookieSize) {

2574

2575 Address numElementsPtr = allocPtr;

2576 CharUnits numElementsOffset = cookieSize - CGF.getSizeSize();

2577 if (!numElementsOffset.isZero())

2578 numElementsPtr =

2580

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

2585

2586

2587

2588

2589

2590 llvm::FunctionType *FTy =

2592 llvm::FunctionCallee F =

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

2595}

2596

2597CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {

2598

2599

2600

2601

2602

2603

2604

2605

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

2608}

2609

2610Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,

2611 Address newPtr,

2612 llvm::Value *numElements,

2613 const CXXNewExpr *expr,

2614 QualType elementType) {

2615 assert(requiresArrayCookie(expr));

2616

2617

2618 Address cookie = newPtr;

2619

2620

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

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

2625

2626

2629

2630

2631

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

2634}

2635

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

2637 Address allocPtr,

2638 CharUnits cookieSize) {

2639

2640

2641 Address numElementsPtr

2643

2646}

2647

2648

2649

2651 llvm::PointerType *GuardPtrTy) {

2652

2653 llvm::FunctionType *FTy =

2655 GuardPtrTy, false);

2657 FTy, "__cxa_guard_acquire",

2659 llvm::AttributeList::FunctionIndex,

2660 llvm::Attribute::NoUnwind));

2661}

2662

2664 llvm::PointerType *GuardPtrTy) {

2665

2666 llvm::FunctionType *FTy =

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

2669 FTy, "__cxa_guard_release",

2671 llvm::AttributeList::FunctionIndex,

2672 llvm::Attribute::NoUnwind));

2673}

2674

2676 llvm::PointerType *GuardPtrTy) {

2677

2678 llvm::FunctionType *FTy =

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

2681 FTy, "__cxa_guard_abort",

2683 llvm::AttributeList::FunctionIndex,

2684 llvm::Attribute::NoUnwind));

2685}

2686

2687namespace {

2688 struct CallGuardAbort final : EHScopeStack::Cleanup {

2689 llvm::GlobalVariable *Guard;

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

2691

2692 void Emit(CodeGenFunction &CGF, Flags flags) override {

2694 Guard);

2695 }

2696 };

2697}

2698

2699

2700

2701void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,

2702 const VarDecl &D,

2703 llvm::GlobalVariable *var,

2704 bool shouldPerformInit) {

2705 CGBuilderTy &Builder = CGF.Builder;

2706

2707

2708

2709 bool NonTemplateInline =

2712

2713

2714

2715

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

2719

2720

2721

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

2723

2724 llvm::IntegerType *guardTy;

2725 CharUnits guardAlignment;

2726 if (useInt8GuardVariable) {

2727 guardTy = CGF.Int8Ty;

2729 } else {

2730

2731

2732 if (UseARMGuardVarABI) {

2733 guardTy = CGF.SizeTy;

2735 } else {

2737 guardAlignment =

2739 }

2740 }

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

2744

2745

2746

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

2748 if (!guard) {

2749

2750 SmallString<256> guardName;

2751 {

2752 llvm::raw_svector_ostream out(guardName);

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

2754 }

2755

2756

2757

2758

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

2760 false, var->getLinkage(),

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

2762 guardName.str());

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

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

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

2766

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

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

2769

2770

2771

2772

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

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

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

2777 guard->setComdat(C);

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

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

2780 }

2781

2782 CGM.setStaticLocalDeclGuardAddress(&D, guard);

2783 }

2784

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

2786

2787

2788

2789

2790

2791

2792

2793

2794

2795

2796

2797

2798

2799

2800

2801

2802

2803

2804

2805

2806

2807

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

2810 if (!threadsafe || MaxInlineWidthInBits) {

2811

2812 llvm::LoadInst *LI =

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

2814

2815

2816

2817

2818

2819

2820

2821 if (threadsafe)

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

2823

2824

2825

2826

2827

2828

2829

2830

2831

2832

2833

2834

2835

2836

2837

2838

2839

2840

2841

2842

2843

2844 llvm::Value *V =

2845 (UseARMGuardVarABI && !useInt8GuardVariable)

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

2847 : LI;

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

2849

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

2851

2852

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

2855

2857 }

2858

2859

2860

2861

2862

2863

2864

2865

2866

2867

2868

2869

2870

2871

2872

2873

2874

2875 if (threadsafe) {

2876

2877 llvm::Value *V

2879

2881

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

2883 InitBlock, EndBlock);

2884

2885

2887

2890

2891

2892

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

2895 }

2896

2897

2899

2900 if (threadsafe) {

2901

2903

2904

2908

2909

2910

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

2913 }

2914

2916}

2917

2918

2920 llvm::FunctionCallee dtor,

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

2923 "unexpected call to emitGlobalDtorWithCXAAtExit");

2925 "__cxa_atexit is disabled");

2926 const char *Name = "__cxa_atexit";

2927 if (TLS) {

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

2930 }

2931

2932

2933

2935

2936

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

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

2940

2941

2942 llvm::Constant *handle =

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

2946

2947

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

2949 llvm::FunctionType *atexitTy =

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

2951

2952

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

2955 fn->setDoesNotThrow();

2956

2959 false, false));

2961 Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI);

2964

2965 if (!addr)

2966

2967

2968

2969

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

2971

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

2974}

2975

2977 StringRef FnName) {

2978

2979

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

2983

2984 return GlobalInitOrCleanupFn;

2985}

2986

2987void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {

2988 for (const auto &I : DtorsUsingAtExit) {

2989 int Priority = I.first;

2990 std::string GlobalCleanupFnName =

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

2992

2993 llvm::Function *GlobalCleanupFn =

2995

2996 CodeGenFunction CGF(*this);

2997 CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalCleanupFn,

2998 getTypes().arrangeNullaryFunction(), FunctionArgList(),

2999 SourceLocation(), SourceLocation());

3001

3002

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

3004

3005

3006

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

3008 auto itv = Dtors.rbegin();

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

3010 llvm::Function *Dtor = *itv;

3011

3012

3013

3015 llvm::Value *NeedsDestruct =

3017

3018 llvm::BasicBlock *DestructCallBlock =

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

3022

3023

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

3025

3026 CGF.EmitBlock(DestructCallBlock);

3027

3028

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

3030

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

3032

3034

3035 itv++;

3036 }

3037

3039 AddGlobalDtor(GlobalCleanupFn, Priority);

3040 }

3041}

3042

3043void CodeGenModule::registerGlobalDtorsWithAtExit() {

3044 for (const auto &I : DtorsUsingAtExit) {

3045 int Priority = I.first;

3046 std::string GlobalInitFnName =

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

3048 llvm::Function *GlobalInitFn =

3050

3051 CodeGenFunction CGF(*this);

3052 CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalInitFn,

3053 getTypes().arrangeNullaryFunction(), FunctionArgList(),

3054 SourceLocation(), SourceLocation());

3056

3057

3058

3059

3060

3061

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

3063 for (auto *Dtor : Dtors) {

3064

3065

3066 if (getCodeGenOpts().CXAAtExit) {

3068 } else {

3069

3070

3072 }

3073 }

3074

3076 AddGlobalCtor(GlobalInitFn, Priority);

3077 }

3078

3079 if (getCXXABI().useSinitAndSterm())

3080 unregisterGlobalDtorsWithUnAtExit();

3081}

3082

3083

3084void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,

3085 llvm::FunctionCallee dtor,

3086 llvm::Constant *addr) {

3088 return;

3089

3090

3091 if (CGM.getLangOpts().HLSL)

3092 return CGM.AddCXXDtorEntry(dtor, addr);

3093

3094

3095

3096

3097

3098

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

3101

3102

3103

3104

3105

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

3108

3109

3110

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

3112

3113 return CGM.AddCXXDtorEntry(dtor, addr);

3114 }

3115

3117}

3118

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

3122

3123

3126}

3127

3128

3129

3130

3131static llvm::GlobalValue::LinkageTypes

3133 llvm::GlobalValue::LinkageTypes VarLinkage =

3135

3136

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

3138 return VarLinkage;

3139

3140

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

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

3144 return VarLinkage;

3145 return llvm::GlobalValue::WeakODRLinkage;

3146}

3147

3148llvm::Function *

3149ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,

3150 llvm::Value *Val) {

3151

3152 SmallString<256> WrapperName;

3153 {

3154 llvm::raw_svector_ostream Out(WrapperName);

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

3156 }

3157

3158

3159

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

3162

3163 QualType RetQT = VD->getType();

3166

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

3168 getContext().getPointerType(RetQT), FunctionArgList());

3169

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

3171 llvm::Function *Wrapper =

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

3174

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

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

3177

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

3179

3180

3181 if (!Wrapper->hasLocalLinkage())

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

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

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

3187

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

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

3191 }

3192

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

3194 return Wrapper;

3195}

3196

3197void ItaniumCXXABI::EmitThreadLocalInitFuncs(

3198 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,

3199 ArrayRef<llvm::Function *> CXXThreadLocalInits,

3200 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {

3201 llvm::Function *InitFunc = nullptr;

3202

3203

3204

3205 llvm::SmallVector<llvm::Function *, 8> OrderedInits;

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

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

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

3211 CXXThreadLocalInits[I];

3212 else

3213 OrderedInits.push_back(CXXThreadLocalInits[I]);

3214 }

3215

3216 if (!OrderedInits.empty()) {

3217

3218 llvm::FunctionType *FTy =

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

3222 SourceLocation(),

3223 true);

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

3226 llvm::GlobalVariable::InternalLinkage,

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

3228 Guard->setThreadLocal(true);

3230

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

3233

3234 CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(

3235 InitFunc, OrderedInits, ConstantAddress(Guard, CGM.Int8Ty, GuardAlign));

3236

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

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

3240 }

3241 }

3242

3243

3244

3245 for (const VarDecl *VD : CXXThreadLocals) {

3249 getOrCreateThreadLocalWrapper(VD, GV);

3250 }

3251 }

3252

3253

3254 for (auto VDAndWrapper : ThreadWrappers) {

3255 const VarDecl *VD = VDAndWrapper.first;

3256 llvm::GlobalVariable *Var =

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

3259

3260

3261

3262

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

3266 continue;

3267 }

3268

3269

3270

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

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

3273 }

3274

3276

3277

3278 SmallString<256> InitFnName;

3279 {

3280 llvm::raw_svector_ostream Out(InitFnName);

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

3282 }

3283

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

3285

3286

3287

3288

3289 llvm::GlobalValue *Init = nullptr;

3290 bool InitIsInitFunc = false;

3291 bool HasConstantInitialization = false;

3292 if (!usesThreadWrapperFunction(VD)) {

3293 HasConstantInitialization = true;

3295 InitIsInitFunc = true;

3296 llvm::Function *InitFuncToUse = InitFunc;

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

3299 if (InitFuncToUse)

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

3301 InitFuncToUse);

3302 } else {

3303

3304

3305

3306

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

3308 llvm::GlobalVariable::ExternalWeakLinkage,

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

3313 }

3314

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

3317

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

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

3320 }

3321

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

3323

3324

3325

3326

3327

3328

3330 isEmittedWithConstantInitializer(VD, true) &&

3331 !mayNeedDestruction(VD)) {

3332

3333

3334

3335

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

3337

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

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

3343 false);

3344

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

3346 CGBuilderTy Builder(CGM, Entry);

3347 Builder.CreateRetVoid();

3348 }

3349

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

3351 CGBuilderTy Builder(CGM, Entry);

3352 if (HasConstantInitialization) {

3353

3354 } else if (InitIsInitFunc) {

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

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

3359 llvm::Function *Fn =

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

3362 }

3363 }

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

3365

3366

3367

3368

3369

3370

3371

3372 Builder.CreateCall(InitFnTy, Init);

3373 } else {

3374

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

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

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

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

3379

3380 Builder.SetInsertPoint(InitBB);

3381 Builder.CreateCall(InitFnTy, Init);

3382 Builder.CreateBr(ExitBB);

3383

3384 Builder.SetInsertPoint(ExitBB);

3385 }

3386

3387

3388

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

3390

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

3394 }

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

3396

3397 Builder.CreateRet(Val);

3398 }

3399}

3400

3401LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,

3402 const VarDecl *VD,

3403 QualType LValType) {

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

3406

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

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

3409

3410 LValue LV;

3413 else

3416

3417 return LV;

3418}

3419

3420

3421

3422bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {

3424

3425

3427 return false;

3428

3429

3431 return true;

3432

3433

3435 return true;

3436

3437 return false;

3438}

3439

3440llvm::Constant *

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

3442 SmallString<256> MethodName;

3443 llvm::raw_svector_ostream Out(MethodName);

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

3445 MethodName += "_vfpthunk_";

3446 StringRef ThunkName = MethodName.str();

3447 llvm::Function *ThunkFn;

3448 if ((ThunkFn = cast_or_nullllvm::Function(

3449 CGM.getModule().getNamedValue(ThunkName))))

3450 return ThunkFn;

3451

3454 llvm::GlobalValue::LinkageTypes Linkage =

3456 : llvm::GlobalValue::InternalLinkage;

3457 ThunkFn =

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

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

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

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

3462

3465

3466

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

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

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

3470

3471

3472 CodeGenFunction CGF(CGM);

3473 CGF.CurGD = GlobalDecl(MD);

3475

3476

3477 FunctionArgList FunctionArgs;

3479

3481 FunctionArgs, MD->getLocation(), SourceLocation());

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

3483 setCXXABIThisValue(CGF, ThisVal);

3484

3485 CallArgList CallArgs;

3486 for (const VarDecl *VD : FunctionArgs)

3488

3489 const FunctionProtoType *FPT = MD->getType()->getAs();

3491 const CGFunctionInfo &CallInfo =

3494 getThisAddress(CGF), ThunkTy);

3495 llvm::CallBase *CallOrInvoke;

3496 CGF.EmitCall(CallInfo, Callee, ReturnValueSlot(), CallArgs, &CallOrInvoke,

3497 true, SourceLocation(), true);

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

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

3501 CGF.Builder.CreateRetVoid();

3502 else

3504

3505

3506

3509 return ThunkFn;

3510}

3511

3512namespace {

3513class ItaniumRTTIBuilder {

3514 CodeGenModule &CGM;

3515 llvm::LLVMContext &VMContext;

3516 const ItaniumCXXABI &CXXABI;

3517

3518

3519 SmallVector<llvm::Constant *, 16> Fields;

3520

3521

3522 llvm::GlobalVariable *

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

3524

3525

3526

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

3528

3529

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

3531

3532

3533

3534 void BuildSIClassTypeInfo(const CXXRecordDecl *RD);

3535

3536

3537

3538

3539 void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);

3540

3541

3542

3543 void BuildPointerTypeInfo(QualType PointeeTy);

3544

3545

3546

3547 void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);

3548

3549

3550

3551 void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);

3552

3553public:

3554 ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)

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

3556

3557

3558 enum {

3559

3560 PTI_Const = 0x1,

3561

3562

3563 PTI_Volatile = 0x2,

3564

3565

3566 PTI_Restrict = 0x4,

3567

3568

3569 PTI_Incomplete = 0x8,

3570

3571

3572

3573 PTI_ContainingClassIncomplete = 0x10,

3574

3575

3576

3577

3578

3579 PTI_Noexcept = 0x40,

3580 };

3581

3582

3583 enum {

3584

3585 VMI_NonDiamondRepeat = 0x1,

3586

3587

3588 VMI_DiamondShaped = 0x2

3589 };

3590

3591

3592 enum {

3593

3594 BCTI_Virtual = 0x1,

3595

3596

3597 BCTI_Public = 0x2

3598 };

3599

3600

3601

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

3603

3604

3605 llvm::Constant *BuildTypeInfo(

3606 QualType Ty,

3607 llvm::GlobalVariable::LinkageTypes Linkage,

3608 llvm::GlobalValue::VisibilityTypes Visibility,

3609 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);

3610};

3611}

3612

3613llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(

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

3615 SmallString<256> Name;

3616 llvm::raw_svector_ostream Out(Name);

3618

3619

3620

3621

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

3623 Name.substr(4));

3625

3628

3629 GV->setInitializer(Init);

3630

3631 return GV;

3632}

3633

3634llvm::Constant *

3635ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {

3636

3637 SmallString<256> Name;

3638 llvm::raw_svector_ostream Out(Name);

3640

3641

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

3643

3644 if (!GV) {

3645

3646

3647

3648

3649 GV = new llvm::GlobalVariable(

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

3654

3655

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

3660 }

3661 }

3662 }

3663

3664 return GV;

3665}

3666

3667

3668

3670

3671

3672

3673

3674

3675

3676

3677

3678

3679

3680

3681

3682

3683

3684 switch (Ty->getKind()) {

3685 case BuiltinType::Void:

3686 case BuiltinType::NullPtr:

3687 case BuiltinType::Bool:

3688 case BuiltinType::WChar_S:

3689 case BuiltinType::WChar_U:

3690 case BuiltinType::Char_U:

3691 case BuiltinType::Char_S:

3692 case BuiltinType::UChar:

3693 case BuiltinType::SChar:

3694 case BuiltinType::Short:

3695 case BuiltinType::UShort:

3696 case BuiltinType::Int:

3697 case BuiltinType::UInt:

3698 case BuiltinType::Long:

3699 case BuiltinType::ULong:

3700 case BuiltinType::LongLong:

3701 case BuiltinType::ULongLong:

3702 case BuiltinType::Half:

3703 case BuiltinType::Float:

3704 case BuiltinType::Double:

3705 case BuiltinType::LongDouble:

3706 case BuiltinType::Float16:

3707 case BuiltinType::Float128:

3708 case BuiltinType::Ibm128:

3709 case BuiltinType::Char8:

3710 case BuiltinType::Char16:

3711 case BuiltinType::Char32:

3712 case BuiltinType::Int128:

3713 case BuiltinType::UInt128:

3714 return true;

3715

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

3717 case BuiltinType::Id:

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

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

3720 case BuiltinType::Id:

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

3722 case BuiltinType::OCLSampler:

3723 case BuiltinType::OCLEvent:

3724 case BuiltinType::OCLClkEvent:

3725 case BuiltinType::OCLQueue:

3726 case BuiltinType::OCLReserveID:

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

3728 case BuiltinType::Id:

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

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

3731 case BuiltinType::Id:

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

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

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

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

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

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

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

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

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

3741 case BuiltinType::ShortAccum:

3742 case BuiltinType::Accum:

3743 case BuiltinType::LongAccum:

3744 case BuiltinType::UShortAccum:

3745 case BuiltinType::UAccum:

3746 case BuiltinType::ULongAccum:

3747 case BuiltinType::ShortFract:

3748 case BuiltinType::Fract:

3749 case BuiltinType::LongFract:

3750 case BuiltinType::UShortFract:

3751 case BuiltinType::UFract:

3752 case BuiltinType::ULongFract:

3753 case BuiltinType::SatShortAccum:

3754 case BuiltinType::SatAccum:

3755 case BuiltinType::SatLongAccum:

3756 case BuiltinType::SatUShortAccum:

3757 case BuiltinType::SatUAccum:

3758 case BuiltinType::SatULongAccum:

3759 case BuiltinType::SatShortFract:

3760 case BuiltinType::SatFract:

3761 case BuiltinType::SatLongFract:

3762 case BuiltinType::SatUShortFract:

3763 case BuiltinType::SatUFract:

3764 case BuiltinType::SatULongFract:

3765 case BuiltinType::BFloat16:

3766 return false;

3767

3768 case BuiltinType::Dependent:

3769#define BUILTIN_TYPE(Id, SingletonId)

3770#define PLACEHOLDER_TYPE(Id, SingletonId) \

3771 case BuiltinType::Id:

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

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

3774

3775 case BuiltinType::ObjCId:

3776 case BuiltinType::ObjCClass:

3777 case BuiltinType::ObjCSel:

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

3779 }

3780

3781 llvm_unreachable("Invalid BuiltinType Kind!");

3782}

3783

3786 const BuiltinType *BuiltinTy = dyn_cast(PointeeTy);

3787 if (!BuiltinTy)

3788 return false;

3789

3790

3793

3794 if (!Quals.empty())

3795 return false;

3796

3798}

3799

3800

3801

3803

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

3806

3807

3808

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

3811

3812 return false;

3813}

3814

3815

3816

3817

3818

3822

3823

3824

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

3826

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

3831 return false;

3832

3834 return false;

3835

3836

3837

3838

3839

3840 bool IsDLLImport = RD->hasAttr();

3841

3842

3843 if (CGM.getTriple().isOSCygMing())

3844 return false;

3845

3848 return true;

3849

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

3852 : true;

3853 }

3854 if (IsDLLImport)

3855 return true;

3856 }

3857

3858 return false;

3859}

3860

3861

3863 return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();

3864}

3865

3866

3867

3868

3869

3870

3871

3872

3873

3874

3875

3876

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

3880 return true;

3881 }

3882

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

3885

3887 dyn_cast(Ty)) {

3888

3889 if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())

3890 return true;

3891

3893 }

3894

3895 return false;

3896}

3897

3898

3899

3900

3902

3904 return false;

3905

3906

3908

3909

3910 if (Base->isVirtual())

3911 return false;

3912

3913

3915 return false;

3916

3917

3918 auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();

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

3921 return false;

3922

3923 return true;

3924}

3925

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

3927 llvm::Constant *StorageAddress) {

3928

3929 static const char * const ClassTypeInfo =

3930 "_ZTVN10__cxxabiv117__class_type_infoE";

3931

3932 static const char * const SIClassTypeInfo =

3933 "_ZTVN10__cxxabiv120__si_class_type_infoE";

3934

3935 static const char * const VMIClassTypeInfo =

3936 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";

3937

3938 const char *VTableName = nullptr;

3939

3941#define TYPE(Class, Base)

3942#define ABSTRACT_TYPE(Class, Base)

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

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

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

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

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

3948

3949 case Type::LValueReference:

3950 case Type::RValueReference:

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

3952

3953 case Type::Auto:

3954 case Type::DeducedTemplateSpecialization:

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

3956

3957 case Type::Pipe:

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

3959

3960 case Type::ArrayParameter:

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

3962

3963 case Type::Builtin:

3964 case Type::BitInt:

3965

3966 case Type::Vector:

3967 case Type::ExtVector:

3968 case Type::ConstantMatrix:

3969 case Type::Complex:

3970 case Type::Atomic:

3971

3972 case Type::BlockPointer:

3973

3974 VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";

3975 break;

3976

3977 case Type::ConstantArray:

3978 case Type::IncompleteArray:

3979 case Type::VariableArray:

3980

3981 VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";

3982 break;

3983

3984 case Type::FunctionNoProto:

3985 case Type::FunctionProto:

3986

3987 VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";

3988 break;

3989

3990 case Type::Enum:

3991

3992 VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";

3993 break;

3994

3995 case Type::Record: {

3997 ->getDefinitionOrSelf();

3998

4000 VTableName = ClassTypeInfo;

4002 VTableName = SIClassTypeInfo;

4003 } else {

4004 VTableName = VMIClassTypeInfo;

4005 }

4006

4007 break;

4008 }

4009

4010 case Type::ObjCObject:

4011

4013

4014

4016 VTableName = ClassTypeInfo;

4017 break;

4018 }

4019

4021 [[fallthrough]];

4022

4023 case Type::ObjCInterface:

4025 VTableName = SIClassTypeInfo;

4026 } else {

4027 VTableName = ClassTypeInfo;

4028 }

4029 break;

4030

4031 case Type::ObjCObjectPointer:

4032 case Type::Pointer:

4033

4034 VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";

4035 break;

4036

4037 case Type::MemberPointer:

4038

4039 VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";

4040 break;

4041

4042 case Type::HLSLAttributedResource:

4043 case Type::HLSLInlineSpirv:

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

4045 }

4046

4047 llvm::Constant *VTable = nullptr;

4048

4049

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

4052 if (!VTable) {

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

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

4055 }

4056

4058

4059 llvm::Type *PtrDiffTy =

4061

4062

4064

4065

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

4067 VTable =

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

4069 } else {

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

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

4072 VTable, Two);

4073 }

4074

4075 if (const auto &Schema =

4078 VTable, Schema,

4079 Schema.isAddressDiscriminated() ? StorageAddress : nullptr,

4080 GlobalDecl(), QualType(Ty, 0));

4081

4082 Fields.push_back(VTable);

4083}

4084

4085

4086

4089

4090

4091

4092

4093

4094

4095

4096

4097

4099 return llvm::GlobalValue::InternalLinkage;

4100

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

4104

4108 return llvm::GlobalValue::InternalLinkage;

4109

4113

4114

4116 return llvm::GlobalValue::LinkOnceODRLinkage;

4117

4118 if (const RecordType *Record = dyn_cast(Ty)) {

4119 const auto *RD =

4121 if (RD->hasAttr())

4122 return llvm::GlobalValue::WeakODRLinkage;

4123 if (CGM.getTriple().isWindowsItaniumEnvironment())

4124 if (RD->hasAttr() &&

4126 return llvm::GlobalValue::ExternalLinkage;

4127

4131 }

4132

4133 return llvm::GlobalValue::LinkOnceODRLinkage;

4134 }

4135

4136 llvm_unreachable("Invalid linkage!");

4137}

4138

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

4140

4142

4143

4144 SmallString<256> Name;

4145 llvm::raw_svector_ostream Out(Name);

4147

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

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

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

4151 "available_externally typeinfos not yet implemented");

4152

4153 return OldGV;

4154 }

4155

4156

4159 return GetAddrOfExternalRTTIDescriptor(Ty);

4160

4161

4163

4164

4165

4166 llvm::GlobalValue::VisibilityTypes llvmVisibility;

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

4168

4169 llvmVisibility = llvm::GlobalValue::DefaultVisibility;

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

4171 ItaniumCXXABI::RUK_NonUniqueHidden)

4172 llvmVisibility = llvm::GlobalValue::HiddenVisibility;

4173 else

4175

4176 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =

4177 llvm::GlobalValue::DefaultStorageClass;

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

4180 RD->hasAttr()) ||

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

4183 llvmVisibility == llvm::GlobalValue::DefaultVisibility))

4184 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;

4185 }

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

4187}

4188

4189llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(

4190 QualType Ty,

4191 llvm::GlobalVariable::LinkageTypes Linkage,

4192 llvm::GlobalValue::VisibilityTypes Visibility,

4193 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {

4194 SmallString<256> Name;

4195 llvm::raw_svector_ostream Out(Name);

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

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

4199

4200 llvm::GlobalVariable *GV =

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

4202 nullptr, Name);

4203

4204

4205 BuildVTablePointer(cast(Ty), GV);

4206

4207

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

4209 llvm::Constant *TypeNameField;

4210

4211

4212

4213 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =

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

4216

4217

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

4219 llvm::Constant *flag =

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

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

4222 TypeNameField =

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

4224 } else {

4226 }

4227 Fields.push_back(TypeNameField);

4228

4230#define TYPE(Class, Base)

4231#define ABSTRACT_TYPE(Class, Base)

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

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

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

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

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

4237

4238

4239 case Type::Builtin:

4240 case Type::Vector:

4241 case Type::ExtVector:

4242 case Type::ConstantMatrix:

4243 case Type::Complex:

4244 case Type::BlockPointer:

4245

4246

4247 break;

4248

4249 case Type::LValueReference:

4250 case Type::RValueReference:

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

4252

4253 case Type::Auto:

4254 case Type::DeducedTemplateSpecialization:

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

4256

4257 case Type::Pipe:

4258 break;

4259

4260 case Type::BitInt:

4261 break;

4262

4263 case Type::ConstantArray:

4264 case Type::IncompleteArray:

4265 case Type::VariableArray:

4266 case Type::ArrayParameter:

4267

4268

4269 break;

4270

4271 case Type::FunctionNoProto:

4272 case Type::FunctionProto:

4273

4274

4275 break;

4276

4277 case Type::Enum:

4278

4279

4280 break;

4281

4282 case Type::Record: {

4284 ->getDefinitionOrSelf();

4286

4287 break;

4288 }

4289

4291 BuildSIClassTypeInfo(RD);

4292 else

4293 BuildVMIClassTypeInfo(RD);

4294

4295 break;

4296 }

4297

4298 case Type::ObjCObject:

4299 case Type::ObjCInterface:

4301 break;

4302

4303 case Type::ObjCObjectPointer:

4305 break;

4306

4307 case Type::Pointer:

4309 break;

4310

4311 case Type::MemberPointer:

4313 break;

4314

4315 case Type::Atomic:

4316

4317 break;

4318

4319 case Type::HLSLAttributedResource:

4320 case Type::HLSLInlineSpirv:

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

4322 }

4323

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

4325

4326

4327 auto GVDLLStorageClass = DLLStorageClass;

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

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

4331 const auto *RD =

4333 if (RD->hasAttr() ||

4335 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;

4336 }

4337 }

4338

4339

4340 if (OldGV) {

4341 GV->takeName(OldGV);

4342 OldGV->replaceAllUsesWith(GV);

4343 OldGV->eraseFromParent();

4344 }

4345

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

4348

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

4352

4353

4354

4355

4356

4357

4358

4359

4360

4361

4362

4363

4364

4365

4366

4367

4370

4373

4374 TypeName->setDLLStorageClass(DLLStorageClass);

4375 GV->setDLLStorageClass(GVDLLStorageClass);

4376

4379

4380 return GV;

4381}

4382

4383

4384

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

4386

4387 const Type *T = OT->getBaseType().getTypePtr();

4389

4390

4391

4393

4395 ObjCInterfaceDecl *Super = Class->getSuperClass();

4396

4397

4398 if (!Super) return;

4399

4401

4402

4403 llvm::Constant *BaseTypeInfo =

4404 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy);

4405 Fields.push_back(BaseTypeInfo);

4406}

4407

4408

4409

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

4411

4412

4413

4414 llvm::Constant *BaseTypeInfo =

4416 Fields.push_back(BaseTypeInfo);

4417}

4418

4419namespace {

4420

4421

4422 struct SeenBases {

4423 llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;

4424 llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;

4425 };

4426}

4427

4428

4429

4430

4432 SeenBases &Bases) {

4433

4434 unsigned Flags = 0;

4435

4436 auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();

4437 if (Base->isVirtual()) {

4438

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

4440

4441

4442 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;

4443 } else {

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

4445 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;

4446 }

4447 } else {

4448

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

4450

4451

4452 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;

4453 } else {

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

4455 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;

4456 }

4457 }

4458

4459

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

4462

4463 return Flags;

4464}

4465

4467 unsigned Flags = 0;

4468 SeenBases Bases;

4469

4470

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

4473

4474 return Flags;

4475}

4476

4477

4478

4479

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

4481 llvm::Type *UnsignedIntLTy =

4483

4484

4485

4486

4487

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

4490

4491

4492

4493

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

4495

4497 return;

4498

4499

4500

4501

4502

4503

4504

4505

4506

4507

4508

4509

4510

4511

4512

4513

4514

4515

4516

4517

4518

4519

4520

4521

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

4527 llvm::Type *OffsetFlagsLTy =

4529

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

4531

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

4533

4534 auto *BaseDecl = Base.getType()->castAsCXXRecordDecl();

4535 int64_t OffsetFlags = 0;

4536

4537

4538

4539

4540

4541 CharUnits Offset;

4542 if (Base.isVirtual())

4543 Offset =

4545 else {

4548 };

4549

4551

4552

4553

4554 if (Base.isVirtual())

4555 OffsetFlags |= BCTI_Virtual;

4557 OffsetFlags |= BCTI_Public;

4558

4559 Fields.push_back(llvm::ConstantInt::getSigned(OffsetFlagsLTy, OffsetFlags));

4560 }

4561}

4562

4563

4564

4566 unsigned Flags = 0;

4567

4568 if (Type.isConstQualified())

4569 Flags |= ItaniumRTTIBuilder::PTI_Const;

4570 if (Type.isVolatileQualified())

4571 Flags |= ItaniumRTTIBuilder::PTI_Volatile;

4572 if (Type.isRestrictQualified())

4573 Flags |= ItaniumRTTIBuilder::PTI_Restrict;

4574 Type = Type.getUnqualifiedType();

4575

4576

4577

4578

4580 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;

4581

4583 if (Proto->isNothrow()) {

4584 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;

4586 }

4587 }

4588

4589 return Flags;

4590}

4591

4592

4593

4594void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {

4595

4596

4597

4599

4600 llvm::Type *UnsignedIntLTy =

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

4603

4604

4605

4606

4607 llvm::Constant *PointeeTypeInfo =

4608 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);

4609 Fields.push_back(PointeeTypeInfo);

4610}

4611

4612

4613

4614void

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

4617

4618

4619

4620

4622

4625 Flags |= PTI_ContainingClassIncomplete;

4626

4627 llvm::Type *UnsignedIntLTy =

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

4630

4631

4632

4633

4634 llvm::Constant *PointeeTypeInfo =

4635 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);

4636 Fields.push_back(PointeeTypeInfo);

4637

4638

4639

4640

4641

4643 Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(T));

4644}

4645

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

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

4648}

4649

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

4651

4652 QualType FundamentalTypes[] = {

4653 getContext().VoidTy, getContext().NullPtrTy,

4654 getContext().BoolTy, getContext().WCharTy,

4655 getContext().CharTy, getContext().UnsignedCharTy,

4656 getContext().SignedCharTy, getContext().ShortTy,

4657 getContext().UnsignedShortTy, getContext().IntTy,

4658 getContext().UnsignedIntTy, getContext().LongTy,

4659 getContext().UnsignedLongTy, getContext().LongLongTy,

4660 getContext().UnsignedLongLongTy, getContext().Int128Ty,

4661 getContext().UnsignedInt128Ty, getContext().HalfTy,

4662 getContext().FloatTy, getContext().DoubleTy,

4663 getContext().LongDoubleTy, getContext().Float128Ty,

4664 getContext().Char8Ty, getContext().Char16Ty,

4665 getContext().Char32Ty

4666 };

4667 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =

4669 ? llvm::GlobalValue::DLLExportStorageClass

4670 : llvm::GlobalValue::DefaultStorageClass;

4671 llvm::GlobalValue::VisibilityTypes Visibility =

4673 for (const QualType &FundamentalType : FundamentalTypes) {

4674 QualType PointerType = getContext().getPointerType(FundamentalType);

4675 QualType PointerTypeConst = getContext().getPointerType(

4676 FundamentalType.withConst());

4677 for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})

4678 ItaniumRTTIBuilder(*this).BuildTypeInfo(

4679 Type, llvm::GlobalValue::ExternalLinkage,

4681 }

4682}

4683

4684

4685

4686ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(

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

4688 if (shouldRTTIBeUnique())

4689 return RUK_Unique;

4690

4691

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

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

4694 return RUK_Unique;

4695

4696

4698 return RUK_Unique;

4699

4700

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

4702 return RUK_NonUniqueHidden;

4703

4704

4705

4706

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

4708 return RUK_NonUniqueVisible;

4709}

4710

4711

4712namespace {

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

4714}

4718 return StructorCodegen::Emit;

4719

4720

4721

4723 return StructorCodegen::Emit;

4724

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

4728 } else {

4731 }

4733

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

4735 return StructorCodegen::RAUW;

4736

4737

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

4739 return StructorCodegen::RAUW;

4740

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

4742

4745 return StructorCodegen::COMDAT;

4746 return StructorCodegen::Emit;

4747 }

4748

4749 return StructorCodegen::Alias;

4750}

4751

4756

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

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

4760 return;

4761

4763

4764

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

4766

4767

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

4769

4770

4771 if (Entry) {

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

4773 "declaration exists with different type");

4774 Alias->takeName(Entry);

4775 Entry->replaceAllUsesWith(Alias);

4776 Entry->eraseFromParent();

4777 } else {

4778 Alias->setName(MangledName);

4779 }

4780

4781

4783}

4784

4785void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {

4787 auto *CD = dyn_cast(MD);

4789

4791

4794 GlobalDecl BaseDecl;

4795 if (CD)

4797 else

4799

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

4802 return;

4803 }

4804

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

4809 return;

4810 }

4811 }

4812

4813

4814

4815

4816

4818 CGType != StructorCodegen::COMDAT &&

4820 return;

4821

4822

4823

4824

4825

4826

4827

4828

4829

4830

4831

4832

4833

4835

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

4837 SmallString<256> Buffer;

4838 llvm::raw_svector_ostream Out(Buffer);

4839 if (DD)

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

4841 else

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

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

4844 Fn->setComdat(C);

4845 } else {

4847 }

4848}

4849

4851

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

4854

4856}

4857

4859

4860 llvm::FunctionType *FTy =

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

4862

4864}

4865

4867

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

4870

4872}

4873

4874namespace {

4875

4876

4877

4878

4879

4880

4881

4882

4883

4884

4885

4886

4887 struct CallEndCatch final : EHScopeStack::Cleanup {

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

4889 bool MightThrow;

4890

4891 void Emit(CodeGenFunction &CGF, Flags flags) override {

4892 if (!MightThrow) {

4894 return;

4895 }

4896

4898 }

4899 };

4900}

4901

4902

4903

4904

4905

4906

4907

4909 llvm::Value *Exn,

4910 bool EndMightThrow) {

4911 llvm::CallInst *call =

4913

4914 CGF.EHStack.pushCleanup(

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

4917

4918 return call;

4919}

4920

4921

4922

4924 const VarDecl &CatchParam,

4927

4929

4933

4934

4935

4938 bool EndCatchMightThrow = CaughtType->isRecordType();

4939

4940

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

4942

4943

4944

4945

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

4948

4949

4950

4952

4953

4954

4955 unsigned HeaderSize =

4957 AdjustedExn =

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

4959

4960

4961

4962

4963

4964

4965

4966

4967

4968

4969

4970

4971

4972

4973

4974 } else {

4975

4977

4978

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

4983

4984

4986 }

4987 }

4988

4989 llvm::Value *ExnCast =

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

4992 return;

4993 }

4994

4995

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

4999

5000

5001

5002 if (CatchType->hasPointerRepresentation()) {

5003 llvm::Value *CastExn =

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

5005

5009 [[fallthrough]];

5010

5015 return;

5016

5019 return;

5020 }

5021 llvm_unreachable("bad ownership qualifier!");

5022 }

5023

5024

5025

5027 LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType);

5028 switch (TEK) {

5031 true);

5032 return;

5036 return;

5037 }

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

5040 }

5041 llvm_unreachable("bad evaluation kind");

5042 }

5043

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

5045 auto catchRD = CatchType->getAsCXXRecordDecl();

5047

5049

5050

5051

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

5053 if (!copyExpr) {

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

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

5056 LLVMCatchTy, caughtExnAlignment);

5057 LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType);

5058 LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType);

5060 return;

5061 }

5062

5063

5064

5065 llvm::CallInst *rawAdjustedExn =

5067

5068

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

5070 LLVMCatchTy, caughtExnAlignment);

5071

5072

5073

5077

5078

5080

5081

5088

5089

5091

5092

5093 opaque.pop();

5094

5095

5097}

5098

5099

5100

5101void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,

5102 const CXXCatchStmt *S) {

5103

5104

5105

5106

5107

5108

5109

5110

5111

5112

5113

5114

5115

5116

5117

5118

5119

5120

5121

5122

5123

5124

5125

5127 if (!CatchParam) {

5130 return;

5131 }

5132

5133

5135 {

5139 }

5141}

5142

5143

5144

5145

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

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

5153 llvm::Function *fn =

5155 if (fn->empty()) {

5158 fn->setDoesNotThrow();

5159 fn->setDoesNotReturn();

5160

5161

5162

5163

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

5165

5166

5167

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

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

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

5172

5173

5174 llvm::BasicBlock *entry =

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

5177

5178

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

5180

5181

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

5183 catchCall->setDoesNotThrow();

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

5185

5186

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

5188 termCall->setDoesNotThrow();

5189 termCall->setDoesNotReturn();

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

5191

5192

5193 builder.CreateUnreachable();

5194 }

5195 return fnRef;

5196}

5197

5198llvm::CallInst *

5199ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,

5200 llvm::Value *Exn) {

5201

5202 if (Exn) {

5205 }

5207}

5208

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

5210ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,

5211 const CXXRecordDecl *RD) {

5213}

5214

5215llvm::Constant *

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

5217 const CXXMethodDecl *origMD =

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

5223 MD->getType(), std::nullopt, MD->getParent());

5225}

5226

5227void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,

5228 const CXXCatchStmt *C) {

5230 CGF.EHStack.pushCleanup(

5232 ItaniumCXXABI::emitBeginCatch(CGF, C);

5233}

5234

5235llvm::CallInst *

5236WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,

5237 llvm::Value *Exn) {

5238

5239

5240

5241

5242

5243

5244

5248 }

5250}

5251

5252

5253void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,

5254 llvm::FunctionCallee Dtor,

5255 llvm::Constant *Addr) {

5257 llvm::PointerType *PtrTy = CGF.DefaultPtrTy;

5258

5259

5260 llvm::FunctionType *AtExitTy =

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

5262

5263

5264 llvm::FunctionCallee AtExit =

5266

5267

5269

5270

5271

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

5274

5275

5276 return;

5277 }

5278

5279

5280 llvm::Function *DtorStub =

5282

5283

5285

5286

5287

5288 emitCXXStermFinalizer(D, DtorStub, Addr);

5289}

5290

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

5292 llvm::Constant *addr) {

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

5294 SmallString<256> FnName;

5295 {

5296 llvm::raw_svector_ostream Out(FnName);

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

5298 }

5299

5300

5303 FTy, FnName.str(), FI, D.getLocation());

5304

5305 CodeGenFunction CGF(CGM);

5306

5310

5311

5312

5313

5314

5316

5318

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

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

5321

5322

5323

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

5325

5326 CGF.EmitBlock(DestructCallBlock);

5327

5328

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

5330

5331

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

5333

5335

5337

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

5340 IPA->getPriority());

5343

5344

5345

5346

5348 } else {

5350 }

5351}

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

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

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

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

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

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

static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf)

static cir::FuncOp getBadCastFn(CIRGenFunction &cgf)

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

Definition ItaniumCXXABI.cpp:4715

static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM)

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

Definition ItaniumCXXABI.cpp:5146

static bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD)

Definition ItaniumCXXABI.cpp:2047

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

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

Definition ItaniumCXXABI.cpp:4565

static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty)

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

Definition ItaniumCXXABI.cpp:3819

static bool IsIncompleteClassType(const RecordType *RecordTy)

IsIncompleteClassType - Returns whether the given record type is incomplete.

Definition ItaniumCXXABI.cpp:3862

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

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

Definition ItaniumCXXABI.cpp:4431

static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF)

Definition ItaniumCXXABI.cpp:1600

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

Register a global destructor using __cxa_atexit.

Definition ItaniumCXXABI.cpp:2919

static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM)

Definition ItaniumCXXABI.cpp:4850

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

Definition ItaniumCXXABI.cpp:1049

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

Definition ItaniumCXXABI.cpp:2663

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

Definition ItaniumCXXABI.cpp:2432

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

Definition ItaniumCXXABI.cpp:2976

static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM)

Definition ItaniumCXXABI.cpp:1456

static bool IsStandardLibraryRTTIDescriptor(QualType Ty)

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

Definition ItaniumCXXABI.cpp:3802

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.

Definition ItaniumCXXABI.cpp:4908

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

Definition ItaniumCXXABI.cpp:2675

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

Definition ItaniumCXXABI.cpp:3119

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

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

Definition ItaniumCXXABI.cpp:4923

static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty)

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

Definition ItaniumCXXABI.cpp:3669

static bool CanUseSingleInheritance(const CXXRecordDecl *RD)

Definition ItaniumCXXABI.cpp:3901

static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM)

Definition ItaniumCXXABI.cpp:4858

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

Get the appropriate linkage for the wrapper function.

Definition ItaniumCXXABI.cpp:3132

static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM)

Definition ItaniumCXXABI.cpp:1465

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

Definition ItaniumCXXABI.cpp:2061

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

Definition ItaniumCXXABI.cpp:2650

static bool ContainsIncompleteClassType(QualType Ty)

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

Definition ItaniumCXXABI.cpp:3877

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

Definition ItaniumCXXABI.cpp:909

static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM)

Definition ItaniumCXXABI.cpp:4866

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

llvm::MachO::Record Record

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

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.

a trap message and trap category.

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.

static CanQualType getCanonicalType(QualType T)

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

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

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

QualType getPointerType(QualType T) const

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

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.

QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const

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

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

CanQualType getCanonicalTagType(const TagDecl *TD) const

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

CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const

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

CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const

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

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

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.

SourceLocation getBeginLoc() const LLVM_READONLY

VarDecl * getExceptionDecl() const

FunctionDecl * getOperatorDelete() const

bool isGlobalDelete() const

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

const CXXRecordDecl * getParent() const

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

CXXMethodDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

Represents a C++ struct/union/class.

bool hasTrivialDestructor() const

Determine whether this class has a trivial destructor (C++ [class.dtor]p3)

unsigned getNumBases() const

Retrieves the number of base classes of this class.

base_class_iterator bases_begin()

const CXXBaseSpecifier * base_class_const_iterator

Iterator that traverses the base classes of a class.

base_class_range vbases()

bool isAbstract() const

Determine whether this class has a pure virtual function.

bool isDynamicClass() const

bool hasDefinition() const

unsigned getNumVBases() const

Retrieves the number of virtual base classes of this class.

bool isDerivedFrom(const CXXRecordDecl *Base) const

Determine whether this class is derived from the class Base.

const Expr * getSubExpr() const

static CanQual< Type > CreateUnsafe(QualType Other)

Qualifiers getQualifiers() const

Retrieve all qualifiers.

CastKind getCastKind() const

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, unsigned AddrSpace, 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 llvm::CallInst * emitTerminateForUnexpectedException(CodeGenFunction &CGF, llvm::Value *Exn)

MangleContext & getMangleContext()

Gets the mangle context.

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

An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

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.

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

llvm::Constant * createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)

Create a stub function, suitable for being passed to atexit, which passes the given address to the gi...

llvm::Function * createTLSAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr, llvm::FunctionCallee &AtExit)

Create a stub function, suitable for being passed to __pt_atexit_np, which passes the given address t...

SanitizerSet SanOpts

Sanitizers enabled for this function.

void EmitARCInitWeak(Address addr, llvm::Value *value)

i8* @objc_initWeak(i8** addr, i8* value) Returns value.

llvm::Value * getExceptionFromSlot()

Returns the contents of the function's exception object and selector slots.

llvm::Type * ConvertType(QualType T)

void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)

Emits a call or invoke to the given noreturn runtime function.

llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")

Emits a call or invoke instruction to the given runtime function.

ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)

EmitLoadOfComplex - Load a complex number from the specified l-value.

bool CurFuncIsThunk

In C++, whether we are code generating a thunk.

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.

llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)

Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...

llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)

void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)

EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...

llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)

createBasicBlock - Create an LLVM basic block.

const LangOptions & getLangOpts() const

LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)

EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.

void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)

void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit)

EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.

void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr, QualType ElementType)

llvm::Constant * EmitCheckTypeDescriptor(QualType T)

Emit a description of a type in a format suitable for passing to a runtime sanitizer handler.

void EmitAnyExprToExn(const Expr *E, Address Addr)

void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)

EmitAggregateCopy - Emit an aggregate copy.

const TargetInfo & getTarget() const

CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, const CXXRecordDecl *RD)

BuildVirtualCall - This routine makes indirect vtable call for call to virtual destructors.

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 EmitCheck(ArrayRef< std::pair< llvm::Value *, SanitizerKind::SanitizerOrdinal > > Checked, SanitizerHandler Check, ArrayRef< llvm::Constant * > StaticArgs, ArrayRef< llvm::Value * > DynamicArgs, const TrapReason *TR=nullptr)

Create a basic block that will either trap or call a handler function in the UBSan runtime with the p...

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.

CGDebugInfo * getDebugInfo()

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.

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

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

CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)

Emit the concrete pointer authentication informaton for the given authentication schema.

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::Value * unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub)

Call unatexit() with function dtorStub.

llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)

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

void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)

EmitStoreOfComplex - Store a complex number into the specified l-value.

const Decl * CurFuncDecl

CurFuncDecl - Holds the Decl for the current outermost non-closure context.

void EmitAutoVarCleanups(const AutoVarEmission &emission)

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

llvm::Value * LoadCXXVTT()

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

llvm::Value * EmitARCRetainNonBlock(llvm::Value *value)

Retain the given object, with normal retain semantics.

llvm::Type * ConvertTypeForMem(QualType T)

CodeGenTypes & getTypes() const

static TypeEvaluationKind getEvaluationKind(QualType T)

getEvaluationKind - Return the TypeEvaluationKind of QualType T.

void EmitBranch(llvm::BasicBlock *Block)

EmitBranch - Emit a branch to the specified basic block from the current insert block,...

void EmitAggExpr(const Expr *E, AggValueSlot AS)

EmitAggExpr - Emit the computation of the specified expression of aggregate type.

llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)

GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...

LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)

void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false, const TrapReason *TR=nullptr)

Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...

void FinishFunction(SourceLocation EndLoc=SourceLocation())

FinishFunction - Complete IR generation of the current function.

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)

Emit a type checked load from the given vtable.

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

llvm::Instruction * CurrentFuncletPad

bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)

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

llvm::LLVMContext & getLLVMContext()

void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)

PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.

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

void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)

EmitBlock - Emit the given block.

LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)

QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)

llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)

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)

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

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.

bool isFuncTypeConvertible(const FunctionType *FT)

isFuncTypeConvertible - Utility to check whether a function type can be converted to an LLVM type (i....

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.

void pushTerminate()

Push a terminate handler on the stack.

void popTerminate()

Pops a terminate handler off the stack.

static RValue get(llvm::Value *V)

static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)

Compute the arguments required by the given formal prototype, given that there may be some additional...

virtual unsigned getSizeOfUnwindException() const

Determines the size of struct _Unwind_Exception on this platform, in 8-bit units.

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.

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

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.

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.

CXXRecordDecl * getMostRecentCXXRecordDecl() const

Note: this can trigger extra deserialization when external AST sources are used.

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.

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

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.

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.

Encodes a location in the source.

SourceLocation getBeginLoc() const LLVM_READONLY

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.

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

CXXRecordDecl * castAsCXXRecordDecl() const

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

Represents a variable declaration or definition.

TLSKind getTLSKind() const

VarDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

bool isNoDestroy(const ASTContext &) const

Is destruction of this variable entirely suppressed?

bool isStaticLocal() const

Returns true if a variable with function scope is a static local variable.

bool isInline() const

Whether this variable is (C++1z) inline.

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.

bool isLocalVarDecl() const

Returns true for local variable declarations other than parameters.

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)

@ Decl

The l-value was an access to a declared entity or something equivalently strong, like the address of ...

CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)

bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)

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.

Definition ItaniumCXXABI.cpp:569

const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr

Matches expressions.

constexpr Variable var(Literal L)

Returns the variable of L.

bool This(InterpState &S, CodePtr OpPC)

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

CanQual< Type > CanQualType

Represents a canonical, potentially-qualified type.

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

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

@ Ctor_Unified

GCC-style unified dtor.

bool isa(CodeGen::Address addr)

bool isTemplateInstantiation(TemplateSpecializationKind Kind)

Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...

@ Success

Annotation was successful.

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

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

@ Result

The result type of a method or function.

const FunctionProtoType * T

CXXDtorType

C++ destructor types.

@ Dtor_VectorDeleting

Vector deleting dtor.

@ Dtor_Comdat

The COMDAT used for dtors.

@ Dtor_Unified

GCC-style unified dtor.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

bool isDiscardableGVALinkage(GVALinkage L)

@ Type

The name was classified as a type.

LangAS

Defines the address space values used by the address space qualifier of QualType.

U cast(CodeGen::Address addr)

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

const half4 dst(half4 Src0, half4 Src1)

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

const CXXRecordDecl * NearestVBase

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::IntegerType * PtrDiffTy

CharUnits getPointerAlign() const

llvm::PointerType * DefaultPtrTy

static const EHPersonality & get(CodeGenModule &CGM, const FunctionDecl *FD)

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.

union clang::ThisAdjustment::VirtualAdjustment Virtual

int64_t NonVirtual

The non-virtual adjustment from the derived object to its nearest virtual base.

ThisAdjustment This

The this pointer adjustment.

unsigned AddressPointIndex

struct clang::ReturnAdjustment::VirtualAdjustment::@103031170252120233124322035264172076254313213024 Itanium

int64_t VBaseOffsetOffset

The offset (in bytes), relative to the address point of the virtual base class offset.

struct clang::ThisAdjustment::VirtualAdjustment::@106065375072164260365214033034320247050276346205 Itanium

int64_t VCallOffsetOffset

The offset (in bytes), relative to the address point, of the virtual call offset.