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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

30#include "llvm/ADT/StringExtras.h"

31#include "llvm/ADT/StringSet.h"

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

33

34using namespace clang;

35using namespace CodeGen;

36

37namespace {

38

39

40struct VBTableGlobals {

43};

44

45class MicrosoftCXXABI : public CGCXXABI {

46public:

48 : CGCXXABI(CGM), BaseClassDescriptorType(nullptr),

49 ClassHierarchyDescriptorType(nullptr),

50 CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr),

51 ThrowInfoType(nullptr) {

54 "visibility export mapping option unimplemented in this ABI");

55 }

56

59

61

63

65

67

68

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

73 return true;

74

76 return false;

77

78 case Dtor_Comdat: llvm_unreachable("emitting dtor comdat as function?");

79 }

80 llvm_unreachable("bad dtor kind");

81 }

82

83

84 return false;

85 }

86

89 assert(Args.size() >= 2 &&

90 "expected the arglist to have at least two args!");

91

92

95 return 2;

96 return 1;

97 }

98

100 std::vector VBPtrOffsets;

103

104 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);

105 for (const std::unique_ptr &VBT : *VBGlobals.VBTables) {

108 CharUnits Offs = VBT->NonVirtualOffset;

110 if (VBT->getVBaseWithVPtr())

112 VBPtrOffsets.push_back(Offs);

113 }

114 llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end());

115 return VBPtrOffsets;

116 }

117

120

124

127

129

130 llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,

132

136

137

139

140

141 if (getContext().getLangOpts().EHAsynch)

143 else

145 }

146

151 llvm::Type *StdTypeInfoPtrTy) override;

152

154 QualType SrcRecordTy) override;

155

157

158 return false;

159 }

163 llvm::BasicBlock *CastSuccess,

164 llvm::BasicBlock *CastFail) override {

165 llvm_unreachable("unsupported");

166 }

167

171 llvm::BasicBlock *CastEnd) override;

172

174 QualType SrcRecordTy) override;

175

178 return false;

179 }

180

181 llvm::Value *

185

186 llvm::BasicBlock *

189

190 llvm::BasicBlock *

192

195

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230 AddedStructorArgCounts

233

234

238 }

239

243

244 llvm::GlobalValue::LinkageTypes

247

249

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

252

253 if (MD->isVirtual()) {

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

256

257

259 return MD->getParent();

260

261

262

264 }

267

268

269

270

271

272

273

275 return nullptr;

276 }

277 return MD->getParent();

278 }

279

283 bool VirtualCall) override;

284

287

289

293 bool ForVirtualBase,

295

299 bool ForVirtualBase,

301

306

308 llvm::GlobalVariable *VTable);

309

312

314 CodeGenFunction::VPtr Vptr) override;

315

316

317

319 return !VTableClass->hasAttr();

320 }

321

322 llvm::Constant *

325

329

332

334 Address This, llvm::Type *Ty,

336

337 llvm::Value *

340 DeleteOrMemberCallExpr E,

341 llvm::CallBase **CallOrInvoke) override;

342

346 "Only deleting destructor thunks are available in this ABI");

349 }

350

352

353 llvm::GlobalVariable *

355 llvm::GlobalVariable::LinkageTypes Linkage);

356

357 llvm::GlobalVariable *

358 getAddrOfVirtualDisplacementMap(const CXXRecordDecl *SrcRD,

361 llvm::raw_svector_ostream Out(OutName);

362 getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out);

363 StringRef MangledName = OutName.str();

364

365 if (auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName))

366 return VDispMap;

367

369 unsigned NumEntries = 1 + SrcRD->getNumVBases();

371 llvm::UndefValue::get(CGM.IntTy));

372 Map[0] = llvm::ConstantInt::get(CGM.IntTy, 0);

373 bool AnyDifferent = false;

374 for (const auto &I : SrcRD->vbases()) {

375 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();

377 continue;

378

379 unsigned SrcVBIndex = VTContext.getVBTableIndex(SrcRD, VBase);

380 unsigned DstVBIndex = VTContext.getVBTableIndex(DstRD, VBase);

381 Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.IntTy, DstVBIndex * 4);

382 AnyDifferent |= SrcVBIndex != DstVBIndex;

383 }

384

385 if (!AnyDifferent)

386 return nullptr;

387

388 llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.IntTy, Map.size());

389 llvm::Constant *Init = llvm::ConstantArray::get(VDispMapTy, Map);

390 llvm::GlobalValue::LinkageTypes Linkage =

392 ? llvm::GlobalValue::LinkOnceODRLinkage

393 : llvm::GlobalValue::InternalLinkage;

394 auto *VDispMap = new llvm::GlobalVariable(

396 Init, MangledName);

397 return VDispMap;

398 }

399

401 llvm::GlobalVariable *GV) const;

402

403 void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,

407

409 Thunk->setLinkage(llvm::GlobalValue::InternalLinkage);

411 Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage);

412 else

413 Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);

414 }

415

416 bool exportThunk() override { return false; }

417

421

425

430

433 LangOptions::MSVC2019_5) &&

436 }

439

441 llvm::GlobalVariable *DeclPtr,

442 bool PerformInit) override;

444 llvm::FunctionCallee Dtor,

445 llvm::Constant *Addr) override;

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

471 QualType elementType) override;

476 llvm::Value *NumElements,

478 QualType ElementType) override;

482

483 friend struct MSRTTIBuilder;

484

485 bool isImageRelative() const {

487 }

488

489

490 llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) {

492 TDTypeName += llvm::utostr(TypeInfoString.size());

493 llvm::StructType *&TypeDescriptorType =

494 TypeDescriptorTypeMap[TypeInfoString.size()];

495 if (TypeDescriptorType)

496 return TypeDescriptorType;

497 llvm::Type *FieldTypes[] = {

500 llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)};

501 TypeDescriptorType =

502 llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName);

503 return TypeDescriptorType;

504 }

505

506 llvm::Type *getImageRelativeType(llvm::Type *PtrType) {

507 if (!isImageRelative())

508 return PtrType;

509 return CGM.IntTy;

510 }

511

512 llvm::StructType *getBaseClassDescriptorType() {

513 if (BaseClassDescriptorType)

514 return BaseClassDescriptorType;

515 llvm::Type *FieldTypes[] = {

516 getImageRelativeType(CGM.Int8PtrTy),

523 };

524 BaseClassDescriptorType = llvm::StructType::create(

525 CGM.getLLVMContext(), FieldTypes, "rtti.BaseClassDescriptor");

526 return BaseClassDescriptorType;

527 }

528

529 llvm::StructType *getClassHierarchyDescriptorType() {

530 if (ClassHierarchyDescriptorType)

531 return ClassHierarchyDescriptorType;

532

533 llvm::Type *FieldTypes[] = {CGM.IntTy, CGM.IntTy, CGM.IntTy,

535 ClassHierarchyDescriptorType =

536 llvm::StructType::create(FieldTypes, "rtti.ClassHierarchyDescriptor");

537 return ClassHierarchyDescriptorType;

538 }

539

540 llvm::StructType *getCompleteObjectLocatorType() {

541 if (CompleteObjectLocatorType)

542 return CompleteObjectLocatorType;

543 llvm::Type *FieldTypes[] = {

547 getImageRelativeType(CGM.Int8PtrTy),

549 getImageRelativeType(CGM.VoidTy),

550 };

552 if (!isImageRelative())

553 FieldTypesRef = FieldTypesRef.drop_back();

554 CompleteObjectLocatorType =

555 llvm::StructType::create(FieldTypesRef, "rtti.CompleteObjectLocator");

556 return CompleteObjectLocatorType;

557 }

558

559 llvm::GlobalVariable *getImageBase() {

560 StringRef Name = "__ImageBase";

561 if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name))

562 return GV;

563

564 auto *GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,

565 true,

566 llvm::GlobalValue::ExternalLinkage,

567 nullptr, Name);

569 return GV;

570 }

571

572 llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {

573 if (!isImageRelative())

574 return PtrVal;

575

576 if (PtrVal->isNullValue())

577 return llvm::Constant::getNullValue(CGM.IntTy);

578

579 llvm::Constant *ImageBaseAsInt =

580 llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.IntPtrTy);

581 llvm::Constant *PtrValAsInt =

582 llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy);

583 llvm::Constant *Diff =

584 llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt,

585 true, true);

586 return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy);

587 }

588

589private:

592 }

593

594 llvm::Constant *getZeroInt() {

595 return llvm::ConstantInt::get(CGM.IntTy, 0);

596 }

597

598 llvm::Constant *getAllOnesInt() {

599 return llvm::Constant::getAllOnesValue(CGM.IntTy);

600 }

601

603

604 void

607

608

609

610

611 llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,

613 llvm::Value *VBPtrOffset,

614 llvm::Value *VBTableOffset,

615 llvm::Value **VBPtr = nullptr);

616

617 llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,

619 int32_t VBPtrOffset,

620 int32_t VBTableOffset,

621 llvm::Value **VBPtr = nullptr) {

622 assert(VBTableOffset % 4 == 0 && "should be byte offset into table of i32s");

623 llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),

624 *VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset);

625 return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);

626 }

627

628 std::tuple<Address, llvm::Value *, const CXXRecordDecl *>

631

632

633

636 llvm::Value *VirtualBaseAdjustmentOffset,

637 llvm::Value *VBPtrOffset );

638

639

640

641 llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,

642 bool IsMemberFunction,

644 CharUnits NonVirtualBaseAdjustment,

645 unsigned VBTableIndex);

646

648 llvm::Constant *MP);

649

650

652

653

654 const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD);

655

656

657 llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,

659

662

663public:

665

667

670 return RD->hasAttr();

671 }

672

674

679

681 llvm::Value *L,

682 llvm::Value *R,

684 bool Inequality) override;

685

687 llvm::Value *MemPtr,

689

690 llvm::Value *

694

695 llvm::Value *EmitNonNullMemberPointerConversion(

700

703 llvm::Value *Src) override;

704

706 llvm::Constant *Src) override;

707

712

715 Address This, llvm::Value *&ThisPtrForCall,

716 llvm::Value *MemPtr,

718

720

721 llvm::StructType *getCatchableTypeType() {

722 if (CatchableTypeType)

723 return CatchableTypeType;

724 llvm::Type *FieldTypes[] = {

725 CGM.IntTy,

726 getImageRelativeType(CGM.Int8PtrTy),

727 CGM.IntTy,

728 CGM.IntTy,

729 CGM.IntTy,

730 CGM.IntTy,

731 getImageRelativeType(CGM.Int8PtrTy)

732 };

733 CatchableTypeType = llvm::StructType::create(

734 CGM.getLLVMContext(), FieldTypes, "eh.CatchableType");

735 return CatchableTypeType;

736 }

737

738 llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) {

739 llvm::StructType *&CatchableTypeArrayType =

740 CatchableTypeArrayTypeMap[NumEntries];

741 if (CatchableTypeArrayType)

742 return CatchableTypeArrayType;

743

745 CTATypeName += llvm::utostr(NumEntries);

746 llvm::Type *CTType = getImageRelativeType(CGM.UnqualPtrTy);

747 llvm::Type *FieldTypes[] = {

748 CGM.IntTy,

749 llvm::ArrayType::get(CTType, NumEntries)

750 };

751 CatchableTypeArrayType =

752 llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, CTATypeName);

753 return CatchableTypeArrayType;

754 }

755

756 llvm::StructType *getThrowInfoType() {

757 if (ThrowInfoType)

758 return ThrowInfoType;

759 llvm::Type *FieldTypes[] = {

760 CGM.IntTy,

761 getImageRelativeType(CGM.Int8PtrTy),

762 getImageRelativeType(CGM.Int8PtrTy),

763 getImageRelativeType(CGM.Int8PtrTy)

764 };

765 ThrowInfoType = llvm::StructType::create(CGM.getLLVMContext(), FieldTypes,

766 "eh.ThrowInfo");

767 return ThrowInfoType;

768 }

769

771

772

774 llvm::FunctionType *FTy =

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

776 llvm::FunctionCallee Throw =

778

780 if (auto *Fn = dyn_castllvm::Function(Throw.getCallee()))

781 Fn->setCallingConv(llvm::CallingConv::X86_StdCall);

782 }

783 return Throw;

784 }

785

786 llvm::Function *getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,

788

789 llvm::Constant *getCatchableType(QualType T,

790 uint32_t NVOffset = 0,

791 int32_t VBPtrOffset = -1,

792 uint32_t VBIndex = 0);

793

794 llvm::GlobalVariable *getCatchableTypeArray(QualType T);

795

797

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

801

802 bool

804

805private:

806 typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;

807 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;

808 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;

809

810 VFTablesMapTy VFTablesMap;

811 VTablesMapTy VTablesMap;

812

813

815

816

817

818 llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;

819

820

821

822 struct GuardInfo {

823 GuardInfo() = default;

824 llvm::GlobalVariable *Guard = nullptr;

825 unsigned BitIndex = 0;

826 };

827

828

829

830 llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;

831 llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap;

832 llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap;

833

834 llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;

835 llvm::StructType *BaseClassDescriptorType;

836 llvm::StructType *ClassHierarchyDescriptorType;

837 llvm::StructType *CompleteObjectLocatorType;

838

839 llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays;

840

841 llvm::StructType *CatchableTypeType;

842 llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;

843 llvm::StructType *ThrowInfoType;

844};

845

846}

847

849MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {

850

851

852

854 return RAA_Default;

855

857 default:

858

859 return RAA_Indirect;

860

861 case llvm::Triple::thumb:

862

863

864

865 return RAA_Indirect;

866

867 case llvm::Triple::x86: {

868

869

870

871

874 return RAA_Indirect;

875

876

877

878 return RAA_DirectInMemory;

879 }

880

881 case llvm::Triple::x86_64:

882 case llvm::Triple::aarch64:

883 return RAA_Indirect;

884 }

885

886 llvm_unreachable("invalid enum");

887}

888

889void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,

894

895

898 llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,

899 nullptr);

900 if (UseGlobalDelete)

902}

903

904void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {

905 llvm::Value *Args[] = {llvm::ConstantPointerNull::get(CGM.Int8PtrTy),

906 llvm::ConstantPointerNull::get(CGM.UnqualPtrTy)};

908 if (isNoReturn)

910 else

912}

913

914void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,

916

917

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

919 llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock();

920 llvm::CatchPadInst *CPI =

921 castllvm::CatchPadInst(CatchPadBB->getFirstNonPHI());

923

924

925

926 if (!CatchParam || !CatchParam->getDeclName()) {

928 return;

929 }

930

932 CPI->setArgOperand(2, var.getObjectAddress(CGF).emitRawPointer(CGF));

935}

936

937

938

939

940std::tuple<Address, llvm::Value *, const CXXRecordDecl *>

945 const ASTContext &Context = getContext();

946

947

948

949

951 return std::make_tuple(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0),

952 SrcDecl);

953

954

955

