Assume loads fix #2
There was linker problem, and it turns out that it is not always safe
to refer to vtable. If the vtable is used, then we can refer to it
without any problem, but because we don't know when it will be used or
not, we can only check if vtable is external or it is safe to to emit it
speculativly (when class it doesn't have any inline virtual functions).
It should be fixed in the future.
http://reviews.llvm.org/D12385
llvm-svn: 246214
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 158d29a..259c878 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -218,8 +218,10 @@
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
- virtual bool canEmitAvailableExternallyVTable(
- const CXXRecordDecl *RD) const = 0;
+ /// \brief Determine whether it's possible to emit a vtable for \p RD, even
+ /// though we do not know that the vtable has been marked as used by semantic
+ /// analysis.
+ virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const = 0;
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0;
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index cd39749..507bae8 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1857,8 +1857,15 @@
// with a vtable. We don't do this for base subobjects for two reasons:
// first, it's incorrect for classes with virtual bases, and second, we're
// about to overwrite the vptrs anyway.
+ // We also have to make sure if we can refer to vtable:
+ // - If vtable is external then it's safe to use it (for available_externally
+ // CGVTables will make sure if it can emit it).
+ // - Otherwise we can refer to vtable if it's safe to speculatively emit.
+ // FIXME: If vtable is used by ctor/dtor, we are always safe to refer to it.
if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
- ClassDecl->isDynamicClass() && Type != Ctor_Base)
+ ClassDecl->isDynamicClass() && Type != Ctor_Base &&
+ (CGM.getVTables().isVTableExternal(ClassDecl) ||
+ CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl)))
EmitVTableAssumptionLoads(ClassDecl, This);
}
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index fcb5c36..bd620a1 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -682,7 +682,7 @@
static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM,
const CXXRecordDecl *RD) {
return CGM.getCodeGenOpts().OptimizationLevel > 0 &&
- CGM.getCXXABI().canEmitAvailableExternallyVTable(RD);
+ CGM.getCXXABI().canSpeculativelyEmitVTable(RD);
}
/// Compute the required linkage of the v-table for the given class.
@@ -832,11 +832,11 @@
/// we define that v-table?
static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM,
const CXXRecordDecl *RD) {
- // If vtable is internal then it has to be done
+ // If vtable is internal then it has to be done.
if (!CGM.getVTables().isVTableExternal(RD))
return true;
- // If it's external then maybe we will need it as available_externally
+ // If it's external then maybe we will need it as available_externally.
return shouldEmitAvailableExternallyVTable(CGM, RD);
}
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index ce37a7f..31a1e48 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -229,7 +229,7 @@
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
- bool canEmitAvailableExternallyVTable(const CXXRecordDecl *RD) const override;
+ bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
bool ReturnAdjustment) override {
@@ -1523,8 +1523,7 @@
VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
}
-bool ItaniumCXXABI::canEmitAvailableExternallyVTable(
- const CXXRecordDecl *RD) const {
+bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
// We don't emit available_externally vtables if we are in -fapple-kext mode
// because kext mode does not permit devirtualization.
if (CGM.getLangOpts().AppleKext)
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index bbc5c2f..de97ec3 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -106,8 +106,7 @@
QualType DestTy) override;
bool EmitBadCastCall(CodeGenFunction &CGF) override;
- bool canEmitAvailableExternallyVTable(
- const CXXRecordDecl *RD) const override {
+ bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override {
return false;
}