[cfe-commits] r90722 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGVtable.cpp lib/CodeGen/CGVtable.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/virt.cpp
Eli Friedman
eli.friedman at gmail.com
Sun Dec 6 14:01:30 PST 2009
Author: efriedma
Date: Sun Dec 6 16:01:30 2009
New Revision: 90722
URL: http://llvm.org/viewvc/llvm-project?rev=90722&view=rev
Log:
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.
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CGVtable.cpp
cfe/trunk/lib/CodeGen/CGVtable.h
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/test/CodeGenCXX/virt.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=90722&r1=90721&r2=90722&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sun Dec 6 16:01:30 2009
@@ -994,6 +994,102 @@
}
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());
Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=90722&r1=90721&r2=90722&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Sun Dec 6 16:01:30 2009
@@ -73,6 +73,7 @@
/// Methods - The methods, in vtable order.
typedef llvm::SmallVector<GlobalDecl, 16> MethodsVectorTy;
MethodsVectorTy Methods;
+ MethodsVectorTy OrigMethods;
public:
/// AddMethod - Add a method to the vtable methods.
@@ -82,6 +83,7 @@
MethodToIndexMap[GD] = Methods.size();
Methods.push_back(GD);
+ OrigMethods.push_back(GD);
}
/// OverrideMethod - Replace a method with another.
@@ -113,6 +115,10 @@
return true;
}
+ GlobalDecl getOrigMethod(uint64_t Index) const {
+ return OrigMethods[Index];
+ }
+
MethodsVectorTy::size_type size() const {
return Methods.size();
}
@@ -120,6 +126,7 @@
void clear() {
MethodToIndexMap.clear();
Methods.clear();
+ OrigMethods.clear();
}
GlobalDecl operator[](uint64_t Index) const {
@@ -135,6 +142,10 @@
typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
ThisAdjustmentsMapTy ThisAdjustments;
+ typedef std::vector<std::pair<std::pair<GlobalDecl, GlobalDecl>,
+ ThunkAdjustment> > SavedThisAdjustmentsVectorTy;
+ SavedThisAdjustmentsVectorTy SavedThisAdjustments;
+
/// BaseReturnTypes - Contains the base return types of methods who have been
/// overridden with methods whose return types require adjustment. Used for
/// generating covariant thunk information.
@@ -202,6 +213,9 @@
llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
{ return VBIndex; }
+ SavedThisAdjustmentsVectorTy &getSavedThisAdjustments()
+ { return SavedThisAdjustments; }
+
llvm::Constant *wrap(Index_t i) {
llvm::Constant *m;
m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
@@ -762,11 +776,17 @@
else
OGD = OMD;
- // FIXME: Explain why this is necessary!
+ // Check whether this is the method being overridden in this section of
+ // the vtable.
uint64_t Index;
if (!Methods.getIndex(OGD, Index))
continue;
+ // Get the original method, which we should be computing thunks, etc,
+ // against.
+ OGD = Methods.getOrigMethod(Index);
+ OMD = cast<CXXMethodDecl>(OGD.getDecl());
+
QualType ReturnType =
MD->getType()->getAs<FunctionType>()->getResultType();
QualType OverriddenReturnType =
@@ -777,10 +797,6 @@
OverriddenReturnType)) {
CanQualType &BaseReturnType = BaseReturnTypes[Index];
- // Get the canonical return type.
- CanQualType CanReturnType =
- CGM.getContext().getCanonicalType(ReturnType);
-
// Insert the base return type.
if (BaseReturnType.isNull())
BaseReturnType =
@@ -820,8 +836,12 @@
ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
VirtualAdjustment);
- if (!isPure && !ThisAdjustment.isEmpty())
+ if (!isPure && !ThisAdjustment.isEmpty()) {
ThisAdjustments[Index] = ThisAdjustment;
+ // FIXME: Might this end up inserting some false adjustments?
+ SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD),
+ ThisAdjustment));
+ }
return true;
}
@@ -882,10 +902,10 @@
if (!ReturnAdjustment.isEmpty()) {
// Build a covariant thunk.
CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment);
- Method = CGM.BuildCovariantThunk(MD, Extern, Adjustment);
+ Method = wrap(CGM.GetAddrOfCovariantThunk(GD, Adjustment));
} else if (!ThisAdjustment.isEmpty()) {
// Build a "regular" thunk.
- Method = CGM.BuildThunk(GD, Extern, ThisAdjustment);
+ Method = wrap(CGM.GetAddrOfThunk(GD, ThisAdjustment));
} else if (MD->isPure()) {
// We have a pure virtual method.
Method = getPureVirtualFn();
@@ -1048,6 +1068,32 @@
return I->second;
}
+ThunkAdjustment CGVtableInfo::getThisAdjustment(GlobalDecl GD,
+ GlobalDecl OGD) {
+ SavedThisAdjustmentsTy::iterator I =
+ SavedThisAdjustments.find(std::make_pair(GD, OGD));
+ if (I != SavedThisAdjustments.end())
+ return I->second;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
+ if (!SavedThisAdjustmentRecords.insert(RD).second)
+ return ThunkAdjustment();
+
+ VtableBuilder b(RD, RD, 0, CGM, false);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
+ b.GenerateVtableForBase(RD);
+ b.GenerateVtableForVBases(RD);
+
+ SavedThisAdjustments.insert(b.getSavedThisAdjustments().begin(),
+ b.getSavedThisAdjustments().end());
+
+ I = SavedThisAdjustments.find(std::make_pair(GD, OGD));
+ if (I != SavedThisAdjustments.end())
+ return I->second;
+
+ return ThunkAdjustment();
+}
+
int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase) {
ClassPairTy ClassPair(RD, VBase);
@@ -1416,5 +1462,17 @@
// Emit the data.
GenerateClassData(Linkage, RD);
+
+ for (CXXRecordDecl::method_iterator i = RD->method_begin(),
+ e = RD->method_end(); i != e; ++i) {
+ if ((*i)->isVirtual() && (*i)->hasInlineBody()) {
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
+ CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
+ CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
+ } else {
+ CGM.BuildThunksForVirtual(GlobalDecl(*i));
+ }
+ }
+ }
}
Modified: cfe/trunk/lib/CodeGen/CGVtable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.h?rev=90722&r1=90721&r2=90722&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.h (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.h Sun Dec 6 16:01:30 2009
@@ -15,6 +15,7 @@
#define CLANG_CODEGEN_CGVTABLE_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/GlobalVariable.h"
#include "GlobalDecl.h"
@@ -83,6 +84,11 @@
/// pointers in the vtable for a given record decl.
llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
+ typedef llvm::DenseMap<std::pair<GlobalDecl, GlobalDecl>,
+ ThunkAdjustment> SavedThisAdjustmentsTy;
+ SavedThisAdjustmentsTy SavedThisAdjustments;
+ llvm::DenseSet<const CXXRecordDecl*> SavedThisAdjustmentRecords;
+
/// getNumVirtualFunctionPointers - Return the number of virtual function
/// pointers in the vtable for a given record decl.
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
@@ -122,6 +128,8 @@
int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase);
+ ThunkAdjustment getThisAdjustment(GlobalDecl GD, GlobalDecl OGD);
+
/// getVtableAddressPoint - returns the address point of the vtable for the
/// given record decl.
/// FIXME: This should return a list of address points.
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=90722&r1=90721&r2=90722&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sun Dec 6 16:01:30 2009
@@ -621,8 +621,13 @@
Context.getSourceManager(),
"Generating code for declaration");
- if (isa<CXXMethodDecl>(D))
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
getVtableInfo().MaybeEmitVtable(GD);
+ if (MD->isVirtual() && MD->isOutOfLine() &&
+ (!isa<CXXDestructorDecl>(D) || GD.getDtorType() != Dtor_Base)) {
+ BuildThunksForVirtual(GD);
+ }
+ }
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
EmitCXXConstructor(CD, GD.getCtorType());
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=90722&r1=90721&r2=90722&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sun Dec 6 16:01:30 2009
@@ -223,6 +223,13 @@
/// non-class type.
llvm::Constant *GenerateRTTI(QualType Ty);
+ llvm::Constant *GetAddrOfThunk(GlobalDecl GD,
+ const ThunkAdjustment &ThisAdjustment);
+ llvm::Constant *GetAddrOfCovariantThunk(GlobalDecl GD,
+ const CovariantThunkAdjustment &ThisAdjustment);
+ void BuildThunksForVirtual(GlobalDecl GD);
+ void BuildThunksForVirtualRecursive(GlobalDecl GD, GlobalDecl BaseOGD);
+
/// BuildThunk - Build a thunk for the given method.
llvm::Constant *BuildThunk(GlobalDecl GD, bool Extern,
const ThunkAdjustment &ThisAdjustment);
Modified: cfe/trunk/test/CodeGenCXX/virt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virt.cpp?rev=90722&r1=90721&r2=90722&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/virt.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virt.cpp Sun Dec 6 16:01:30 2009
@@ -768,7 +768,7 @@
// FIXME: This is the wrong thunk, but until these issues are fixed, better
// than nothing.
-// CHECK-LPLL64:define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*) {
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*)
// CHECK-LPLL64:entry:
// CHECK-LPLL64: %retval = alloca %class.test8_D*
// CHECK-LPLL64: %.addr = alloca %class.test8_D*
@@ -790,7 +790,7 @@
// CHECK-LPLL64: ret %class.test8_D* %10
// CHECK-LPLL64:}
-// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D*) {
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D*)
// CHECK-LPLL64:entry:
// CHECK-LPLL64: %retval = alloca %class.test8_D*
// CHECK-LPLL64: %.addr = alloca %class.test8_D*
More information about the cfe-commits
mailing list