957 for (auto &Base : SrcDecl->vbases()) {

958 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();

960 PolymorphicBase = BaseDecl;

961 break;

962 }

963 }

964 assert(PolymorphicBase && "polymorphic class has no apparent vfptr?");

965

966 llvm::Value *Offset =

967 GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase);

969 Value.getElementType(), Value.emitRawPointer(CGF), Offset);

972 return std::make_tuple(Address(Ptr, CGF.Int8Ty, VBaseAlign), Offset,

973 PolymorphicBase);

974}

975

976bool MicrosoftCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {

978 return !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();

979}

980

982 llvm::Value *Argument) {

983 llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};

984 llvm::FunctionType *FTy =

985 llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false);

986 llvm::Value *Args[] = {Argument};

989}

990

991void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {

992 llvm::CallBase *Call =

994 Call->setDoesNotReturn();

995 CGF.Builder.CreateUnreachable();

996}

997

998llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,

1001 llvm::Type *StdTypeInfoPtrTy) {

1002 std::tie(ThisPtr, std::ignore, std::ignore) =

1003 performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);

1005 return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy);

1006}

1007

1008bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,

1011 return SrcIsPtr &&

1012 !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();

1013}

1014

1015llvm::Value *MicrosoftCXXABI::emitDynamicCastCall(

1017 QualType DestRecordTy, llvm::BasicBlock *CastEnd) {

1018 llvm::Value *SrcRTTI =

1020 llvm::Value *DestRTTI =

1022

1023 llvm::Value *Offset;

1024 std::tie(This, Offset, std::ignore) =

1025 performBaseAdjustment(CGF, This, SrcRecordTy);

1026 llvm::Value *ThisPtr = This.emitRawPointer(CGF);

1027 Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty);

1028

1029

1030

1031

1032

1033

1034

1038 llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),

1039 "__RTDynamicCast");

1040 llvm::Value *Args[] = {

1041 ThisPtr, Offset, SrcRTTI, DestRTTI,

1044}

1045

1046llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,

1049 std::tie(Value, std::ignore, std::ignore) =

1050 performBaseAdjustment(CGF, Value, SrcRecordTy);

1051

1052

1053

1054 llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};

1056 llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),

1057 "__RTCastToVoid");

1058 llvm::Value *Args[] = {Value.emitRawPointer(CGF)};

1060}

1061

1062bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {

1063 return false;

1064}

1065

1066llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(

1069 const ASTContext &Context = getContext();

1072 llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars);

1075 IntSize *

1077 llvm::Value *VBTableOffset =

1078 llvm::ConstantInt::get(CGM.IntTy, VBTableChars.getQuantity());

1079

1080 llvm::Value *VBPtrToNewBase =

1081 GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset);

1082 VBPtrToNewBase =

1083 CGF.Builder.CreateSExtOrBitCast(VBPtrToNewBase, CGM.PtrDiffTy);

1084 return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);

1085}

1086

1087bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {

1088 return isa(GD.getDecl());

1089}

1090

1092 return isa(GD.getDecl()) &&

1094}

1095

1096bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const {

1098}

1099

1102

1103

1104

1106 uint64_t NumElts = 0;

1109 isa(Base)) {

1110 return true;

1111 }

1112

1113

1114

1115

1116

1117

1118

1119

1120

1121

1122

1123

1124

1125

1126

1127

1128

1129

1130

1131

1132

1133

1134

1136 return false;

1138 return false;

1140 return false;

1142 return false;

1144 return false;

1146 if (auto *Ctor = dyn_cast(D)) {

1147 if (Ctor->isUserProvided())

1148 return false;

1149 } else if (auto *Template = dyn_cast(D)) {

1150 if (isa(Template->getTemplatedDecl()))

1151 return false;

1152 } else if (auto *MethodDecl = dyn_cast(D)) {

1153 if (MethodDecl->isCopyAssignmentOperator() && MethodDecl->isDeleted())

1154 return false;

1155 }

1156 }

1158 return false;

1159 return true;

1160}

1161

1162bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {

1164 if (!RD)

1165 return false;

1166

1169

1170

1171 bool isIndirectReturn = !isTrivialForABI || FI.isInstanceMethod();

1172

1173 if (isIndirectReturn) {

1176

1177

1179

1180

1181

1183

1184 return true;

1185 }

1186

1187

1188 return false;

1189}

1190

1191llvm::BasicBlock *

1192MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,

1194 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);

1195 assert(IsMostDerivedClass &&

1196 "ctor for a class with virtual bases must have an implicit parameter");

1197 llvm::Value *IsCompleteObject =

1198 CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object");

1199

1200 llvm::BasicBlock *CallVbaseCtorsBB = CGF.createBasicBlock("ctor.init_vbases");

1201 llvm::BasicBlock *SkipVbaseCtorsBB = CGF.createBasicBlock("ctor.skip_vbases");

1202 CGF.Builder.CreateCondBr(IsCompleteObject,

1203 CallVbaseCtorsBB, SkipVbaseCtorsBB);

1204

1205 CGF.EmitBlock(CallVbaseCtorsBB);

1206

1207

1208 EmitVBPtrStores(CGF, RD);

1209

1210

1211

1212 return SkipVbaseCtorsBB;

1213}

1214

1215llvm::BasicBlock *

1216MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) {

1217 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);

1218 assert(IsMostDerivedClass &&

1219 "ctor for a class with virtual bases must have an implicit parameter");

1220 llvm::Value *IsCompleteObject =

1221 CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object");

1222

1223 llvm::BasicBlock *CallVbaseDtorsBB = CGF.createBasicBlock("Dtor.dtor_vbases");

1224 llvm::BasicBlock *SkipVbaseDtorsBB = CGF.createBasicBlock("Dtor.skip_vbases");

1225 CGF.Builder.CreateCondBr(IsCompleteObject,

1226 CallVbaseDtorsBB, SkipVbaseDtorsBB);

1227

1228 CGF.EmitBlock(CallVbaseDtorsBB);

1229

1230

1231 return SkipVbaseDtorsBB;

1232}

1233

1234void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(

1236

1237

1238

1239

1240

1241

1242

1243

1244

1245

1246

1247

1248

1249 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);

1253

1254 llvm::Value *Int8This = nullptr;

1255

1257 const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();

1258 auto I = VBaseMap.find(VBase);

1259 assert(I != VBaseMap.end());

1260 if (!I->second.hasVtorDisp())

1261 continue;

1262

1263 llvm::Value *VBaseOffset =

1264 GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);

1265 uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();

1266

1267

1268 llvm::Value *VtorDispValue = Builder.CreateSub(

1269 VBaseOffset, llvm::ConstantInt::get(CGM.PtrDiffTy, ConstantVBaseOffset),

1270 "vtordisp.value");

1271 VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.Int32Ty);

1272

1273 if (!Int8This)

1274 Int8This = getThisValue(CGF);

1275

1276 llvm::Value *VtorDispPtr =

1277 Builder.CreateInBoundsGEP(CGF.Int8Ty, Int8This, VBaseOffset);

1278

1279 VtorDispPtr = Builder.CreateConstGEP1_32(CGF.Int8Ty, VtorDispPtr, -4);

1280

1281 Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr,

1283 }

1284}

1285

1289 false, true);

1292 return ExpectedCallingConv == ActualCallingConv;

1293}

1294

1296

1298

1299

1300

1301

1302

1303 if (D->hasAttr() && D->isDefaultConstructor() &&

1304 D->isDefined()) {

1307 Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);

1309 }

1310 }

1311}

1312

1313void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,

1317 const ASTContext &Context = getContext();

1319

1320 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);

1321 for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {

1322 const std::unique_ptr &VBT = (*VBGlobals.VBTables)[I];

1323 llvm::GlobalVariable *GV = VBGlobals.Globals[I];

1326 CharUnits Offs = VBT->NonVirtualOffset;

1328 if (VBT->getVBaseWithVPtr())

1331 llvm::Value *GVPtr =

1335 }

1336}

1337

1339MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,

1341 AddedStructorArgCounts Added;

1342

1343 if (isa(GD.getDecl()) &&

1345

1346 ArgTys.push_back(getContext().IntTy);

1347 ++Added.Suffix;

1348 }

1349 auto *CD = dyn_cast(GD.getDecl());

1350 if (!CD)

1351 return Added;

1352

1353

1354

1355

1358 if (Class->getNumVBases()) {

1360 ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy);

1361 ++Added.Prefix;

1362 } else {

1363 ArgTys.push_back(getContext().IntTy);

1364 ++Added.Suffix;

1365 }

1366 }

1367

1368 return Added;

1369}

1370

1371void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,

1374

1375

1377 GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);

1378 } else {

1381 }

1382}

1383

1384llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(

1386

1387

1389 return llvm::GlobalValue::InternalLinkage;

1390

1391 switch (DT) {

1393

1394

1397

1398

1399

1400 if (Dtor->hasAttr())

1401 return llvm::GlobalValue::WeakODRLinkage;

1402 if (Dtor->hasAttr())

1403 return llvm::GlobalValue::AvailableExternallyLinkage;

1404 return llvm::GlobalValue::LinkOnceODRLinkage;

1406

1407

1408

1409 return llvm::GlobalValue::LinkOnceODRLinkage;

1411 llvm_unreachable("MS C++ ABI does not support comdat dtors");

1412 }

1413 llvm_unreachable("invalid dtor type");

1414}

1415

1416void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {

1417

1418

1420

1421

1422

1423

1424

1425 if (D->getParent()->getNumVBases() > 0 && D->hasAttr())

1427}

1428

1430MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {

1432

1433 if (const CXXDestructorDecl *DD = dyn_cast(MD)) {

1434

1435

1438

1439

1440

1442 }

1443

1447

1448

1449

1450

1451

1452 if (isa(MD))

1454

1457 getContext().getASTRecordLayout(MD->getParent());

1459 }

1460

1461 return Adjustment;

1462}

1463

1464Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(

1466 bool VirtualCall) {

1467 if (!VirtualCall) {

1468

1469

1470 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD);

1471 if (Adjustment.isZero())

1472 return This;

1473

1477 }

1478

1480

1482 if (const CXXDestructorDecl *DD = dyn_cast(MD)) {

1483

1484

1486 return This;

1487

1488

1489

1491 }

1494

1496

1497

1498

1499

1502

1505 Result = Result.withElementType(CGF.Int8Ty);

1506

1509 llvm::Value *VBaseOffset =

1510 GetVirtualBaseClassOffset(CGF, Result, Derived, VBase);

1512 Result.getElementType(), Result.emitRawPointer(CGF), VBaseOffset);

1515 Result = Address(VBasePtr, CGF.Int8Ty, VBaseAlign);

1516 }

1517 if (!StaticOffset.isZero()) {

1519 Result = Result.withElementType(CGF.Int8Ty);

1521

1522

1523

1524

1526 } else {

1528 }

1529 }

1530 return Result;

1531}

1532

1533void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,

1538 assert(isa(MD) || isa(MD));

1542 &Context.Idents.get("is_most_derived"), Context.IntTy,

1543 ImplicitParamKind::Other);

1544

1545

1548 Params.insert(Params.begin() + 1, IsMostDerived);

1549 else

1550 Params.push_back(IsMostDerived);

1551 getStructorImplicitParamDecl(CGF) = IsMostDerived;

1555 &Context.Idents.get("should_call_delete"), Context.IntTy,

1556 ImplicitParamKind::Other);

1557 Params.push_back(ShouldDelete);

1558 getStructorImplicitParamDecl(CGF) = ShouldDelete;

1559 }

1560}

1561

1562void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {

1563

1565 return;

1566

1567

1568

1569

1570

1571

1572

1573

1574

1575

1576

1577

1578

1579 llvm::Value *This = loadIncomingCXXThis(CGF);

1582 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.CurGD);

1583 if (!Adjustment.isZero()) {

1587 }

1588 }

1589 setCXXABIThisValue(CGF, This);

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599 if (HasThisReturn(CGF.CurGD) || hasMostDerivedReturn(CGF.CurGD))

1601

1603 assert(getStructorImplicitParamDecl(CGF) &&

1604 "no implicit parameter for a constructor with virtual bases?");

1605 getStructorImplicitParamValue(CGF)

1608 "is_most_derived");

1609 }

1610

1612 assert(getStructorImplicitParamDecl(CGF) &&

1613 "no implicit parameter for a deleting destructor?");

1614 getStructorImplicitParamValue(CGF)

1617 "should_call_delete");

1618 }

1619}

1620

1623 bool ForVirtualBase, bool Delegating) {

1625

1626

1627 if (D->getParent()->getNumVBases())

1628 return AddedStructorArgs{};

1629

1630

1632 llvm::Value *MostDerivedArg;

1634 MostDerivedArg = getStructorImplicitParamValue(CGF);

1635 } else {

1637 }

1639 return AddedStructorArgs::prefix({{MostDerivedArg, getContext().IntTy}});

1640 }

1641 return AddedStructorArgs::suffix({{MostDerivedArg, getContext().IntTy}});

1642}

1643

1644llvm::Value *MicrosoftCXXABI::getCXXDestructorImplicitParam(

1646 bool ForVirtualBase, bool Delegating) {

1647 return nullptr;

1648}

1649

1650void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,

1655

1656

1657

1660

1663

1665 assert(Type != CXXDtorType::Dtor_Deleting &&

1666 "The deleting destructor should only be called via a virtual call");

1667 This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD, Type),

1668 This, false);

1669 }

1670

1671 llvm::BasicBlock *BaseDtorEndBB = nullptr;

1672 if (ForVirtualBase && isa(CGF.CurCodeDecl)) {

1673 BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);

1674 }

1675

1680 ThisTy,

1682 QualType(), nullptr);

1683 if (BaseDtorEndBB) {

1684

1685 CGF.Builder.CreateBr(BaseDtorEndBB);

1687 }

1688}

1689

1690void MicrosoftCXXABI::emitVTableTypeMetadata(const VPtrInfo &Info,

1692 llvm::GlobalVariable *VTable) {

1693

1694

1695

1698 return;

1699

1700

1701

1703 llvm::DenseSet<const CXXRecordDecl *> Visited;

1704 llvm::GlobalObject::VCallVisibility TypeVis =

1706 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)

1707 VTable->setVCallVisibilityMetadata(TypeVis);

1708 }

1709

1710

1711

1712

1714 getContext().getLangOpts().RTTIData

1715 ? getContext().toCharUnitsFromBits(

1716 getContext().getTargetInfo().getPointerWidth(LangAS::Default))

1718

1721 return;

1722 }

1723

1724

1727

1728

1729

1733

1735 getContext().getASTRecordLayout(DerivedRD);

1740 else

1741 Offset = VBI->second.VBaseOffset;

1742 if (!Offset.isZero())

1743 return;

1745 }

1746

1747

1750}

1751

1752void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,

1756

1757 for (const std::unique_ptr& Info : VFPtrs) {

1758 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC);

1759 if (VTable->hasInitializer())

1760 continue;

1761

1764

1765 llvm::Constant *RTTI = nullptr;

