diff options
author | Anders Carlsson <andersca@mac.com> | 2010-03-23 18:18:41 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-03-23 18:18:41 +0000 |
commit | 55e89f877cf2846f1d76b5f333026389bfb8e231 (patch) | |
tree | 0454ed6338adb02e40c0357cb2ab0877eb1db15a | |
parent | 3131496622ba071ec34d58da48d07f990430425f (diff) | |
download | bcm5719-llvm-55e89f877cf2846f1d76b5f333026389bfb8e231.tar.gz bcm5719-llvm-55e89f877cf2846f1d76b5f333026389bfb8e231.zip |
More work on thunks - don't assert if there's a variable with the same name as the thunk already.
llvm-svn: 99303
-rw-r--r-- | clang/lib/CodeGen/CGVtable.cpp | 34 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVtable.h | 2 |
2 files changed, 34 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index 6fee2a566c4..9204e4e565c 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -3669,8 +3669,40 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk) { llvm::Constant *ThunkFn = CGM.GetAddrOfThunk(GD, Thunk); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); + + // Strip off a bitcast if we got one back. + if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(ThunkFn)) { + assert(CE->getOpcode() == llvm::Instruction::BitCast); + ThunkFn = CE->getOperand(0); + } - (void)ThunkFn; + const llvm::Type *ThunkFnTy = + cast<llvm::GlobalValue>(ThunkFn)->getType()->getElementType(); + + // There's already a declaration with the same name, check if it has the same + // type or if we need to replace it. + if (ThunkFnTy != CGM.getTypes().GetFunctionTypeForVtable(MD)) { + llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(ThunkFn); + + // If the types mismatch then we have to rewrite the definition. + assert(OldThunkFn->isDeclaration() && + "Shouldn't replace non-declaration"); + + // Remove the name from the old thunk function and get a new thunk. + OldThunkFn->setName(llvm::StringRef()); + ThunkFn = CGM.GetAddrOfThunk(GD, Thunk); + + // If needed, replace the old thunk with a bitcast. + if (!OldThunkFn->use_empty()) { + llvm::Constant *NewPtrForOldDecl = + llvm::ConstantExpr::getBitCast(ThunkFn, OldThunkFn->getType()); + OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl); + } + + // Remove the old thunk. + OldThunkFn->eraseFromParent(); + } } void CodeGenVTables::EmitThunks(GlobalDecl GD) diff --git a/clang/lib/CodeGen/CGVtable.h b/clang/lib/CodeGen/CGVtable.h index 450fa9382f2..cc4cb87f7f4 100644 --- a/clang/lib/CodeGen/CGVtable.h +++ b/clang/lib/CodeGen/CGVtable.h @@ -341,7 +341,7 @@ public: // have, as well as the vtable itself if the global decl is the key function. void EmitVTableRelatedData(GlobalDecl GD); - /// GenerateClassData - Generate all the class data requires to be generated + /// GenerateClassData - Generate all the class data required to be generated /// upon definition of a KeyFunction. This includes the vtable, the /// rtti data structure and the VTT. /// |