aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCXX.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-12-06 22:01:30 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-12-06 22:01:30 +0000
commit72649ed78a25365d003b5218cae7b332c418800e (patch)
tree1e0f8aab2711bc5812e2f4d9b3143ab48b9bc0a1 /lib/CodeGen/CGCXX.cpp
parentd490f953e812a9bb1729637cc70a6db7d997ced0 (diff)
Work-in-progess rewrite of thunks: move thunk generation outside of vtable
generation, and make sure we generate thunks when the function is defined rather than when the vtable is defined. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90722 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCXX.cpp')
-rw-r--r--lib/CodeGen/CGCXX.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index a2674b82d1..77bee48b58 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -994,6 +994,102 @@ CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
}
llvm::Constant *
+CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
+ const ThunkAdjustment &ThisAdjustment) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // Compute mangled name
+ llvm::SmallString<256> OutName;
+ if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
+ getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), ThisAdjustment,
+ OutName);
+ else
+ getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
+ OutName += '\0';
+ const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
+
+ // Get function for mangled name
+ const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
+ return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
+}
+
+llvm::Constant *
+CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
+ const CovariantThunkAdjustment &Adjustment) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // Compute mangled name
+ llvm::SmallString<256> OutName;
+ getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
+ OutName += '\0';
+ const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
+
+ // Get function for mangled name
+ const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
+ return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
+}
+
+void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
+ BuildThunksForVirtualRecursive(GD, GD);
+}
+
+void
+CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
+ GlobalDecl BaseOGD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ const CXXMethodDecl *BaseOMD = cast<CXXMethodDecl>(BaseOGD.getDecl());
+ for (CXXMethodDecl::method_iterator mi = BaseOMD->begin_overridden_methods(),
+ e = BaseOMD->end_overridden_methods();
+ mi != e; ++mi) {
+ GlobalDecl OGD;
+ const CXXMethodDecl *OMD = *mi;
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
+ OGD = GlobalDecl(DD, GD.getDtorType());
+ else
+ OGD = GlobalDecl(OMD);
+ QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
+ CanQualType oret = getContext().getCanonicalType(nc_oret);
+ QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
+ CanQualType ret = getContext().getCanonicalType(nc_ret);
+ ThunkAdjustment ReturnAdjustment;
+ if (oret != ret) {
+ QualType qD = nc_ret->getPointeeType();
+ QualType qB = nc_oret->getPointeeType();
+ CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
+ CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
+ ReturnAdjustment = ComputeThunkAdjustment(D, B);
+ }
+ ThunkAdjustment ThisAdjustment =
+ getVtableInfo().getThisAdjustment(GD, OGD);
+ bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace();
+ if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) {
+ CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment);
+ llvm::Constant *FnConst;
+ if (!ReturnAdjustment.isEmpty())
+ FnConst = GetAddrOfCovariantThunk(GD, CoAdj);
+ else
+ FnConst = GetAddrOfThunk(GD, ThisAdjustment);
+ if (!isa<llvm::Function>(FnConst)) {
+ assert(0 && "Figure out how to handle incomplete-type cases!");
+ }
+ llvm::Function *Fn = cast<llvm::Function>(FnConst);
+ if (Fn->isDeclaration()) {
+ llvm::GlobalVariable::LinkageTypes linktype;
+ linktype = llvm::GlobalValue::WeakAnyLinkage;
+ if (!Extern)
+ linktype = llvm::GlobalValue::InternalLinkage;
+ Fn->setLinkage(linktype);
+ if (!Features.Exceptions && !Features.ObjCNonFragileABI)
+ Fn->addFnAttr(llvm::Attribute::NoUnwind);
+ Fn->setAlignment(2);
+ CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
+ }
+ }
+ BuildThunksForVirtualRecursive(GD, OGD);
+ }
+}
+
+llvm::Constant *
CodeGenModule::BuildThunk(GlobalDecl GD, bool Extern,
const ThunkAdjustment &ThisAdjustment) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());