1767 [](const VTableComponent &VTC) { return VTC.isRTTIKind(); }))

1768 RTTI = getMSCompleteObjectLocator(RD, *Info);

1769

1771 auto components = builder.beginStruct();

1773 VTable->hasLocalLinkage());

1774 components.finishAndSetAsInitializer(VTable);

1775

1776 emitVTableTypeMetadata(*Info, RD, VTable);

1777 }

1778}

1779

1780bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(

1782 return Vptr.NearestVBase != nullptr;

1783}

1784

1785llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(

1788 llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass);

1789 if (!VTableAddressPoint) {

1790 assert(Base.getBase()->getNumVBases() &&

1791 !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());

1792 }

1793 return VTableAddressPoint;

1794}

1795

1799 llvm::raw_svector_ostream Out(Name);

1801}

1802

1803llvm::Constant *

1806 (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());

1807 VFTableIdTy ID(VTableClass, Base.getBaseOffset());

1808 return VFTablesMap[ID];

1809}

1810

1811llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,

1813

1814

1815

1816

1817 VFTableIdTy ID(RD, VPtrOffset);

1818 VTablesMapTy::iterator I;

1819 bool Inserted;

1820 std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID, nullptr));

1821 if (!Inserted)

1822 return I->second;

1823

1824 llvm::GlobalVariable *&VTable = I->second;

1825

1828

1829 if (DeferredVFTables.insert(RD).second) {

1830

1831

1833

1834#ifndef NDEBUG

1835

1836

1837 llvm::StringSet<> ObservedMangledNames;

1838 for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {

1841 if (!ObservedMangledNames.insert(Name.str()).second)

1842 llvm_unreachable("Already saw this mangling before?");

1843 }

1844#endif

1845 }

1846

1847 const std::unique_ptr *VFPtrI =

1848 llvm::find_if(VFPtrs, [&](const std::unique_ptr &VPI) {

1849 return VPI->FullOffsetInMDC == VPtrOffset;

1850 });

1851 if (VFPtrI == VFPtrs.end()) {

1852 VFTablesMap[ID] = nullptr;

1853 return nullptr;

1854 }

1855 const std::unique_ptr &VFPtr = *VFPtrI;

1856

1859

1860

1861

1862

1863

1864

1865

1866

1867 llvm::GlobalValue::LinkageTypes VFTableLinkage =

1868 RD->hasAttr() ? llvm::GlobalValue::LinkOnceODRLinkage

1870 bool VFTableComesFromAnotherTU =

1871 llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) ||

1872 llvm::GlobalValue::isExternalLinkage(VFTableLinkage);

1873 bool VTableAliasIsRequred =

1874 !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData;

1875

1876 if (llvm::GlobalValue *VFTable =

1877 CGM.getModule().getNamedGlobal(VFTableName)) {

1878 VFTablesMap[ID] = VFTable;

1879 VTable = VTableAliasIsRequred

1880 ? castllvm::GlobalVariable(

1881 castllvm::GlobalAlias(VFTable)->getAliaseeObject())

1882 : cast<llvm::GlobalVariable>(VFTable);

1883 return VTable;

1884 }

1885

1888 llvm::GlobalValue::LinkageTypes VTableLinkage =

1889 VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;

1890

1891 StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();

1892

1894

1895

1896

1897 llvm::GlobalValue *VFTable;

1898 VTable = new llvm::GlobalVariable(CGM.getModule(), VTableType,

1899 true, VTableLinkage,

1900 nullptr, VTableName);

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

1902

1903 llvm::Comdat *C = nullptr;

1904 if (!VFTableComesFromAnotherTU &&

1905 llvm::GlobalValue::isWeakForLinker(VFTableLinkage))

1906 C = CGM.getModule().getOrInsertComdat(VFTableName.str());

1907

1908

1909

1910

1911 if (VTableAliasIsRequred) {

1912 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.Int32Ty, 0),

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

1914 llvm::ConstantInt::get(CGM.Int32Ty, 1)};

1915

1916

1917 llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(

1918 VTable->getValueType(), VTable, GEPIndices);

1919 if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {

1920 VFTableLinkage = llvm::GlobalValue::ExternalLinkage;

1921 if (C)

1922 C->setSelectionKind(llvm::Comdat::Largest);

1923 }

1924 VFTable = llvm::GlobalAlias::create(CGM.Int8PtrTy,

1925 0, VFTableLinkage,

1926 VFTableName.str(), VTableGEP,

1928 VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

1929 } else {

1930

1931

1932

1933

1934 VFTable = VTable;

1935 }

1936 if (C)

1937 VTable->setComdat(C);

1938

1939 if (RD->hasAttr())

1940 VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);

1941

1942 VFTablesMap[ID] = VFTable;

1943 return VTable;

1944}

1945

1949 llvm::Type *Ty,

1952

1955 adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);

1956

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

1958 llvm::Value *VTable =

1960

1963

1964

1965

1966 auto getObjectWithVPtr = [&] {

1969 [&](const std::unique_ptr &Info) {

1970 return Info->FullOffsetInMDC == ML.VFPtrOffset;

1971 })

1972 ->get()

1973 ->ObjectWithVPtr;

1974 };

1975

1976 llvm::Value *VFunc;

1979 getObjectWithVPtr(), VTable, Ty,

1982 8);

1983 } else {

1986

1987 llvm::Value *VFuncPtr =

1988 Builder.CreateConstInBoundsGEP1_64(Ty, VTable, ML.Index, "vfn");

1989 VFunc = Builder.CreateAlignedLoad(Ty, VFuncPtr, CGF.getPointerAlign());

1990 }

1991

1994}

1995

1996llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(

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

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

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

2004

2005

2006

2012

2014 llvm::Value *ImplicitParam = llvm::ConstantInt::get(

2015 llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()),

2017

2019 if (CE) {

2020 ThisTy = CE->getObjectType();

2021 } else {

2022 ThisTy = D->getDestroyedType();

2023 }

2024

2025 This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);

2028 ImplicitParam, Context.IntTy, CE, CallOrInvoke);

2030}

2031

2032const VBTableGlobals &

2033MicrosoftCXXABI::enumerateVBTables(const CXXRecordDecl *RD) {

2034

2035

2036 llvm::DenseMap<const CXXRecordDecl*, VBTableGlobals>::iterator Entry;

2037 bool Added;

2038 std::tie(Entry, Added) =

2039 VBTablesMap.insert(std::make_pair(RD, VBTableGlobals()));

2040 VBTableGlobals &VBGlobals = Entry->second;

2041 if (!Added)

2042 return VBGlobals;

2043

2045 VBGlobals.VBTables = &Context.enumerateVBTables(RD);

2046

2047

2048

2050 for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(),

2051 E = VBGlobals.VBTables->end();

2052 I != E; ++I) {

2053 VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD, Linkage));

2054 }

2055

2056 return VBGlobals;

2057}

2058

2059llvm::Function *

2060MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,

2062 assert(!isa(MD) && !isa(MD) &&

2063 "can't form pointers to ctors or virtual dtors");

2064

2065

2067 llvm::raw_svector_ostream Out(ThunkName);

2068 getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);

2069

2070

2071 if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))

2072 return castllvm::Function(GV);

2073

2074

2078 llvm::Function *ThunkFn =

2079 llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,

2080 ThunkName.str(), &CGM.getModule());

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

2082

2084 ? llvm::GlobalValue::LinkOnceODRLinkage

2085 : llvm::GlobalValue::InternalLinkage);

2087 ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));

2088

2091

2092

2093

2094

2095

2096 ThunkFn->addFnAttr("thunk");

2097

2098

2099 ThunkFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);

2100

2101

2105

2106

2107

2109 buildThisParam(CGF, FunctionArgs);

2110

2111

2114

2116 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));

2117

2118

2119

2120 llvm::Type *ThunkPtrTy = CGF.UnqualPtrTy;

2121 llvm::Value *VTable =

2123

2124 llvm::Value *VFuncPtr = CGF.Builder.CreateConstInBoundsGEP1_64(

2125 ThunkPtrTy, VTable, ML.Index, "vfn");

2126 llvm::Value *Callee =

2128

2130

2131 return ThunkFn;

2132}

2133

2134void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {

2135 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);

2136 for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {

2137 const std::unique_ptr& VBT = (*VBGlobals.VBTables)[I];

2138 llvm::GlobalVariable *GV = VBGlobals.Globals[I];

2139 if (GV->isDeclaration())

2140 emitVBTableDefinition(*VBT, RD, GV);

2141 }

2142}

2143

2144llvm::GlobalVariable *

2146 llvm::GlobalVariable::LinkageTypes Linkage) {

2148 llvm::raw_svector_ostream Out(OutName);

2149 getMangleContext().mangleCXXVBTable(RD, VBT.MangledPath, Out);

2150 StringRef Name = OutName.str();

2151

2152 llvm::ArrayType *VBTableType =

2154

2155 assert(!CGM.getModule().getNamedGlobal(Name) &&

2156 "vbtable with this name already exists: mangling bug?");

2161 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

2162

2163 if (RD->hasAttr())

2164 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);

2165 else if (RD->hasAttr())

2166 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);

2167

2168 if (!GV->hasExternalLinkage())

2169 emitVBTableDefinition(VBT, RD, GV);

2170

2171 return GV;

2172}

2173

2174void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT,

2176 llvm::GlobalVariable *GV) const {

2178

2180 "should only emit vbtables for classes with vbtables");

2181

2184 const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);

2185

2187 nullptr);

2188

2189

2191 Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity());

2192

2194 for (const auto &I : ObjectWithVPtr->vbases()) {

2195 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();

2197 assert(!Offset.isNegative());

2198

2199

2202 CompleteVBPtrOffset +=

2204 Offset -= CompleteVBPtrOffset;

2205

2206 unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase);

2207 assert(Offsets[VBIndex] == nullptr && "The same vbindex seen twice?");

2208 Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity());

2209 }

2210

2211 assert(Offsets.size() ==

2212 castllvm::ArrayType(GV->getValueType())->getNumElements());

2213 llvm::ArrayType *VBTableType =

2214 llvm::ArrayType::get(CGM.IntTy, Offsets.size());

2215 llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets);

2216 GV->setInitializer(Init);

2217

2218 if (RD->hasAttr())

2219 GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage);

2220}

2221

2222llvm::Value *MicrosoftCXXABI::performThisAdjustment(

2227 return This.emitRawPointer(CGF);

2228

2230

2231 llvm::Value *V;

2233 V = This.emitRawPointer(CGF);

2234 } else {

2236

2241 llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp");

2243 CGF.Builder.CreateNeg(VtorDisp));

2244

2245

2246

2247

2248

2250

2251

2252

2255 llvm::Value *VBPtr;

2256 llvm::Value *VBaseOffset = GetVBaseOffsetFromVBPtr(

2261 }

2262 }

2263

2265

2266

2267

2269 }

2270

2271

2272 return V;

2273}

2274

2275llvm::Value *MicrosoftCXXABI::performReturnAdjustment(

2278

2280 return Ret.emitRawPointer(CGF);

2281

2283

2284 llvm::Value *V = Ret.emitRawPointer(CGF);

2288 llvm::Value *VBPtr;

2289 llvm::Value *VBaseOffset =

2293 }

2294

2297

2298 return V;

2299}

2300

2301bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,

2303

2304

2306}

2307

2308bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {

2309

2310

2311 return expr->getAllocatedType().isDestructedType();

2312}

2313

2315

2316

2320}

2321

2322llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,

2327}

2328

2331 llvm::Value *numElements,

2334 assert(requiresArrayCookie(expr));

2335

2336

2337 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);

2338

2339

2340 Address cookiePtr = newPtr;

2341

2342

2345

2346

2347

2349}

2350

2352 llvm::FunctionCallee Dtor,

2353 llvm::Constant *Addr) {

2354

2355 llvm::Constant *DtorStub = CGF.createAtExitStub(VD, Dtor, Addr);

2356

2357

2358 llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get(

2359 CGF.IntTy, DtorStub->getType(), false);

2360

2362 TLRegDtorTy, "__tlregdtor", llvm::AttributeList(), true);

2363 if (llvm::Function *TLRegDtorFn =

2364 dyn_castllvm::Function(TLRegDtor.getCallee()))

2365 TLRegDtorFn->setDoesNotThrow();

2366

2368}

2369

2371 llvm::FunctionCallee Dtor,

2372 llvm::Constant *Addr) {

2374 return;

2375

2376 if (D.getTLSKind())

2378

2379

2382

2383

2385}

2386

2387void MicrosoftCXXABI::EmitThreadLocalInitFuncs(

2391 if (CXXThreadLocalInits.empty())

2392 return;

2393

2395 llvm::Triple::x86

2396 ? "/include:___dyn_tls_init@12"

2397 : "/include:__dyn_tls_init");

2398

2399

2400

2401

2402 auto AddToXDU = [&CGM](llvm::Function *InitFunc) {

2403 llvm::GlobalVariable *InitFuncPtr = new llvm::GlobalVariable(

2404 CGM.getModule(), InitFunc->getType(), true,

2405 llvm::GlobalVariable::InternalLinkage, InitFunc,

2406 Twine(InitFunc->getName(), "$initializer$"));

2407 InitFuncPtr->setSection(".CRT$XDU");

2408

2409

2411 return InitFuncPtr;

2412 };

2413

2414 std::vector<llvm::Function *> NonComdatInits;

2415 for (size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) {

2416 llvm::GlobalVariable *GV = castllvm::GlobalVariable(

2418 llvm::Function *F = CXXThreadLocalInits[I];

2419

2420

2421 if (llvm::Comdat *C = GV->getComdat())

2422 AddToXDU(F)->setComdat(C);

2423 else

2424 NonComdatInits.push_back(F);

2425 }

2426

2427 if (!NonComdatInits.empty()) {

2428 llvm::FunctionType *FTy =

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

2434

2435 AddToXDU(InitFunc);

2436 }

2437}

2438

2440

2441

2442

2443

2444 llvm::Type *VTy = llvm::Type::getInt8Ty(CGM.getLLVMContext());

2445 llvm::Constant *TlsGuardConstant =

2447 llvm::GlobalValue *TlsGuard = castllvm::GlobalValue(TlsGuardConstant);

2448

2449 TlsGuard->setThreadLocal(true);

2450

2451 return TlsGuard;

2452}

2453

2455

2456

2457 llvm::FunctionType *FTy =

2458 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), {},

2459 false);

2461 FTy, "__dyn_tls_on_demand_init",

2463 llvm::AttributeList::FunctionIndex,

2464 llvm::Attribute::NoUnwind),

2465 true);

2466}

2467

2469 llvm::BasicBlock *DynInitBB,

2470 llvm::BasicBlock *ContinueBB) {

2471 llvm::LoadInst *TlsGuardValue =

2473 llvm::Value *CmpResult =

2474 CGF.Builder.CreateICmpEQ(TlsGuardValue, CGF.Builder.getInt8(0));

2475 CGF.Builder.CreateCondBr(CmpResult, DynInitBB, ContinueBB);

2476}

