diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-01 20:58:49 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-01 20:58:49 +0000 |
| commit | 416ada0f75bab22b084a1776deb229cd4a669c4d (patch) | |
| tree | 6eb65f3790434471361628af6199b07a4de92de7 /lib/CodeGen/ItaniumCXXABI.cpp | |
| parent | 550ae89a710bf458d47e5b1d183f5e7039c2b384 (diff) | |
Notes
Diffstat (limited to 'lib/CodeGen/ItaniumCXXABI.cpp')
| -rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 66f51305430a..62b0e6155f99 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -366,20 +366,30 @@ public: void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; private: - bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const { - const auto &VtableLayout = - CGM.getItaniumVTableContext().getVTableLayout(RD); + bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const { + const auto &VtableLayout = + CGM.getItaniumVTableContext().getVTableLayout(RD); - for (const auto &VtableComponent : VtableLayout.vtable_components()) { - // Skip empty slot. - if (!VtableComponent.isUsedFunctionPointerKind()) - continue; + for (const auto &VtableComponent : VtableLayout.vtable_components()) { + // Skip empty slot. + if (!VtableComponent.isUsedFunctionPointerKind()) + continue; - const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); - if (Method->getCanonicalDecl()->isInlined()) - return true; - } - return false; + const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); + if (!Method->getCanonicalDecl()->isInlined()) + continue; + + StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl()); + auto *Entry = CGM.GetGlobalValue(Name); + // This checks if virtual inline function has already been emitted. + // Note that it is possible that this inline function would be emitted + // after trying to emit vtable speculatively. Because of this we do + // an extra pass after emitting all deferred vtables to find and emit + // these vtables opportunistically. + if (!Entry || Entry->isDeclaration()) + return true; + } + return false; } bool isVTableHidden(const CXXRecordDecl *RD) const { @@ -1687,11 +1697,11 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const { if (CGM.getLangOpts().AppleKext) return false; - // If we don't have any inline virtual functions, and if vtable is not hidden, - // then we are safe to emit available_externally copy of vtable. + // If we don't have any not emitted inline virtual function, and if vtable is + // not hidden, then we are safe to emit available_externally copy of vtable. // FIXME we can still emit a copy of the vtable if we // can emit definition of the inline functions. - return !hasAnyVirtualInlineFunction(RD) && !isVTableHidden(RD); + return !hasAnyUnusedVirtualInlineFunction(RD) && !isVTableHidden(RD); } static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, Address InitialPtr, @@ -2576,6 +2586,9 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { if (!GV) { // Create a new global variable. + // Note for the future: If we would ever like to do deferred emission of + // RTTI, check if emitting vtables opportunistically need any adjustment. + GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, /*Constant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr, |
