aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGVTables.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2011-02-06 18:31:40 +0000
committerAnders Carlsson <andersca@mac.com>2011-02-06 18:31:40 +0000
commit14e82fd91c6d5041aa840574143521d244f185cd (patch)
tree8a0f4a9734a6085ec451e9c2f85becae35533471 /lib/CodeGen/CGVTables.cpp
parent84c49e4e4baeb4c30251fd72220efb344b033cf0 (diff)
When building with optimizations, emit thunks with available_externally linkage so devirtualized function calls can also be de-thunked.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124984 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVTables.cpp')
-rw-r--r--lib/CodeGen/CGVTables.cpp38
1 files changed, 34 insertions, 4 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index e626be2871..3dd7a15fe3 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -2679,7 +2679,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
setThunkVisibility(CGM, MD, Thunk, Fn);
}
-void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
+void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
+ bool UseAvailableExternallyLinkage)
{
llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
@@ -2714,9 +2715,37 @@ void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
OldThunkFn->eraseFromParent();
}
- // Actually generate the thunk body.
llvm::Function *ThunkFn = cast<llvm::Function>(Entry);
+
+ if (!ThunkFn->isDeclaration()) {
+ if (UseAvailableExternallyLinkage) {
+ // There is already a thunk emitted for this function, do nothing.
+ return;
+ }
+
+ // We should never be able to get a function with a definition here.
+ assert(false && "Shouldn't have an already existing definition");
+ }
+
+ // Actually generate the thunk body.
CodeGenFunction(CGM).GenerateThunk(ThunkFn, GD, Thunk);
+
+ if (UseAvailableExternallyLinkage)
+ ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+}
+
+void CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD,
+ const ThunkInfo &Thunk) {
+ // We only want to do this when building with optimizations.
+ if (!CGM.getCodeGenOpts().OptimizationLevel)
+ return;
+
+ // We can't emit thunks for member functions with incomplete types.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ if (CGM.getTypes().VerifyFuncTypeComplete(MD->getType().getTypePtr()))
+ return;
+
+ EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);
}
void CodeGenVTables::EmitThunks(GlobalDecl GD)
@@ -2741,7 +2770,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
const ThunkInfoVectorTy &ThunkInfoVector = I->second;
for (unsigned I = 0, E = ThunkInfoVector.size(); I != E; ++I)
- EmitThunk(GD, ThunkInfoVector[I]);
+ EmitThunk(GD, ThunkInfoVector[I], /*UseAvailableExternallyLinkage=*/false);
}
void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
@@ -2913,7 +2942,8 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
Init = CGM.GetAddrOfThunk(GD, Thunk);
-
+ MaybeEmitThunkAvailableExternally(GD, Thunk);
+
NextVTableThunkIndex++;
} else {
const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);