2477

2479 llvm::GlobalValue *TlsGuard,

2480 llvm::BasicBlock *ContinueBB) {

2482 llvm::Function *InitializerFunction =

2483 castllvm::Function(Initializer.getCallee());

2484 llvm::CallInst *CallVal = CGF.Builder.CreateCall(InitializerFunction);

2485 CallVal->setCallingConv(InitializerFunction->getCallingConv());

2486

2487 CGF.Builder.CreateBr(ContinueBB);

2488}

2489

2491 llvm::BasicBlock *DynInitBB =

2493 llvm::BasicBlock *ContinueBB =

2495

2497

2499 CGF.Builder.SetInsertPoint(DynInitBB);

2501 CGF.Builder.SetInsertPoint(ContinueBB);

2502}

2503

2507

2508

2509

2510

2511

2513

2514

2515

2518

2520 Address Addr(V, RealVarTy, Alignment);

2521

2524 AlignmentSource::Decl)

2525 : CGF.MakeAddrLValue(Addr, LValType, AlignmentSource::Decl);

2526 return LV;

2527}

2528

2530 StringRef VarName("_Init_thread_epoch");

2532 if (auto *GV = CGM.getModule().getNamedGlobal(VarName))

2534 auto *GV = new llvm::GlobalVariable(

2536 false, llvm::GlobalVariable::ExternalLinkage,

2537 nullptr, VarName,

2538 nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);

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

2541}

2542

2544 llvm::FunctionType *FTy =

2545 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),

2548 FTy, "_Init_thread_header",

2550 llvm::AttributeList::FunctionIndex,

2551 llvm::Attribute::NoUnwind),

2552 true);

2553}

2554

2556 llvm::FunctionType *FTy =

2557 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),

2560 FTy, "_Init_thread_footer",

2562 llvm::AttributeList::FunctionIndex,

2563 llvm::Attribute::NoUnwind),

2564 true);

2565}

2566

2568 llvm::FunctionType *FTy =

2569 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),

2572 FTy, "_Init_thread_abort",

2574 llvm::AttributeList::FunctionIndex,

2575 llvm::Attribute::NoUnwind),

2576 true);

2577}

2578

2579namespace {

2582 unsigned GuardNum;

2583 ResetGuardBit(Address Guard, unsigned GuardNum)

2584 : Guard(Guard), GuardNum(GuardNum) {}

2585

2587

2588

2590 llvm::LoadInst *LI = Builder.CreateLoad(Guard);

2591 llvm::ConstantInt *Mask =

2592 llvm::ConstantInt::get(CGF.IntTy, ~(1ULL << GuardNum));

2593 Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard);

2594 }

2595};

2596

2598 llvm::Value *Guard;

2599 CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {}

2600

2602

2604 }

2605};

2606}

2607

2609 llvm::GlobalVariable *GV,

2610 bool PerformInit) {

2611

2612 if (D.isStaticLocal()) {

2613 assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());

2614

2615 llvm::Function *F = CGF.CurFn;

2616 F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);

2617 F->setComdat(CGM.getModule().getOrInsertComdat(F->getName()));

2619 return;

2620 }

2621

2622 bool ThreadlocalStatic = D.getTLSKind();

2623 bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics;

2624

2625

2626

2627 bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic;

2628

2630 llvm::IntegerType *GuardTy = CGF.Int32Ty;

2631 llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);

2633

2634

2635 GuardInfo *GI = nullptr;

2636 if (ThreadlocalStatic)

2638 else if (!ThreadsafeStatic)

2640

2641 llvm::GlobalVariable *GuardVar = GI ? GI->Guard : nullptr;

2642 unsigned GuardNum;

2643 if (D.isExternallyVisible()) {

2644

2645

2646 GuardNum = getContext().getStaticLocalNumber(&D);

2647 assert(GuardNum > 0);

2648 GuardNum--;

2649 } else if (HasPerVariableGuard) {

2651 } else {

2652

2653 GuardNum = GI->BitIndex++;

2654 }

2655

2656 if (!HasPerVariableGuard && GuardNum >= 32) {

2657 if (D.isExternallyVisible())

2658 ErrorUnsupportedABI(CGF, "more than 32 guarded initializations");

2659 GuardNum %= 32;

2660 GuardVar = nullptr;

2661 }

2662

2663 if (!GuardVar) {

2664

2666 {

2667 llvm::raw_svector_ostream Out(GuardName);

2668 if (HasPerVariableGuard)

2669 getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum,

2670 Out);

2671 else

2672 getMangleContext().mangleStaticGuardVariable(&D, Out);

2673 }

2674

2675

2676

2677 GuardVar =

2678 new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,

2679 GV->getLinkage(), Zero, GuardName.str());

2680 GuardVar->setVisibility(GV->getVisibility());

2681 GuardVar->setDLLStorageClass(GV->getDLLStorageClass());

2682 GuardVar->setAlignment(GuardAlign.getAsAlign());

2683 if (GuardVar->isWeakForLinker())

2684 GuardVar->setComdat(

2685 CGM.getModule().getOrInsertComdat(GuardVar->getName()));

2686 if (D.getTLSKind())

2688 if (GI && !HasPerVariableGuard)

2689 GI->Guard = GuardVar;

2690 }

2691

2692 ConstantAddress GuardAddr(GuardVar, GuardTy, GuardAlign);

2693

2694 assert(GuardVar->getLinkage() == GV->getLinkage() &&

2695 "static local from the same function had different linkage");

2696

2697 if (!HasPerVariableGuard) {

2698

2699

2700

2701

2702

2703

2704

2705 llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);

2706 llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);

2707 llvm::Value *NeedsInit =

2708 Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit), Zero);

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

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

2713

2714

2715

2717 Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr);

2718 CGF.EHStack.pushCleanup(EHCleanup, GuardAddr, GuardNum);

2721 Builder.CreateBr(EndBlock);

2722

2723

2725 } else {

2726

2727

2728

2729

2730

2731

2732

2733

2734

2735

2736

2737

2738

2739 llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr);

2740 FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);

2741 llvm::LoadInst *InitThreadEpoch =

2743 llvm::Value *IsUninitialized =

2744 Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);

2745 llvm::BasicBlock *AttemptInitBlock = CGF.createBasicBlock("init.attempt");

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

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

2749

2750

2751

2752 CGF.EmitBlock(AttemptInitBlock);

2754 GuardAddr.getPointer());

2755 llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr);

2756 SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);

2757 llvm::Value *ShouldDoInit =

2758 Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());

2760 Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock);

2761

2762

2764 CGF.EHStack.pushCleanup(EHCleanup, GuardAddr);

2768 GuardAddr.getPointer());

2769 Builder.CreateBr(EndBlock);

2770

2772 }

2773}

2774

2775bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {

2776

2777

2779 return true;

2780

2781

2782

2783

2788}

2789

2790llvm::Type *

2791MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {

2796 fields.push_back(CGM.VoidPtrTy);

2797 else

2798 fields.push_back(CGM.IntTy);

2799

2801 Inheritance))

2802 fields.push_back(CGM.IntTy);

2804 fields.push_back(CGM.IntTy);

2806 fields.push_back(CGM.IntTy);

2807

2808 if (fields.size() == 1)

2809 return fields[0];

2810 return llvm::StructType::get(CGM.getLLVMContext(), fields);

2811}

2812

2813void MicrosoftCXXABI::

2816 assert(fields.empty());

2820

2821 fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));

2822 } else {

2824 fields.push_back(getZeroInt());

2825 else

2826 fields.push_back(getAllOnesInt());

2827 }

2828

2830 Inheritance))

2831 fields.push_back(getZeroInt());

2833 fields.push_back(getZeroInt());

2835 fields.push_back(getAllOnesInt());

2836}

2837

2838llvm::Constant *

2839MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {

2841 GetNullMemberPointerFields(MPT, fields);

2842 if (fields.size() == 1)

2843 return fields[0];

2844 llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields);

2845 assert(Res->getType() == ConvertMemberPointerType(MPT));

2846 return Res;

2847}

2848

2849llvm::Constant *

2850MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,

2851 bool IsMemberFunction,

2853 CharUnits NonVirtualBaseAdjustment,

2854 unsigned VBTableIndex) {

2856

2857

2858

2860 return FirstField;

2861

2863 fields.push_back(FirstField);

2864

2866 fields.push_back(llvm::ConstantInt::get(

2868

2871 if (VBTableIndex)

2872 Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();

2873 fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity()));

2874 }

2875

2876

2878 fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBTableIndex));

2879

2880 return llvm::ConstantStruct::getAnon(fields);

2881}

2882

2883llvm::Constant *

2884MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,

2887}

2888

2889llvm::Constant *MicrosoftCXXABI::EmitMemberDataPointer(const CXXRecordDecl *RD,

2892 MSInheritanceModel::Virtual)

2893 offset -= getContext().getOffsetOfBaseWithVBPtr(RD);

2894 llvm::Constant *FirstField =

2896 return EmitFullMemberPointer(FirstField, false, RD,

2898}

2899

2900llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,

2904 if (!MPD)

2905 return EmitNullMemberPointer(DstTy);

2906

2909

2910 llvm::Constant *C;

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

2912 C = EmitMemberFunctionPointer(MD);

2913 } else {

2914

2915

2916

2917

2919 const FieldDecl *FD = dyn_cast(MPD);

2920 if (!FD)

2921 FD = cast(*cast(MPD)->chain_begin());

2924 C = EmitMemberDataPointer(RD, FieldOffset);

2925 }

2926

2927 if (!MemberPointerPath.empty()) {

2928 const CXXRecordDecl *SrcRD = cast(MPD->getDeclContext());

2933

2937 for (const CXXRecordDecl *PathElem : MemberPointerPath) {

2940 if (DerivedMember) {

2941 Base = PathElem;

2942 Derived = PrevRD;

2943 } else {

2944 Base = PrevRD;

2945 Derived = PathElem;

2946 }

2948 if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() ==

2949 Base->getCanonicalDecl())

2950 DerivedToBasePath.push_back(&BS);

2951 PrevRD = PathElem;

2952 }

2953 assert(DerivedToBasePath.size() == MemberPointerPath.size());

2954

2955 CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer

2956 : CK_BaseToDerivedMemberPointer;

2957 C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(),

2958 DerivedToBasePath.end(), C);

2959 }

2960 return C;

2961}

2962

2963llvm::Constant *

2964MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {

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

2966

2970

2971 unsigned VBTableIndex = 0;

2972 llvm::Constant *FirstField;

2975 llvm::Type *Ty;

2976

2977 if (Types.isFuncTypeConvertible(FPT)) {

2978

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

2980 } else {

2981

2982

2984 }

2986 } else {

2989 FirstField = EmitVirtualMemPtrThunk(MD, ML);

2990

2991 NonVirtualBaseAdjustment += ML.VFPtrOffset;

2993 VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4;

2994 }

2995

2996 if (VBTableIndex == 0 &&

2998 MSInheritanceModel::Virtual)

2999 NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);

3000

3001

3002 return EmitFullMemberPointer(FirstField, true, RD,

3003 NonVirtualBaseAdjustment, VBTableIndex);

3004}

3005

3006

3007

3008

3009llvm::Value *

3010MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,

3011 llvm::Value *L,

3012 llvm::Value *R,

3014 bool Inequality) {

3016

3017

3018 llvm::ICmpInst::Predicate Eq;

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

3020 if (Inequality) {

3021 Eq = llvm::ICmpInst::ICMP_NE;

3022 And = llvm::Instruction::Or;

3023 Or = llvm::Instruction::And;

3024 } else {

3025 Eq = llvm::ICmpInst::ICMP_EQ;

3026 And = llvm::Instruction::And;

3027 Or = llvm::Instruction::Or;

3028 }

3029

3030

3031

3035 Inheritance))

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

3037

3038

3039 llvm::Value *L0 = Builder.CreateExtractValue(L, 0, "lhs.0");

3040 llvm::Value *R0 = Builder.CreateExtractValue(R, 0, "rhs.0");

3041 llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0, "memptr.cmp.first");

3042

3043

3044 llvm::Value *Res = nullptr;

3045 llvm::StructType *LType = castllvm::StructType(L->getType());

3046 for (unsigned I = 1, E = LType->getNumElements(); I != E; ++I) {

3047 llvm::Value *LF = Builder.CreateExtractValue(L, I);

3048 llvm::Value *RF = Builder.CreateExtractValue(R, I);

3049 llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF, "memptr.cmp.rest");

3050 if (Res)

3051 Res = Builder.CreateBinOp(And, Res, Cmp);

3052 else

3053 Res = Cmp;

3054 }

3055

3056

3058

3059 llvm::Value *Zero = llvm::Constant::getNullValue(L0->getType());

3060 llvm::Value *IsZero = Builder.CreateICmp(Eq, L0, Zero, "memptr.cmp.iszero");

3061 Res = Builder.CreateBinOp(Or, Res, IsZero);

3062 }

3063

3064

3065

3066 return Builder.CreateBinOp(And, Res, Cmp0, "memptr.cmp");

3067}

3068

3069llvm::Value *

3070MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,

3071 llvm::Value *MemPtr,

3075

3077 fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));

3078 else

3079 GetNullMemberPointerFields(MPT, fields);

3080 assert(!fields.empty());

3081 llvm::Value *FirstField = MemPtr;

3082 if (MemPtr->getType()->isStructTy())

3083 FirstField = Builder.CreateExtractValue(MemPtr, 0);

3084 llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0], "memptr.cmp0");

3085

3086

3087

3089 return Res;

3090

3091

3092 for (int I = 1, E = fields.size(); I < E; ++I) {

3093 llvm::Value *Field = Builder.CreateExtractValue(MemPtr, I);

3094 llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I], "memptr.cmp");

3095 Res = Builder.CreateOr(Res, Next, "memptr.tobool");

3096 }

3097 return Res;

3098}

3099

3100bool MicrosoftCXXABI::MemberPointerConstantIsNull(const MemberPointerType *MPT,

3101 llvm::Constant *Val) {

3102

3104 llvm::Constant *FirstField = Val->getType()->isStructTy() ?

3105 Val->getAggregateElement(0U) : Val;

3106 return FirstField->isNullValue();

3107 }

3108

3109

3110

3111 if (isZeroInitializable(MPT) && Val->isNullValue())

3112 return true;

3113

3114

3115

3117 GetNullMemberPointerFields(MPT, Fields);

3118 if (Fields.size() == 1) {

3119 assert(Val->getType()->isIntegerTy());

3120 return Val == Fields[0];

3121 }

3122

3123 unsigned I, E;

3124 for (I = 0, E = Fields.size(); I != E; ++I) {

3125 if (Val->getAggregateElement(I) != Fields[I])

3126 break;

3127 }

3128 return I == E;

3129}

3130

3131llvm::Value *

3132MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,

3134 llvm::Value *VBPtrOffset,

3135 llvm::Value *VBTableOffset,

