diff options
author | Anders Carlsson <andersca@mac.com> | 2009-12-03 02:32:59 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-12-03 02:32:59 +0000 |
commit | 891bb4b6a51346838e15c4c381d782e800fb3390 (patch) | |
tree | 95390bccff3dffa9f90c18d3084c3393ac790724 /lib/CodeGen/CGVtable.cpp | |
parent | bc0e3396c441015a77ccd18bf507fd8c784c76f5 (diff) |
Delay computing the return adjustments for covariant thunks until when they are added to the vtable.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90396 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 211 |
1 files changed, 113 insertions, 98 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index f38e034055..edcd14c96e 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -281,9 +281,20 @@ public: Thunks.erase(i); } - - CovariantThunkAdjustment Adjustment(ThisAdjustment, - Thunk.ReturnAdjustment); + + // Construct the return adjustment. + QualType DerivedType = + MD->getType()->getAs<FunctionType>()->getResultType(); + + int64_t NonVirtualAdjustment = + getNVOffset(Thunk.ReturnType, DerivedType) / 8; + + int64_t VirtualAdjustment = + getVbaseOffset(Thunk.ReturnType, DerivedType); + + ThunkAdjustment ReturnAdjustment(NonVirtualAdjustment, VirtualAdjustment); + + CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment); submethods[Index] = CGM.BuildCovariantThunk(MD, Extern, Adjustment); } CovariantThunks.clear(); @@ -670,6 +681,83 @@ public: }; } // end anonymous namespace +/// TypeConversionRequiresAdjustment - Returns whether conversion from a +/// derived type to a base type requires adjustment. +static bool +TypeConversionRequiresAdjustment(ASTContext &Ctx, + const CXXRecordDecl *DerivedDecl, + const CXXRecordDecl *BaseDecl) { + CXXBasePaths Paths(/*FindAmbiguities=*/false, + /*RecordPaths=*/true, /*DetectVirtual=*/true); + if (!const_cast<CXXRecordDecl *>(DerivedDecl)-> + isDerivedFrom(const_cast<CXXRecordDecl *>(BaseDecl), Paths)) { + assert(false && "Class must be derived from the passed in base class!"); + return false; + } + + // If we found a virtual base we always want to require adjustment. + if (Paths.getDetectedVirtual()) + return true; + + const CXXBasePath &Path = Paths.front(); + + for (size_t Start = 0, End = Path.size(); Start != End; ++Start) { + const CXXBasePathElement &Element = Path[Start]; + + // Check the base class offset. + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Element.Class); + + const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>(); + const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl()); + + if (Layout.getBaseClassOffset(Base) != 0) { + // This requires an adjustment. + return true; + } + } + + return false; +} + +static bool +TypeConversionRequiresAdjustment(ASTContext &Ctx, + QualType DerivedType, QualType BaseType) { + // Canonicalize the types. + QualType CanDerivedType = Ctx.getCanonicalType(DerivedType); + QualType CanBaseType = Ctx.getCanonicalType(BaseType); + + assert(CanDerivedType->getTypeClass() == CanBaseType->getTypeClass() && + "Types must have same type class!"); + + if (CanDerivedType == CanBaseType) { + // No adjustment needed. + return false; + } + + if (const ReferenceType *RT = dyn_cast<ReferenceType>(CanDerivedType)) { + CanDerivedType = RT->getPointeeType(); + CanBaseType = cast<ReferenceType>(CanBaseType)->getPointeeType(); + } else if (const PointerType *PT = dyn_cast<PointerType>(CanDerivedType)) { + CanDerivedType = PT->getPointeeType(); + CanBaseType = cast<PointerType>(CanBaseType)->getPointeeType(); + } else { + assert(false && "Unexpected return type!"); + } + + if (CanDerivedType == CanBaseType) { + // No adjustment needed. + return false; + } + + const CXXRecordDecl *DerivedDecl = + cast<CXXRecordDecl>(cast<RecordType>(CanDerivedType)->getDecl()); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(cast<RecordType>(CanBaseType)->getDecl()); + + return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl); +} + bool VtableBuilder::OverrideMethod(GlobalDecl GD, llvm::Constant *m, bool MorallyVirtual, Index_t OverrideOffset, Index_t Offset, int64_t CurrentVBaseOffset) { @@ -704,24 +792,29 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, llvm::Constant *m, // FIXME: begin_overridden_methods might be too lax, covariance */ if (submethods[i] != om) continue; - QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType(); - CanQualType oret = CGM.getContext().getCanonicalType(nc_oret); - QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType(); - CanQualType ret = CGM.getContext().getCanonicalType(nc_ret); - if (oret != ret) { - // FIXME: calculate offsets for covariance - CovariantThunksMapTy::iterator it = CovariantThunks.find(i); - if (it != CovariantThunks.end()) { - oret = it->second.ReturnType; - CovariantThunks.erase(it); - } - // FIXME: Double check oret - Index_t nv = getNVOffset(oret, ret)/8; - CovariantThunks[i] = - CovariantThunk(GD, ThunkAdjustment(nv, getVbaseOffset(oret, ret)), - oret); - + + QualType ReturnType = + MD->getType()->getAs<FunctionType>()->getResultType(); + QualType OverriddenReturnType = + OMD->getType()->getAs<FunctionType>()->getResultType(); + + // Check if we need a return type adjustment. + if (TypeConversionRequiresAdjustment(CGM.getContext(), ReturnType, + OverriddenReturnType)) { + CovariantThunk &Adjustment = CovariantThunks[i]; + + // Get the canonical return type. + CanQualType CanReturnType = + CGM.getContext().getCanonicalType(ReturnType); + + // Insert the base return type. + if (Adjustment.ReturnType.isNull()) + Adjustment.ReturnType = + CGM.getContext().getCanonicalType(OverriddenReturnType); + + Adjustment.GD = GD; } + Index[GD] = i; submethods[i] = m; if (isPure) @@ -779,84 +872,6 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, llvm::Constant *m, return false; } - -/// TypeConversionRequiresAdjustment - Returns whether conversion from a -/// derived type to a base type requires adjustment. -static bool -TypeConversionRequiresAdjustment(ASTContext &Ctx, - const CXXRecordDecl *DerivedDecl, - const CXXRecordDecl *BaseDecl) { - CXXBasePaths Paths(/*FindAmbiguities=*/false, - /*RecordPaths=*/true, /*DetectVirtual=*/true); - if (!const_cast<CXXRecordDecl *>(DerivedDecl)-> - isDerivedFrom(const_cast<CXXRecordDecl *>(BaseDecl), Paths)) { - assert(false && "Class must be derived from the passed in base class!"); - return false; - } - - // If we found a virtual base we always want to require adjustment. - if (Paths.getDetectedVirtual()) - return true; - - const CXXBasePath &Path = Paths.front(); - - for (size_t Start = 0, End = Path.size(); Start != End; ++Start) { - const CXXBasePathElement &Element = Path[Start]; - - // Check the base class offset. - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Element.Class); - - const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>(); - const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl()); - - if (Layout.getBaseClassOffset(Base) != 0) { - // This requires an adjustment. - return true; - } - } - - return false; -} - -static bool -TypeConversionRequiresAdjustment(ASTContext &Ctx, - QualType DerivedType, QualType BaseType) { - // Canonicalize the types. - QualType CanDerivedType = Ctx.getCanonicalType(DerivedType); - QualType CanBaseType = Ctx.getCanonicalType(BaseType); - - assert(CanDerivedType->getTypeClass() == CanBaseType->getTypeClass() && - "Types must have same type class!"); - - if (CanDerivedType == CanBaseType) { - // No adjustment needed. - return false; - } - - if (const ReferenceType *RT = dyn_cast<ReferenceType>(CanDerivedType)) { - CanDerivedType = RT->getPointeeType(); - CanBaseType = cast<ReferenceType>(CanBaseType)->getPointeeType(); - } else if (const PointerType *PT = dyn_cast<PointerType>(CanDerivedType)) { - CanDerivedType = PT->getPointeeType(); - CanBaseType = cast<PointerType>(CanBaseType)->getPointeeType(); - } else { - assert(false && "Unexpected return type!"); - } - - if (CanDerivedType == CanBaseType) { - // No adjustment needed. - return false; - } - - const CXXRecordDecl *DerivedDecl = - cast<CXXRecordDecl>(cast<RecordType>(CanDerivedType)->getDecl()); - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(cast<RecordType>(CanBaseType)->getDecl()); - - return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl); -} - void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) { // Itanium C++ ABI 2.5.2: |