3136 llvm::Value **VBPtrOut) {

3138

3139 llvm::Value *VBPtr = Builder.CreateInBoundsGEP(

3140 CGM.Int8Ty, This.emitRawPointer(CGF), VBPtrOffset, "vbptr");

3141 if (VBPtrOut)

3142 *VBPtrOut = VBPtr;

3143

3145 if (auto CI = dyn_castllvm::ConstantInt(VBPtrOffset)) {

3146 VBPtrAlign = This.getAlignment().alignmentAtOffset(

3148 } else {

3150 }

3151

3152 llvm::Value *VBTable =

3153 Builder.CreateAlignedLoad(CGM.UnqualPtrTy, VBPtr, VBPtrAlign, "vbtable");

3154

3155

3156 llvm::Value *VBTableIndex = Builder.CreateAShr(

3157 VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2),

3158 "vbtindex", true);

3159

3160

3161 llvm::Value *VBaseOffs =

3162 Builder.CreateInBoundsGEP(CGM.Int32Ty, VBTable, VBTableIndex);

3163 return Builder.CreateAlignedLoad(CGM.Int32Ty, VBaseOffs,

3165}

3166

3167

3168

3169llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(

3171 Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {

3174 llvm::BasicBlock *OriginalBB = nullptr;

3175 llvm::BasicBlock *SkipAdjustBB = nullptr;

3176 llvm::BasicBlock *VBaseAdjustBB = nullptr;

3177

3178

3179

3180

3181

3182 if (VBPtrOffset) {

3183 OriginalBB = Builder.GetInsertBlock();

3186 llvm::Value *IsVirtual =

3187 Builder.CreateICmpNE(VBTableOffset, getZeroInt(),

3188 "memptr.is_vbase");

3189 Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);

3191 }

3192

3193

3194

3195 if (!VBPtrOffset) {

3201 "member pointer representation requires a "

3202 "complete class type for %0 to perform this expression");

3205 offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();

3206 VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity());

3207 }

3208 llvm::Value *VBPtr = nullptr;

3209 llvm::Value *VBaseOffs =

3210 GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);

3211 llvm::Value *AdjustedBase =

3212 Builder.CreateInBoundsGEP(CGM.Int8Ty, VBPtr, VBaseOffs);

3213

3214

3215 if (VBaseAdjustBB) {

3216 Builder.CreateBr(SkipAdjustBB);

3218 llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base");

3219 Phi->addIncoming(Base.emitRawPointer(CGF), OriginalBB);

3220 Phi->addIncoming(AdjustedBase, VBaseAdjustBB);

3221 return Phi;

3222 }

3223 return AdjustedBase;

3224}

3225

3226llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(

3233

3234

3235

3236 llvm::Value *FieldOffset = MemPtr;

3237 llvm::Value *VirtualBaseAdjustmentOffset = nullptr;

3238 llvm::Value *VBPtrOffset = nullptr;

3239 if (MemPtr->getType()->isStructTy()) {

3240

3241 unsigned I = 0;

3242 FieldOffset = Builder.CreateExtractValue(MemPtr, I++);

3244 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);

3246 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);

3247 }

3248

3249 llvm::Value *Addr;

3250 if (VirtualBaseAdjustmentOffset) {

3251 Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,

3252 VBPtrOffset);

3253 } else {

3254 Addr = Base.emitRawPointer(CGF);

3255 }

3256

3257

3258 return Builder.CreateInBoundsGEP(CGF.Int8Ty, Addr, FieldOffset,

3259 "memptr.offset");

3260}

3261

3262llvm::Value *

3263MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,

3265 llvm::Value *Src) {

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

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

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

3269

3270

3271 if (isallvm::Constant(Src))

3272 return EmitMemberPointerConversion(E, castllvm::Constant(Src));

3273

3274

3275

3280

3281

3282 bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer;

3283 if (IsReinterpret && IsFunc)

3284 return Src;

3285

3287 CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();

3288 if (IsReinterpret &&

3290 return Src;

3291

3293

3294

3295 llvm::Value *IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);

3296 llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);

3297

3298

3299

3300 if (IsReinterpret) {

3301

3302

3303 assert(Src->getType() == DstNull->getType());

3304 return Builder.CreateSelect(IsNotNull, Src, DstNull);

3305 }

3306

3307 llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();

3308 llvm::BasicBlock *ConvertBB = CGF.createBasicBlock("memptr.convert");

3309 llvm::BasicBlock *ContinueBB = CGF.createBasicBlock("memptr.converted");

3310 Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB);

3312

3313 llvm::Value *Dst = EmitNonNullMemberPointerConversion(

3314 SrcTy, DstTy, E->getCastKind(), E->path_begin(), E->path_end(), Src,

3315 Builder);

3316

3317 Builder.CreateBr(ContinueBB);

3318

3319

3321 llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted");

3322 Phi->addIncoming(DstNull, OriginalBB);

3323 Phi->addIncoming(Dst, ConvertBB);

3324 return Phi;

3325}

3326

3327llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(

3337 bool IsConstant = isallvm::Constant(Src);

3338

3339

3340 llvm::Value *FirstField = Src;

3341 llvm::Value *NonVirtualBaseAdjustment = getZeroInt();

3342 llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt();

3343 llvm::Value *VBPtrOffset = getZeroInt();

3345

3346 unsigned I = 0;

3347 FirstField = Builder.CreateExtractValue(Src, I++);

3349 NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);

3351 VBPtrOffset = Builder.CreateExtractValue(Src, I++);

3353 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);

3354 }

3355

3356 bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer);

3357 const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy;

3359

3360

3361

3362 llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;

3363

3364

3365

3366

3367

3368

3369 llvm::Value *SrcVBIndexEqZero =

3370 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());

3371 if (SrcInheritance == MSInheritanceModel::Virtual) {

3372 if (int64_t SrcOffsetToFirstVBase =

3373 getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {

3374 llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(

3375 SrcVBIndexEqZero,

3376 llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase),

3377 getZeroInt());

3378 NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment);

3379 }

3380 }

3381

3382

3383

3384

3385

3386

3387

3388

3389 llvm::Constant *BaseClassOffset = llvm::ConstantInt::get(

3393

3394 llvm::Value *NVDisp;

3395 if (IsDerivedToBase)

3396 NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset, "adj");

3397 else

3398 NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset, "adj");

3399

3400 NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt());

3401

3402

3403

3404 llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero;

3407 if (llvm::GlobalVariable *VDispMap =

3408 getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) {

3409 llvm::Value *VBIndex = Builder.CreateExactUDiv(

3410 VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.IntTy, 4));

3411 if (IsConstant) {

3412 llvm::Constant *Mapping = VDispMap->getInitializer();

3413 VirtualBaseAdjustmentOffset =

3414 Mapping->getAggregateElement(castllvm::Constant(VBIndex));

3415 } else {

3416 llvm::Value *Idxs[] = {getZeroInt(), VBIndex};

3417 VirtualBaseAdjustmentOffset = Builder.CreateAlignedLoad(

3418 CGM.IntTy, Builder.CreateInBoundsGEP(VDispMap->getValueType(),

3419 VDispMap, Idxs),

3421 }

3422

3423 DstVBIndexEqZero =

3424 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());

3425 }

3426 }

3427

3428

3429

3431 llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get(

3433 getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity());

3434 VBPtrOffset =

3435 Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset);

3436 }

3437

3438

3439

3440

3441 if (DstInheritance == MSInheritanceModel::Virtual) {

3442 if (int64_t DstOffsetToFirstVBase =

3443 getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {

3444 llvm::Value *DoDstAdjustment = Builder.CreateSelect(

3445 DstVBIndexEqZero,

3446 llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase),

3447 getZeroInt());

3448 NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment);

3449 }

3450 }

3451

3452

3453 llvm::Value *Dst;

3455 Dst = FirstField;

3456 } else {

3457 Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy));

3458 unsigned Idx = 0;

3459 Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);

3461 Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++);

3463 Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++);

3465 Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++);

3466 }

3467 return Dst;

3468}

3469

3470llvm::Constant *

3471MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,

3472 llvm::Constant *Src) {

3476

3478

3479 return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->path_begin(),

3480 E->path_end(), Src);

3481}

3482

3483llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(

3487 assert(CK == CK_DerivedToBaseMemberPointer ||

3488 CK == CK_BaseToDerivedMemberPointer ||

3489 CK == CK_ReinterpretMemberPointer);

3490

3491

3492 if (MemberPointerConstantIsNull(SrcTy, Src))

3493 return EmitNullMemberPointer(DstTy);

3494

3495

3496

3497

3498 if (CK == CK_ReinterpretMemberPointer)

3499 return Src;

3500

3502 auto *Dst = castllvm::Constant(EmitNonNullMemberPointerConversion(

3503 SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));

3504

3505 return Dst;

3506}

3507

3508CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(

3510 llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,

3517

3519

3520

3521

3522 llvm::Value *FunctionPointer = MemPtr;

3523 llvm::Value *NonVirtualBaseAdjustment = nullptr;

3524 llvm::Value *VirtualBaseAdjustmentOffset = nullptr;

3525 llvm::Value *VBPtrOffset = nullptr;

3526 if (MemPtr->getType()->isStructTy()) {

3527

3528 unsigned I = 0;

3529 FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);

3531 NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);

3533 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);

3535 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);

3536 }

3537

3538 if (VirtualBaseAdjustmentOffset) {

3539 ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This,

3540 VirtualBaseAdjustmentOffset, VBPtrOffset);

3541 } else {

3542 ThisPtrForCall = This.emitRawPointer(CGF);

3543 }

3544

3545 if (NonVirtualBaseAdjustment)

3546 ThisPtrForCall = Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisPtrForCall,

3547 NonVirtualBaseAdjustment);

3548

3551}

3552

3554 return new MicrosoftCXXABI(CGM);

3555}

3556

3557

3558

3559

3560

3561

3562

3563

3564

3565

3566

3567

3568

3569

3570

3571

3572

3573

3574

3575

3576

3577

3578

3579

3580

3581

3582

3583

3584

3585

3586

3588 StringRef MangledName("??_7type_info@@6B@");

3589 if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))

3590 return VTable;

3592 true,

3593 llvm::GlobalVariable::ExternalLinkage,

3594 nullptr, MangledName);

3595}

3596

3597namespace {

3598

3599

3600

3601

3602

3603

3604

3605struct MSRTTIClass {

3606 enum {

3607 IsPrivateOnPath = 1 | 8,

3608 IsAmbiguous = 2,

3609 IsPrivate = 4,

3610 IsVirtual = 16,

3611 HasHierarchyDescriptor = 64

3612 };

3613 MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {}

3616

3617 MSRTTIClass *getFirstChild() { return this + 1; }

3618 static MSRTTIClass *getNextChild(MSRTTIClass *Child) {

3619 return Child + 1 + Child->NumBases;

3620 }

3621

3623 uint32_t Flags, NumBases, OffsetInVBase;

3624};

3625

3626

3627uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,

3629 Flags = HasHierarchyDescriptor;

3631 VirtualRoot = nullptr;

3632 OffsetInVBase = 0;

3633 } else {

3635 Flags |= IsPrivate | IsPrivateOnPath;

3637 Flags |= IsVirtual;

3638 VirtualRoot = RD;

3639 OffsetInVBase = 0;

3640 } else {

3641 if (Parent->Flags & IsPrivateOnPath)

3642 Flags |= IsPrivateOnPath;

3643 VirtualRoot = Parent->VirtualRoot;

3644 OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()

3645 .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();

3646 }

3647 }

3648 NumBases = 0;

3649 MSRTTIClass *Child = getFirstChild();

3651 NumBases += Child->initialize(this, &Base) + 1;

3652 Child = getNextChild(Child);

3653 }

3654 return NumBases;

3655}

3656

3657static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {

3659 case Linkage::Invalid:

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

3661

3662 case Linkage::None:

3663 case Linkage::Internal:

3664 case Linkage::UniqueExternal:

3665 return llvm::GlobalValue::InternalLinkage;

3666

3667 case Linkage::VisibleNone:

3668 case Linkage::Module:

3669 case Linkage::External:

3670 return llvm::GlobalValue::LinkOnceODRLinkage;

3671 }

3672 llvm_unreachable("Invalid linkage!");

3673}

3674

3675

3676

3677

3678struct MSRTTIBuilder {

3679 enum {

3680 HasBranchingHierarchy = 1,

3681 HasVirtualBranchingHierarchy = 2,

3682 HasAmbiguousBases = 4

3683 };

3684

3685 MSRTTIBuilder(MicrosoftCXXABI &ABI, const CXXRecordDecl *RD)

3686 : CGM(ABI.CGM), Context(CGM.getContext()),

3687 VMContext(CGM.getLLVMContext()), Module(CGM.getModule()), RD(RD),

3688 Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))),

3689 ABI(ABI) {}

3690

3691 llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes);

3692 llvm::GlobalVariable *

3694 llvm::GlobalVariable *getClassHierarchyDescriptor();

3695 llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo &Info);

3696

3699 llvm::LLVMContext &VMContext;

3700 llvm::Module &Module;

3702 llvm::GlobalVariable::LinkageTypes Linkage;

3703 MicrosoftCXXABI &ABI;

3704};

3705

3706}

3707

3708

3709

3712 Classes.push_back(MSRTTIClass(RD));

3715}

3716

3717

3718static void

3723 for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {

3724 if ((Class->Flags & MSRTTIClass::IsVirtual) &&

3725 !VirtualBases.insert(Class->RD).second) {

3726 Class = MSRTTIClass::getNextChild(Class);

3727 continue;

3728 }

3729 if (!UniqueBases.insert(Class->RD).second)

3730 AmbiguousBases.insert(Class->RD);

3732 }

3733 if (AmbiguousBases.empty())

3734 return;

3735 for (MSRTTIClass &Class : Classes)

3736 if (AmbiguousBases.count(Class.RD))

3737 Class.Flags |= MSRTTIClass::IsAmbiguous;

3738}

3739

3740llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {

3742 {

3743 llvm::raw_svector_ostream Out(MangledName);

3744 ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out);

3745 }

3746

3747

3748 if (auto CHD = Module.getNamedGlobal(MangledName))

3749 return CHD;

3750

3751

3754 Classes.front().initialize(nullptr, nullptr);

3756 int Flags = 0;

3757 for (const MSRTTIClass &Class : Classes) {

3758 if (Class.RD->getNumBases() > 1)

3759 Flags |= HasBranchingHierarchy;

3760

3761

3762 if (Class.Flags & MSRTTIClass::IsAmbiguous)

3763 Flags |= HasAmbiguousBases;

3764 }

3765 if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)

3766 Flags |= HasVirtualBranchingHierarchy;

3767

3768

3769 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),

3770 llvm::ConstantInt::get(CGM.IntTy, 0)};

3771

3772

3773 auto Type = ABI.getClassHierarchyDescriptorType();

3774 auto CHD = new llvm::GlobalVariable(Module, Type, true, Linkage,

3775 nullptr,

3776 MangledName);

3777 if (CHD->isWeakForLinker())

3778 CHD->setComdat(CGM.getModule().getOrInsertComdat(CHD->getName()));

3779

3780 auto *Bases = getBaseClassArray(Classes);

3781

3782

3783 llvm::Constant *Fields[] = {

3784 llvm::ConstantInt::get(CGM.IntTy, 0),

3785 llvm::ConstantInt::get(CGM.IntTy, Flags),

3786 llvm::ConstantInt::get(CGM.IntTy, Classes.size()),

3787 ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(

3788 Bases->getValueType(), Bases,

3790 };

3791 CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));

3792 return CHD;

3793}

3794

3795llvm::GlobalVariable *

3798 {

3799 llvm::raw_svector_ostream Out(MangledName);

3800 ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out);

3801 }

3802

3803

3804

3805

3806

3807

3808 llvm::Type *PtrType = ABI.getImageRelativeType(CGM.UnqualPtrTy);

3809 auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);

3810 auto *BCA =

3811 new llvm::GlobalVariable(Module, ArrType,

3812 true, Linkage,

3813 nullptr, MangledName);

3814 if (BCA->isWeakForLinker())

3815 BCA->setComdat(CGM.getModule().getOrInsertComdat(BCA->getName()));

3816

3817

3819 for (MSRTTIClass &Class : Classes)

3820 BaseClassArrayData.push_back(

3821 ABI.getImageRelativeConstant(getBaseClassDescriptor(Class)));

3822 BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));

3823 BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData));

3824 return BCA;

3825}

3826

3827llvm::GlobalVariable *

3828MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {

3829

3830

3831 uint32_t OffsetInVBTable = 0;

3832 int32_t VBPtrOffset = -1;

3833 if (Class.VirtualRoot) {

3837 }

3838

3840 {

3841 llvm::raw_svector_ostream Out(MangledName);

3842 ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor(

3843 Class.RD, Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable,

3844 Class.Flags, Out);

3845 }

3846

3847

3848 if (auto BCD = Module.getNamedGlobal(MangledName))

3849 return BCD;

3850

3851

3852 auto Type = ABI.getBaseClassDescriptorType();

3853 auto BCD =

3854 new llvm::GlobalVariable(Module, Type, true, Linkage,

3855 nullptr, MangledName);

3856 if (BCD->isWeakForLinker())

3857 BCD->setComdat(CGM.getModule().getOrInsertComdat(BCD->getName()));

3858

3859

3860 llvm::Constant *Fields[] = {

3861 ABI.getImageRelativeConstant(

3863 llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),

3864 llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),

3865 llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),

3866 llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable),

3867 llvm::ConstantInt::get(CGM.IntTy, Class.Flags),

3868 ABI.getImageRelativeConstant(

3869 MSRTTIBuilder(ABI, Class.RD).getClassHierarchyDescriptor()),

3870 };

3871 BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));

3872 return BCD;

3873}

3874

3875llvm::GlobalVariable *

3876MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo &Info) {

3878 {

3879 llvm::raw_svector_ostream Out(MangledName);

3880 ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.MangledPath, Out);

3881 }

3882

3883

3884 if (auto COL = Module.getNamedGlobal(MangledName))

3885 return COL;

3886

3887

3889 int VFPtrOffset = 0;

3890

3894 .find(VBase)

3895 ->second.hasVtorDisp())

3897

3898

3899 llvm::StructType *Type = ABI.getCompleteObjectLocatorType();

3900 auto COL = new llvm::GlobalVariable(Module, Type, true, Linkage,

3901 nullptr, MangledName);

3902

3903

3904 llvm::Constant *Fields[] = {

3905 llvm::ConstantInt::get(CGM.IntTy, ABI.isImageRelative()),

3906 llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),

3907 llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),

3908 ABI.getImageRelativeConstant(

3910 ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),

3911 ABI.getImageRelativeConstant(COL),

3912 };

3914 if (!ABI.isImageRelative())

3915 FieldsRef = FieldsRef.drop_back();

3916 COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef));

3917 if (COL->isWeakForLinker())

3918 COL->setComdat(CGM.getModule().getOrInsertComdat(COL->getName()));

3919 return COL;

3920}

3921

3923 bool &IsConst, bool &IsVolatile,

3924 bool &IsUnaligned) {

3926

3927

3928

3929

3930

3931

3932 IsConst = false;

3933 IsVolatile = false;

3934 IsUnaligned = false;

3936 if (!PointeeType.isNull()) {

3940 }

3941

3942

3943

3946 MPTy->getClass());

3947

3948

3949

3952

3953 return T;

3954}

3955

3957MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type,

3958 QualType CatchHandlerType) {

3959

3960

3961

3962 bool IsConst, IsVolatile, IsUnaligned;

3965

3967

3969 if (IsConst)

3970 Flags |= 1;

3971 if (IsVolatile)

3972 Flags |= 2;

3973 if (IsUnaligned)

3974 Flags |= 4;

3975 if (IsReference)

3976 Flags |= 8;

3977

3978 return CatchTypeInfo{getAddrOfRTTIDescriptor(Type)->stripPointerCasts(),

3979 Flags};

3980}

3981

3982

3983

3984

3985

3986llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {

3988 {

3989 llvm::raw_svector_ostream Out(MangledName);

3990 getMangleContext().mangleCXXRTTI(Type, Out);

3991 }

3992

3993

3994 if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))

3995 return GV;

3996

3997

3998

3999

4000

4002 {

4003 llvm::raw_svector_ostream Out(TypeInfoString);

4004 getMangleContext().mangleCXXRTTIName(Type, Out);

4005 }

4006

4007

4008 llvm::Constant *Fields[] = {

4010 llvm::ConstantPointerNull::get(CGM.Int8PtrTy),

4011 llvm::ConstantDataArray::getString(CGM.getLLVMContext(), TypeInfoString)};

4012 llvm::StructType *TypeDescriptorType =

4013 getTypeDescriptorType(TypeInfoString);

4014 auto *Var = new llvm::GlobalVariable(

4015 CGM.getModule(), TypeDescriptorType, false,

4016 getLinkageForRTTI(Type),

4017 llvm::ConstantStruct::get(TypeDescriptorType, Fields),

4018 MangledName);

4019 if (Var->isWeakForLinker())

4020 Var->setComdat(CGM.getModule().getOrInsertComdat(Var->getName()));

4021 return Var;

4022}

4023

4024

4025llvm::GlobalVariable *

4026MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD,

4028 return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);

4029}

4030

4031void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) {

4032 if (auto *ctor = dyn_cast(GD.getDecl())) {

4033

4034 llvm::Function *Fn =

4037 return;

4038 }

4039

4040 auto *dtor = cast(GD.getDecl());

4041

4042

4043

4044

4046 dtor->getParent()->getNumVBases() == 0)

4048

4049

4050

4051

4052

4054 return;

4055

4057 if (Fn->isWeakForLinker())

4058 Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName()));

4059}

4060

4061llvm::Function *

4062MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,

4065

4066

4068 llvm::raw_svector_ostream Out(ThunkName);

4069 getMangleContext().mangleName(GlobalDecl(CD, CT), Out);

4070

4071

4072 if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))

4073 return castllvm::Function(GV);

4074

4075

4079 QualType RecordTy = getContext().getRecordType(RD);

4080 llvm::Function *ThunkFn = llvm::Function::Create(

4081 ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule());

4082 ThunkFn->setCallingConv(static_castllvm::CallingConv::ID\(

4084 if (ThunkFn->isWeakForLinker())

4085 ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));

4087

4088

4091

4092

4094

4095

4096 buildThisParam(CGF, FunctionArgs);

4097

4098

4099

4102 &getContext().Idents.get("src"),

4103 getContext().getLValueReferenceType(RecordTy,

4104 true),

4105 ImplicitParamKind::Other);

4106 if (IsCopy)

4107 FunctionArgs.push_back(&SrcParam);

4108

4109

4110

4111

4114 &getContext().Idents.get("is_most_derived"),

4115 getContext().IntTy, ImplicitParamKind::Other);

4116

4118 FunctionArgs.push_back(&IsMostDerived);

4119

4120

4124

4126 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));

4127 llvm::Value *This = getThisValue(CGF);

4128

4129 llvm::Value *SrcVal =

4131 : nullptr;

4132

4134

4135

4137

4138

4139 if (SrcVal)

4141

4142

4146 assert(PD->hasDefaultArg() && "ctor closure lacks default args");

4147 ArgVec.push_back(PD->getDefaultArg());

4148 }

4149

4150 CodeGenFunction::RunCleanupsScope Cleanups(CGF);

4151

4154

4155

4156 AddedStructorArgCounts ExtraArgs =

4157 addImplicitConstructorArgs(CGF, CD, Ctor_Complete,

4158 false,

4159 false, Args);

4160

4161 llvm::Constant *CalleePtr =

4166 Args, CD, Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix);

4168

4169 Cleanups.ForceCleanup();

4170

4171

4172

4174

4175 return ThunkFn;

4176}

4177

4178llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,

4179 uint32_t NVOffset,

4180 int32_t VBPtrOffset,

4181 uint32_t VBIndex) {

4183

4188 if (CD)

4191

4192 uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity();

4194 {

4195 llvm::raw_svector_ostream Out(MangledName);

4196 getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset,

4197 VBPtrOffset, VBIndex, Out);

4198 }

4199 if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))

4200 return getImageRelativeConstant(GV);

4201

4202

4203

4204 llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T));

4205

4206

4207

4208 llvm::Constant *CopyCtor;

4209 if (CD) {

4212 else

4214 } else {

4215 CopyCtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);

4216 }

4217 CopyCtor = getImageRelativeConstant(CopyCtor);

4218

4219 bool IsScalar = !RD;

4220 bool HasVirtualBases = false;

4221 bool IsStdBadAlloc = false;

4228 IsStdBadAlloc = II->isStr("bad_alloc") && RD->isInStdNamespace();

4229 }

4230

4231

4232

4234 if (IsScalar)

4235 Flags |= 1;

4236 if (HasVirtualBases)

4237 Flags |= 4;

4238 if (IsStdBadAlloc)

4239 Flags |= 16;

4240

4241 llvm::Constant *Fields[] = {

4242 llvm::ConstantInt::get(CGM.IntTy, Flags),

4243 TD,

4244 llvm::ConstantInt::get(CGM.IntTy, NVOffset),

4245 llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),

4246 llvm::ConstantInt::get(CGM.IntTy, VBIndex),

4247 llvm::ConstantInt::get(CGM.IntTy, Size),

4248 CopyCtor

4249 };

4250 llvm::StructType *CTType = getCatchableTypeType();

4251 auto *GV = new llvm::GlobalVariable(

4252 CGM.getModule(), CTType, true, getLinkageForRTTI(T),

4253 llvm::ConstantStruct::get(CTType, Fields), MangledName);

4254 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

4255 GV->setSection(".xdata");

4256 if (GV->isWeakForLinker())

4257 GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName()));

4258 return getImageRelativeConstant(GV);

4259}

4260

4261llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) {

4263

4264

4265 llvm::GlobalVariable *&CTA = CatchableTypeArrays[T];

4266 if (CTA)

4267 return CTA;

4268

4269

4270

4271

4273

4274

4275

4276

4277

4278

4279

4280

4281

4282 const CXXRecordDecl *MostDerivedClass = nullptr;

4284 if (IsPointer)

4286 else

4288

4289

4290 if (MostDerivedClass) {

4291 const ASTContext &Context = getContext();

4297 Classes.front().initialize(nullptr, nullptr);

4299 for (const MSRTTIClass &Class : Classes) {

4300

4301 if (Class.Flags &

4302 (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous))

4303 continue;

4304

4305 uint32_t OffsetInVBTable = 0;

4306 int32_t VBPtrOffset = -1;

4307 if (Class.VirtualRoot) {

4308 OffsetInVBTable =

4311 }

4312

4313

4314

4316 if (IsPointer)

4318 CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase,

4319 VBPtrOffset, OffsetInVBTable));

4320 }

4321 }

4322

4323

4324

4325

4326

4327 CatchableTypes.insert(getCatchableType(T));

4328

4329

4330

4331

4332

4333

4334

4335

4336

4337

4338

4340 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));

4341

4342

4343

4344

4345

4346

4347

4348

4349

4351 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));

4352

4353 uint32_t NumEntries = CatchableTypes.size();

4354 llvm::Type *CTType = getImageRelativeType(CGM.UnqualPtrTy);

4355 llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);

4356 llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);

4357 llvm::Constant *Fields[] = {

4358 llvm::ConstantInt::get(CGM.IntTy, NumEntries),

4359 llvm::ConstantArray::get(

4361 CatchableTypes.end()))

4362 };

4364 {

4365 llvm::raw_svector_ostream Out(MangledName);

4366 getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out);

4367 }

4368 CTA = new llvm::GlobalVariable(

4369 CGM.getModule(), CTAType, true, getLinkageForRTTI(T),

4370 llvm::ConstantStruct::get(CTAType, Fields), MangledName);

4371 CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

4372 CTA->setSection(".xdata");

4373 if (CTA->isWeakForLinker())

4374 CTA->setComdat(CGM.getModule().getOrInsertComdat(CTA->getName()));

4375 return CTA;

4376}

4377

4378llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType T) {

4379 bool IsConst, IsVolatile, IsUnaligned;

4381

4382

4383

4384 llvm::GlobalVariable *CTA = getCatchableTypeArray(T);

4385

4386

4387

4388

4390 castllvm::ConstantInt(CTA->getInitializer()->getAggregateElement(0U))

4391 ->getLimitedValue();

4392

4394 {

4395 llvm::raw_svector_ostream Out(MangledName);

4396 getMangleContext().mangleCXXThrowInfo(T, IsConst, IsVolatile, IsUnaligned,

4397 NumEntries, Out);

4398 }

4399

4400

4401

4402 if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))

4403 return GV;

4404

4405

4406

4407

4409 if (IsConst)

4410 Flags |= 1;

4411 if (IsVolatile)

4412 Flags |= 2;

4413 if (IsUnaligned)

4414 Flags |= 4;

4415

4416

4417

4418 llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.Int8PtrTy);

4421 if (!DtorD->isTrivial())

4423

4424 llvm::Constant *ForwardCompat =

4425 getImageRelativeConstant(llvm::Constant::getNullValue(CGM.Int8PtrTy));

4426 llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant(CTA);

4427 llvm::StructType *TIType = getThrowInfoType();

4428 llvm::Constant *Fields[] = {

4429 llvm::ConstantInt::get(CGM.IntTy, Flags),

4430 getImageRelativeConstant(CleanupFn),

4431 ForwardCompat,

4432 PointerToCatchableTypes

4433 };

4434 auto *GV = new llvm::GlobalVariable(

4435 CGM.getModule(), TIType, true, getLinkageForRTTI(T),

4436 llvm::ConstantStruct::get(TIType, Fields), MangledName.str());

4437 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

4438 GV->setSection(".xdata");

4439 if (GV->isWeakForLinker())

4440 GV->setComdat(CGM.getModule().getOrInsertComdat(GV->getName()));

4441 return GV;

4442}

4443

4445 const Expr *SubExpr = E->getSubExpr();

4446 assert(SubExpr && "SubExpr cannot be null");

4448

4449

4452 true);

4453

4454

4455

4456 llvm::GlobalVariable *TI = getThrowInfo(ThrowType);

4457

4458

4461}

4462

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

4466 std::tie(This, std::ignore, RD) =

4469}

4470

4471bool MicrosoftCXXABI::isPermittedToBeHomogeneousAggregate(

4473

4474

4476 return true;

4477

4478

4479

4480

4482 return false;

4484 return false;

4486 return false;

4488 return false;

4490 return false;

4491

4492

4493

4494

4495

4496

4497

4498

4499

4500

4501

4503 if (const CXXRecordDecl *FRD = B.getType()->getAsCXXRecordDecl()) {

4504 if (!isPermittedToBeHomogeneousAggregate(FRD))

4505 return false;

4506 }

4507 }

4508

4509

4510

4511

4512 return true;

4513}

static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM)

static void emitTlsGuardCheck(CodeGenFunction &CGF, llvm::GlobalValue *TlsGuard, llvm::BasicBlock *DynInitBB, llvm::BasicBlock *ContinueBB)

static llvm::GlobalVariable * getTypeInfoVTable(CodeGenModule &CGM)

static bool hasDefaultCXXMethodCC(ASTContext &Context, const CXXMethodDecl *MD)

static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty, CodeGenModule &CGM)

static llvm::FunctionCallee getInitThreadAbortFn(CodeGenModule &CGM)

static llvm::FunctionCallee getInitThreadHeaderFn(CodeGenModule &CGM)

static llvm::GlobalValue * getTlsGuardVar(CodeGenModule &CGM)

static QualType decomposeTypeForEH(ASTContext &Context, QualType T, bool &IsConst, bool &IsVolatile, bool &IsUnaligned)

static llvm::CallBase * emitRTtypeidCall(CodeGenFunction &CGF, llvm::Value *Argument)

static llvm::FunctionCallee getDynTlsOnDemandInitFn(CodeGenModule &CGM)

static void emitDynamicTlsInitializationCall(CodeGenFunction &CGF, llvm::GlobalValue *TlsGuard, llvm::BasicBlock *ContinueBB)

static void detectAmbiguousBases(SmallVectorImpl< MSRTTIClass > &Classes)

Find ambiguity among base classes.

static void emitDynamicTlsInitialization(CodeGenFunction &CGF)

static void serializeClassHierarchy(SmallVectorImpl< MSRTTIClass > &Classes, const CXXRecordDecl *RD)

Recursively serializes a class hierarchy in pre-order depth first order.

static llvm::FunctionCallee getInitThreadFooterFn(CodeGenModule &CGM)

static bool isDeletingDtor(GlobalDecl GD)

static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)

static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM)

static void mangleVFTableName(MicrosoftMangleContext &MangleContext, const CXXRecordDecl *RD, const VPtrInfo &VFPtr, SmallString< 256 > &Name)

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

llvm::DenseSet< const void * > Visited

const NestedNameSpecifier * Specifier

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

bool isMemberPointerToDerivedMember() const

const ValueDecl * getMemberPointerDecl() const

ArrayRef< const CXXRecordDecl * > getMemberPointerPath() 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.

uint64_t getFieldOffset(const ValueDecl *FD) const

Get the offset of a FieldDecl or IndirectFieldDecl, in bits.

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

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

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

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

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

Retrieves the default calling convention for the current target.

QualType getPointerType(QualType T) const

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

QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const

Return the unique reference to the type for the specified type declaration.

const LangOptions & getLangOpts() const

GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const

CanQualType getSizeType() const

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

CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const

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

CharUnits getTypeSizeInChars(QualType T) const

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

QualType getExceptionObjectType(QualType T) const

const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD)

const TargetInfo & getTargetInfo() const

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

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

llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy

CharUnits getVBPtrOffset() const

getVBPtrOffset - Get the offset for virtual base table pointer.

CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const

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

CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const

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

const VBaseOffsetsMapTy & getVBaseOffsetsMap() const

bool hasExtendableVFPtr() const

hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...

Represents a base class of a C++ class.

CXXCatchStmt - This represents a C++ catch block.

Represents a C++ constructor within a class.

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

FunctionDecl * getOperatorDelete() const

bool isGlobalDelete() const

Represents a C++ destructor within a class.

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

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

const CXXRecordDecl * getParent() const

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

QualType getThisType() const

Return the type of the this pointer.

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

Represents a C++ struct/union/class.

bool hasNonTrivialCopyAssignment() const

Determine whether this class has a non-trivial copy assignment operator (C++ [class....

bool hasPrivateFields() const

bool hasProtectedFields() const

bool hasNonTrivialDestructor() const

Determine whether this class has a non-trivial destructor (C++ [class.dtor]p3)

bool isPolymorphic() const

Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...

unsigned getNumBases() const

Retrieves the number of base classes of this class.

CXXRecordDecl * getMostRecentNonInjectedDecl()

base_class_range vbases()

MSInheritanceModel getMSInheritanceModel() const

Returns the inheritance model used for this record.

bool nullFieldOffsetIsZero() const

In the Microsoft C++ ABI, use zero for the field offset of a null data member pointer if we can guara...

bool hasDefinition() const

bool isEmpty() const

Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).

CXXDestructorDecl * getDestructor() const

Returns the destructor decl for this class.

bool hasNonTrivialDefaultConstructor() const

Determine whether this class has a non-trivial default constructor (C++11 [class.ctor]p5).

bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const

Determine whether this class is virtually derived from the class Base.

bool needsImplicitCopyAssignment() const

Determine whether this class needs an implicit copy assignment operator to be lazily declared.

bool hasSimpleCopyAssignment() const

true if we know for sure that this class has a single, accessible, unambiguous copy assignment operat...

unsigned getNumVBases() const

Retrieves the number of virtual base classes of this class.

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

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

const CXXBaseSpecifier *const * path_const_iterator

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

bool isPositive() const

isPositive - Test whether the quantity is greater than zero.

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.

bool hasProfileIRInstr() const

Check if IR level profile instrumentation is on.

static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)

void setSRetAfterThis(bool AfterThis)

bool isHomogeneousAggregate(QualType Ty, const Type *&Base, uint64_t &Members) const

isHomogeneousAggregate - Return true if a type is an ELFv2 homogeneous aggregate.

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

Address withElementType(llvm::Type *ElemTy) const

Return address with different element type, but same pointer and alignment.

A scoped helper to set the current debug location to the specified location or preferred location of ...

static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)

Apply TemporaryLocation if it is valid.

static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)

Set the IRBuilder to not attach debug locations.

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.

Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name="")

Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")

llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")

Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")

llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")

Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")

Implements C++ ABI-specific code generation functions.

virtual bool shouldEmitExactDynamicCast(QualType DestRecordTy)=0

llvm::Value *& getStructorImplicitParamValue(CodeGenFunction &CGF)

virtual void EmitCXXConstructors(const CXXConstructorDecl *D)=0

Emit constructor variants required by this ABI.

virtual llvm::Constant * getAddrOfRTTIDescriptor(QualType Ty)=0

virtual bool hasMostDerivedReturn(GlobalDecl GD) const

virtual bool HasThisReturn(GlobalDecl GD) const

Returns true if the given constructor or destructor is one of the kinds that the ABI says returns 'th...

virtual llvm::Value * getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base, const CXXRecordDecl *NearestVBase)=0

Get the address point of the vtable for the given base subobject while building a constructor or a de...

virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C)=0

virtual std::vector< CharUnits > getVBPtrOffsets(const CXXRecordDecl *RD)

Gets the offsets of all the virtual base pointers in a given class.

virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn)=0

virtual void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, const CXXRecordDecl *RD)

Emit the code to initialize hidden members required to handle virtual inheritance,...

virtual bool isMemberPointerConvertible(const MemberPointerType *MPT) const

Return whether or not a member pointers type is convertible to an IR type.

virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0

virtual bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr)=0

Checks if ABI requires extra virtual offset for vtable field.

virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, llvm::GlobalVariable *DeclPtr, bool PerformInit)=0

Emits the guarded initializer and destructor setup for the given variable, given that it couldn't be ...

virtual void EmitCXXDestructors(const CXXDestructorDecl *D)=0

Emit destructor variants required by this ABI.

virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF)=0

Emit the ABI-specific prolog for the function.

virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, CXXDtorType DT) const =0

Returns true if the given destructor type should be emitted as a linkonce delegating thunk,...

virtual CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD)

Get the ABI-specific "this" parameter adjustment to apply in the prologue of a virtual function.

virtual void setCXXDestructorDLLStorage(llvm::GlobalValue *GV, const CXXDestructorDecl *Dtor, CXXDtorType DT) const

RecordArgABI

Specify how one should pass an argument of a record type.

virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy)=0

virtual llvm::Type * ConvertMemberPointerType(const MemberPointerType *MPT)

Find the LLVM type used to represent the given member pointer type.

virtual llvm::Value * performThisAdjustment(CodeGenFunction &CGF, Address This, const CXXRecordDecl *UnadjustedClass, const ThunkInfo &TI)=0

virtual llvm::Constant * EmitNullMemberPointer(const MemberPointerType *MPT)

Create a null member pointer of the given type.

virtual StringRef GetPureVirtualCallName()=0

Gets the pure virtual member call function.

virtual CharUnits getArrayCookieSizeImpl(QualType elementType)

Returns the extra size required in order to store the array cookie for the given type.

virtual bool isSRetParameterAfterThis() const

Returns true if the implicit 'sret' parameter comes after the implicit 'this' parameter of C++ instan...

virtual void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr)=0

Emit code to force the execution of a destructor during global teardown.

virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const =0

Determine whether it's possible to emit a vtable for RD, even though we do not know that the vtable h...

virtual StringRef GetDeletedVirtualCallName()=0

Gets the deleted virtual member call name.

virtual llvm::Value * EmitMemberPointerIsNotNull(CodeGenFunction &CGF, llvm::Value *MemPtr, const MemberPointerType *MPT)

Determine if a member pointer is non-null. Returns an i1.

virtual llvm::Value * performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const CXXRecordDecl *UnadjustedClass, const ReturnAdjustment &RA)=0

virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, QualType LValType)=0

Emit a reference to a non-local thread_local variable (including triggering the initialization of all...

bool isEmittedWithConstantInitializer(const VarDecl *VD, bool InspectInitForWeakDef=false) const

Determine whether we will definitely emit this variable with a constant initializer,...

virtual llvm::Value * EmitMemberPointerComparison(CodeGenFunction &CGF, llvm::Value *L, llvm::Value *R, const MemberPointerType *MPT, bool Inequality)

Emit a comparison between two member pointers. Returns an i1.

virtual llvm::Constant * EmitMemberPointer(const APValue &MP, QualType MPT)

Create a member pointer for the given member pointer constant.

virtual llvm::Constant * getVTableAddressPoint(BaseSubobject Base, const CXXRecordDecl *VTableClass)=0

Get the address point of the vtable for the given base subobject.

virtual void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params)=0

Insert any ABI-specific implicit parameters into the parameter list for a function.

virtual llvm::Value * readArrayCookieImpl(CodeGenFunction &IGF, Address ptr, CharUnits cookieSize)

Reads the array cookie for an allocation which is known to have one.

virtual llvm::Value * EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, const MemberPointerType *MPT)

Calculate an l-value from an object and a data member pointer.

virtual llvm::Value * getCXXDestructorImplicitParam(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating)=0

Get the implicit (second) parameter that comes after the "this" pointer, or nullptr if there is isn't...

virtual bool requiresArrayCookie(const CXXDeleteExpr *E, QualType eltType)

virtual CatchTypeInfo getCatchAllTypeInfo()

virtual std::pair< llvm::Value *, const CXXRecordDecl * > LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD)=0

Load a vtable from This, an object of polymorphic type RD, or from one of its virtual bases if it doe...

virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment)=0

virtual Address adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, Address This, bool VirtualCall)

Perform ABI-specific "this" argument adjustment required prior to a call of a virtual function.

bool mayNeedDestruction(const VarDecl *VD) const

virtual llvm::BasicBlock * EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, const CXXRecordDecl *RD)

virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass)=0

Checks if ABI requires to initialize vptrs for given dynamic class.

virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E)=0

virtual llvm::Value * GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl)=0

virtual bool isThisCompleteObject(GlobalDecl GD) const =0

Determine whether there's something special about the rules of the ABI tell us that 'this' is a compl...

virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, Address This, llvm::Type *Ty, SourceLocation Loc)=0

Build a virtual function pointer in the ABI-specific way.

virtual bool classifyReturnType(CGFunctionInfo &FI) const =0

If the C++ ABI requires the given type be returned in a particular way, this method sets RetAI and re...

virtual void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, const CXXDestructorDecl *Dtor)=0

virtual CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType)=0

virtual void EmitThreadLocalInitFuncs(CodeGenModule &CGM, ArrayRef< const VarDecl * > CXXThreadLocals, ArrayRef< llvm::Function * > CXXThreadLocalInits, ArrayRef< const VarDecl * > CXXThreadLocalInitVars)=0

Emits ABI-required functions necessary to initialize thread_local variables in this translation unit.

virtual bool usesThreadWrapperFunction(const VarDecl *VD) const =0

virtual RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const =0

Returns how an argument of the given record type should be passed.

virtual llvm::Value * emitExactDynamicCast(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess, llvm::BasicBlock *CastFail)=0

Emit a dynamic_cast from SrcRecordTy to DestRecordTy.

virtual const CXXRecordDecl * getThisArgumentTypeForMethod(GlobalDecl GD)

Get the type of the implicit "this" parameter used by a method.

virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)=0

Emit the destructor call.

virtual llvm::GlobalVariable * getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset)=0

Get the address of the vtable for the given record decl which should be used for the vptr at the give...

virtual bool EmitBadCastCall(CodeGenFunction &CGF)=0

virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, CallArgList &CallArgs)

virtual llvm::Constant * EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset)

Create a member pointer for the given field.

virtual llvm::Value * EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy)=0

virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD)=0

Emit any tables needed to implement virtual inheritance.

virtual void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD)=0

Emits the VTable definitions required for the given record type.

virtual CGCallee EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, Address This, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, const MemberPointerType *MPT)

Load a member function from an object and a member function pointer.

virtual bool isPermittedToBeHomogeneousAggregate(const CXXRecordDecl *RD) const

Returns true if the ABI permits the argument to be a homogeneous aggregate.

virtual void emitCXXStructor(GlobalDecl GD)=0

Emit a single constructor/destructor with the given type from a C++ constructor Decl.

virtual llvm::Value * EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke)=0

Emit the ABI-specific virtual destructor call.

virtual bool exportThunk()=0

virtual void EmitBadTypeidCall(CodeGenFunction &CGF)=0

virtual llvm::Value * emitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy)=0

virtual bool isZeroInitializable(const MemberPointerType *MPT)

Return true if the given member pointer can be zero-initialized (in the C++ sense) with an LLVM zeroi...

virtual llvm::Value * EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src)

Perform a derived-to-base, base-to-derived, or bitcast member pointer conversion.

virtual llvm::Constant * EmitMemberFunctionPointer(const CXXMethodDecl *MD)

Create a member pointer for the given method.

virtual llvm::Value * emitDynamicCastCall(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd)=0

virtual llvm::GlobalVariable * getThrowInfo(QualType T)

virtual llvm::GlobalValue::LinkageTypes getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const

virtual Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr, llvm::Value *NumElements, const CXXNewExpr *expr, QualType ElementType)

Initialize the array cookie for the given allocation.

ASTContext & getContext() const

virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, QualType SrcRecordTy)=0

virtual AddedStructorArgCounts buildStructorSignature(GlobalDecl GD, SmallVectorImpl< CanQualType > &ArgTys)=0

Build the signature of the given constructor or destructor variant by adding any required parameters.

MangleContext & getMangleContext()

Gets the mangle context.

virtual AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating)=0

All available information about a concrete callee.

static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)

static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())

CGFunctionInfo - Class to encapsulate the information about a function definition.

bool isInstanceMethod() const

ABIArgInfo & getReturnInfo()

CanQualType getReturnType() const

unsigned getEffectiveCallingConvention() const

getEffectiveCallingConvention - Return the actual calling convention to use, which may depend on the ...

CallArgList - Type for representing both the value and type of arguments in a call.

void add(RValue rvalue, QualType type)

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

void GenerateCXXGlobalInitFunc(llvm::Function *Fn, ArrayRef< llvm::Function * > CXXThreadLocals, ConstantAddress Guard=ConstantAddress::invalid())

GenerateCXXGlobalInitFunc - Generates code for initializing global variables.

void FinishFunction(SourceLocation EndLoc=SourceLocation())

FinishFunction - Complete IR generation of the current function.

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass, VTableAuthMode AuthMode=VTableAuthMode::Authenticate)

GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.

llvm::Constant * createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)

void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)

bool CurFuncIsThunk

In C++, whether we are code generating a thunk.

void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)

llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)

void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, QualType DeleteTy, llvm::Value *NumElements=nullptr, CharUnits CookieSize=CharUnits())

llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)

createBasicBlock - Create an LLVM basic block.

void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)

EmitBlock - Emit the given block.

llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)

Emit a type checked load from the given vtable.

void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)

EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...

const Decl * CurCodeDecl

CurCodeDecl - This is the inner-most code context, which includes blocks.

RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)

CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...

void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit)

EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.

bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)

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

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 registerGlobalDtorWithAtExit(const VarDecl &D, llvm::FunctionCallee fn, llvm::Constant *addr)

Call atexit() with a function that passes the given argument to the given function.

RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)

EmitCall - Generate a call of the given function, expecting the given result type,...

llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")

ASTContext & getContext() const

const Decl * CurFuncDecl

CurFuncDecl - Holds the Decl for the current outermost non-closure context.

AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)

void EmitAutoVarCleanups(const AutoVarEmission &emission)

void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)

PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.

void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc)

If whole-program virtual table optimization is enabled, emit an assumption that VTable is a member of...

llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")

void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)

CodeGenTypes & getTypes() const

llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")

LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)

LValue EmitLoadOfReferenceLValue(LValue RefLVal)

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

llvm::Instruction * CurrentFuncletPad

llvm::LLVMContext & getLLVMContext()

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.

void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, llvm::FunctionCallee Callee)

Emit a musttail call for a thunk with a potentially adjusted this pointer.

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

void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const

Set visibility, dllimport/dllexport and dso_local.

void AddCXXDtorEntry(llvm::FunctionCallee DtorFn, llvm::Constant *Object)

Add a destructor and object to add to the C++ global destructor function.

void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD)

Create and attach type metadata for the given vtable.

void setDSOLocal(llvm::GlobalValue *GV) const

llvm::GlobalObject::VCallVisibility GetVCallVisibilityLevel(const CXXRecordDecl *RD, llvm::DenseSet< const CXXRecordDecl * > &Visited)

Returns the vcall visibility of the given type.

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

llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)

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

llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)

Return the address of the given function.

const ABIInfo & getABIInfo()

DiagnosticsEngine & getDiags() const

llvm::Constant * getAddrOfCXXStructor(GlobalDecl GD, const CGFunctionInfo *FnInfo=nullptr, llvm::FunctionType *FnType=nullptr, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)

Return the address of the constructor/destructor of the given type.

llvm::GlobalValue::LinkageTypes getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage)

Returns LLVM linkage for a declarator.

const LangOptions & getLangOpts() const

CodeGenTypes & getTypes()

const TargetInfo & getTarget() const

void EmitGlobal(GlobalDecl D)

Emit code for a single global function or var decl.

void addUsedGlobal(llvm::GlobalValue *GV)

Add a global to a list to be added to the llvm.used metadata.

void AppendLinkerOptions(StringRef Opts)

Appends Opts to the "llvm.linker.options" metadata value.

bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D)

Try to emit a base destructor as an alias to its primary base-class destructor.

CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, CastExpr::path_const_iterator End)

CharUnits getVBaseAlignment(CharUnits DerivedAlign, const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)

Returns the assumed alignment of a virtual base of a class.

llvm::Function * codegenCXXStructor(GlobalDecl GD)

llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)

Create a new runtime global variable with the specified type and name.

void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const

Set the TLS mode for the given LLVM GlobalValue for the thread-local variable declaration D.

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.

MicrosoftVTableContext & getMicrosoftVTableContext()

const CodeGenOptions & getCodeGenOpts() const

StringRef getMangledName(GlobalDecl GD)

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::LLVMContext & getLLVMContext()

llvm::GlobalValue * GetGlobalValue(StringRef Ref)

void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO)

void setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl D) const

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 addDeferredVTable(const CXXRecordDecl *RD)

void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)

Set the LLVM function attributes which only apply to a function definition.

llvm::Function * CreateGlobalInitOrCleanUpFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc=SourceLocation(), bool TLS=false, llvm::GlobalVariable::LinkageTypes Linkage=llvm::GlobalVariable::InternalLinkage)

This class organizes the cross-module state that is used while lowering AST types to LLVM types.

llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)

GetFunctionType - Get the LLVM function type for.

llvm::Type * ConvertTypeForMem(QualType T)

ConvertTypeForMem - Convert type T into a llvm::Type.

const CGFunctionInfo & arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD)

Arrange a thunk that takes 'this' as the first parameter followed by varargs.

const CGFunctionInfo & arrangeCXXConstructorCall(const CallArgList &Args, const CXXConstructorDecl *D, CXXCtorType CtorKind, unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, bool PassProtoArgs=true)

Arrange a call to a C++ method, passing the given arguments.

const CGFunctionInfo & arrangeCXXStructorDeclaration(GlobalDecl GD)

const CGFunctionInfo & arrangeMSCtorClosure(const CXXConstructorDecl *CD, CXXCtorType CT)

const CGFunctionInfo & arrangeNullaryFunction()

A nullary function is a freestanding function of type 'void ()'.

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.

llvm::Type * getVTableType(const VTableLayout &layout)

Returns the type of a vtable with the given layout.

A specialization of Address that requires the address to be an LLVM Constant.

The standard implementation of ConstantInitBuilder used in Clang.

Information for lazily generating a cleanup.

FunctionArgList - Type for representing both the decl and type of parameters to a function.

LValue - This represents an lvalue references.

RValue - This trivial value class is used to represent the result of an expression that is evaluated.

static RValue get(llvm::Value *V)

llvm::Value * getScalarVal() const

getScalarVal() - Return the Value* of this scalar value.

An abstract representation of an aligned address.

ReturnValueSlot - Contains the address where the return value of a function can be stored,...

DeclContext * getParent()

getParent - Returns the containing DeclContext.

decl_range decls() const

decls_begin/decls_end - Iterate over the declarations stored in this context.

Decl - This represents one declaration (or definition), e.g.

bool isInStdNamespace() const

SourceLocation getLocation() const

DeclContext * getDeclContext()

const LangOptions & getLangOpts() const LLVM_READONLY

Helper to get the language options from the ASTContext.

Concrete class used by the front-end to report problems and issues.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

unsigned getCustomDiagID(Level L, const char(&FormatString)[N])

Return an ID for a diagnostic with the specified format string and level.

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

Represents a member of a struct/union/class.

const RecordDecl * getParent() const

Returns the parent of this field declaration, which is the struct in which this field is defined.

ArrayRef< ParmVarDecl * > parameters() const

unsigned getNumParams() const

Return the number of parameters this function must have based on its FunctionType.

Represents a prototype with parameter type info, e.g.

bool isVariadic() const

Whether this function prototype is variadic.

GlobalDecl - represents a global declaration.

GlobalDecl getWithCtorType(CXXCtorType Type)

GlobalDecl getWithDtorType(CXXDtorType Type)

CXXDtorType getDtorType() const

const Decl * getDecl() const

One of these records is kept for each identifier that is lexed.

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 isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const

bool isExplicitDefaultVisibilityExportMapping() const

bool isAllDefaultVisibilityExportMapping() const

MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...

A pointer to member type per C++ 8.3.3 - Pointers to members.

CXXRecordDecl * getMostRecentCXXRecordDecl() const

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.

unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)

Returns the index of VBase in the vbtable of Derived.

MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD)

const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)

const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)

Describes a module or submodule.

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

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

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

bool isExternallyVisible() const

Represents a parameter to a function.

A (possibly-)qualified type.

bool isVolatileQualified() const

Determine whether this type is volatile-qualified.

bool isNull() const

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

const Type * getTypePtr() const

Retrieves a pointer to the underlying (unqualified) type.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

bool isConstQualified() const

Determine whether this type is const-qualified.

DestructionKind isDestructedType() const

Returns a nonzero value if objects of this type require non-trivial work to clean up after.

bool hasUnaligned() const

bool canPassInRegisters() const

Determine whether this class can be passed in registers.

Encodes a location in the source.

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

uint64_t getPointerWidth(LangAS AddrSpace) const

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

const Type * getTypeForDecl() const

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

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

bool isPointerType() 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.

bool isObjectType() const

Determine whether this type is an object type.

Linkage getLinkage() const

Determine the linkage of this type.

const T * getAs() const

Member-template getAs'.

bool isNullPtrType() const

Represents a single component in a vtable.

ArrayRef< VTableComponent > vtable_components() const

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

Represents a variable declaration or definition.

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

@ 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 * CreateMicrosoftCXXABI(CodeGenModule &CGM)

Creates a Microsoft-family ABI.

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr

Matches expressions.

constexpr Variable var(Literal L)

Returns the variable of L.

bool This(InterpState &S, CodePtr OpPC)

bool Zero(InterpState &S, CodePtr OpPC)

bool Ret(InterpState &S, CodePtr &PC)

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

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_DefaultClosure

Default closure variant of a ctor.

@ Ctor_CopyingClosure

Copying closure variant of a ctor.

@ Ctor_Complete

Complete object ctor.

GVALinkage

A more specific kind of linkage than enum Linkage.

void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)

bool inheritanceModelHasNVOffsetField(bool IsMemberFunction, MSInheritanceModel Inheritance)

bool inheritanceModelHasOnlyOneField(bool IsMemberFunction, MSInheritanceModel Inheritance)

bool inheritanceModelHasVBPtrOffsetField(MSInheritanceModel Inheritance)

bool inheritanceModelHasVBTableOffsetField(MSInheritanceModel Inheritance)

Linkage

Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.

CXXDtorType

C++ destructor types.

@ Dtor_Comdat

The COMDAT used for dtors.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

CastKind

CastKind - The kind of operation required for a conversion.

const FunctionProtoType * T

MSInheritanceModel

Assigned inheritance model for a class in the MS C++ ABI.

CallingConv

CallingConv - Specifies the calling convention that a function uses.

U cast(CodeGen::Address addr)

@ Class

The "class" keyword introduces the elaborated-type-specifier.

@ Implicit

An implicit conversion.

Diagnostic wrappers for TextAPI types for error reporting.

Similar to AddedStructorArgs, but only notes the number of additional arguments.

Additional implicit arguments to add to the beginning (Prefix) and end (Suffix) of a constructor / de...

The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...

llvm::PointerType * VoidPtrTy

llvm::PointerType * Int8PtrPtrTy

CharUnits getIntAlign() const

llvm::IntegerType * Int8Ty

i8, i16, i32, and i64

CharUnits getIntSize() const

llvm::IntegerType * SizeTy

llvm::IntegerType * Int32Ty

llvm::IntegerType * IntPtrTy

llvm::IntegerType * IntTy

int

llvm::PointerType * Int8PtrTy

llvm::PointerType * UnqualPtrTy

llvm::IntegerType * PtrDiffTy

CharUnits getPointerAlign() const

const CXXRecordDecl * VBase

If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to.

CharUnits VFPtrOffset

This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...

uint64_t Index

Method's index in the vftable.

union clang::ReturnAdjustment::VirtualAdjustment Virtual

int64_t NonVirtual

The non-virtual adjustment from the derived object to its nearest virtual base.

A this pointer adjustment.

union clang::ThisAdjustment::VirtualAdjustment Virtual

int64_t NonVirtual

The non-virtual adjustment from the derived object to its nearest virtual base.

The this pointer adjustment as well as an optional return adjustment for a thunk.

ThisAdjustment This

The this pointer adjustment.

Holds information about the inheritance path to a virtual base or function table pointer.

CharUnits NonVirtualOffset

IntroducingObject is at this offset from its containing complete object or virtual base.

CharUnits FullOffsetInMDC

Static offset from the top of the most derived class to this vfptr, including any virtual base offset...

const CXXRecordDecl * getVBaseWithVPtr() const

The vptr is stored inside the non-virtual component of this virtual base.

const CXXRecordDecl * IntroducingObject

This is the class that introduced the vptr by declaring new virtual methods or virtual bases.

BasePath MangledPath

The bases from the inheritance path that got used to mangle the vbtable name.

BasePath PathToIntroducingObject

This holds the base classes path from the complete type to the first base with the given vfptr offset...

const CXXRecordDecl * ObjectWithVPtr

This is the most derived class that has this vptr at offset zero.

struct clang::ReturnAdjustment::VirtualAdjustment::@193 Microsoft

uint32_t VBPtrOffset

The offset (in bytes) of the vbptr, relative to the beginning of the derived class.

uint32_t VBIndex

Index of the virtual base in the vbtable.

int32_t VtordispOffset

The offset of the vtordisp (in bytes), relative to the ECX.

int32_t VBOffsetOffset

The offset (in bytes) of the vbase offset in the vbtable.

int32_t VBPtrOffset

The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...

struct clang::ThisAdjustment::VirtualAdjustment::@195 Microsoft