diff options
author | Anders Carlsson <andersca@mac.com> | 2010-03-30 03:43:47 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-03-30 03:43:47 +0000 |
commit | bfb7a1d6eba6714bd71db921092332da65b774c0 (patch) | |
tree | 24f5959442b15279230b022c4fad6e2dac0eb585 /lib/CodeGen/CGVtable.cpp | |
parent | 9dc338ac74e7855293a60812bd5780a52f141f52 (diff) |
Remove the old vtable layout code.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99869 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 1158 |
1 files changed, 0 insertions, 1158 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 30c9efc91b..841281cdc4 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -2373,1081 +2373,6 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) { } -namespace { -class OldVtableBuilder { -public: - /// Index_t - Vtable index type. - typedef uint64_t Index_t; - typedef std::vector<std::pair<GlobalDecl, - std::pair<GlobalDecl, ThunkAdjustment> > > - SavedAdjustmentsVectorTy; - typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; - -private: - - // VtableComponents - The components of the vtable being built. - typedef llvm::SmallVector<llvm::Constant *, 64> VtableComponentsVectorTy; - VtableComponentsVectorTy VtableComponents; - - const bool BuildVtable; - - llvm::Type *Ptr8Ty; - - /// MostDerivedClass - The most derived class that this vtable is being - /// built for. - const CXXRecordDecl *MostDerivedClass; - - /// LayoutClass - The most derived class used for virtual base layout - /// information. - const CXXRecordDecl *LayoutClass; - /// LayoutOffset - The offset for Class in LayoutClass. - uint64_t LayoutOffset; - /// BLayout - Layout for the most derived class that this vtable is being - /// built for. - const ASTRecordLayout &BLayout; - llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary; - llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase; - llvm::Constant *rtti; - llvm::LLVMContext &VMContext; - CodeGenModule &CGM; // Per-module state. - - llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall; - llvm::DenseMap<GlobalDecl, Index_t> VCallOffset; - llvm::DenseMap<GlobalDecl, Index_t> VCallOffsetForVCall; - // This is the offset to the nearest virtual base - llvm::DenseMap<const CXXMethodDecl *, Index_t> NonVirtualOffset; - llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex; - - /// PureVirtualFunction - Points to __cxa_pure_virtual. - llvm::Constant *PureVirtualFn; - - /// VtableMethods - A data structure for keeping track of methods in a vtable. - /// Can add methods, override methods and iterate in vtable order. - class VtableMethods { - // MethodToIndexMap - Maps from a global decl to the index it has in the - // Methods vector. - llvm::DenseMap<GlobalDecl, uint64_t> MethodToIndexMap; - - /// 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. - void AddMethod(GlobalDecl GD) { - assert(!MethodToIndexMap.count(GD) && - "Method has already been added!"); - - MethodToIndexMap[GD] = Methods.size(); - Methods.push_back(GD); - OrigMethods.push_back(GD); - } - - /// OverrideMethod - Replace a method with another. - void OverrideMethod(GlobalDecl OverriddenGD, GlobalDecl GD) { - llvm::DenseMap<GlobalDecl, uint64_t>::iterator i - = MethodToIndexMap.find(OverriddenGD); - assert(i != MethodToIndexMap.end() && "Did not find entry!"); - - // Get the index of the old decl. - uint64_t Index = i->second; - - // Replace the old decl with the new decl. - Methods[Index] = GD; - - // And add the new. - MethodToIndexMap[GD] = Index; - } - - /// getIndex - Gives the index of a passed in GlobalDecl. Returns false if - /// the index couldn't be found. - bool getIndex(GlobalDecl GD, uint64_t &Index) const { - llvm::DenseMap<GlobalDecl, uint64_t>::const_iterator i - = MethodToIndexMap.find(GD); - - if (i == MethodToIndexMap.end()) - return false; - - Index = i->second; - return true; - } - - GlobalDecl getOrigMethod(uint64_t Index) const { - return OrigMethods[Index]; - } - - MethodsVectorTy::size_type size() const { - return Methods.size(); - } - - void clear() { - MethodToIndexMap.clear(); - Methods.clear(); - OrigMethods.clear(); - } - - GlobalDecl operator[](uint64_t Index) const { - return Methods[Index]; - } - }; - - /// Methods - The vtable methods we're currently building. - VtableMethods Methods; - - /// ThisAdjustments - For a given index in the vtable, contains the 'this' - /// pointer adjustment needed for a method. - typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy; - ThisAdjustmentsMapTy ThisAdjustments; - - SavedAdjustmentsVectorTy SavedAdjustments; - - /// 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. - typedef llvm::DenseMap<uint64_t, CanQualType> BaseReturnTypesMapTy; - BaseReturnTypesMapTy BaseReturnTypes; - - std::vector<Index_t> VCalls; - - typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t; - // subAddressPoints - Used to hold the AddressPoints (offsets) into the built - // vtable for use in computing the initializers for the VTT. - llvm::DenseMap<CtorVtable_t, int64_t> &subAddressPoints; - - /// AddressPoints - Address points for this vtable. - AddressPointsMapTy& AddressPoints; - - typedef CXXRecordDecl::method_iterator method_iter; - const uint32_t LLVMPointerWidth; - Index_t extra; - typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t; - static llvm::DenseMap<CtorVtable_t, int64_t>& - AllocAddressPoint(CodeGenModule &cgm, const CXXRecordDecl *l, - const CXXRecordDecl *c) { - CodeGenVTables::AddrMap_t *&oref = cgm.getVTables().OldAddressPoints[l]; - if (oref == 0) - oref = new CodeGenVTables::AddrMap_t; - - llvm::DenseMap<CtorVtable_t, int64_t> *&ref = (*oref)[c]; - if (ref == 0) - ref = new llvm::DenseMap<CtorVtable_t, int64_t>; - return *ref; - } - - bool DclIsSame(const FunctionDecl *New, const FunctionDecl *Old) { - FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); - FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); - - // C++ [temp.fct]p2: - // A function template can be overloaded with other function templates - // and with normal (non-template) functions. - if ((OldTemplate == 0) != (NewTemplate == 0)) - return false; - - // Is the function New an overload of the function Old? - QualType OldQType = CGM.getContext().getCanonicalType(Old->getType()); - QualType NewQType = CGM.getContext().getCanonicalType(New->getType()); - - // Compare the signatures (C++ 1.3.10) of the two functions to - // determine whether they are overloads. If we find any mismatch - // in the signature, they are overloads. - - // If either of these functions is a K&R-style function (no - // prototype), then we consider them to have matching signatures. - if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) || - isa<FunctionNoProtoType>(NewQType.getTypePtr())) - return true; - - FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType); - FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType); - - // The signature of a function includes the types of its - // parameters (C++ 1.3.10), which includes the presence or absence - // of the ellipsis; see C++ DR 357). - if (OldQType != NewQType && - (OldType->getNumArgs() != NewType->getNumArgs() || - OldType->isVariadic() != NewType->isVariadic() || - !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(), - NewType->arg_type_begin()))) - return false; - -#if 0 - // C++ [temp.over.link]p4: - // The signature of a function template consists of its function - // signature, its return type and its template parameter list. The names - // of the template parameters are significant only for establishing the - // relationship between the template parameters and the rest of the - // signature. - // - // We check the return type and template parameter lists for function - // templates first; the remaining checks follow. - if (NewTemplate && - (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), - OldTemplate->getTemplateParameters(), - TPL_TemplateMatch) || - OldType->getResultType() != NewType->getResultType())) - return false; -#endif - - // If the function is a class member, its signature includes the - // cv-qualifiers (if any) on the function itself. - // - // As part of this, also check whether one of the member functions - // is static, in which case they are not overloads (C++ - // 13.1p2). While not part of the definition of the signature, - // this check is important to determine whether these functions - // can be overloaded. - const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); - const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); - if (OldMethod && NewMethod && - !OldMethod->isStatic() && !NewMethod->isStatic() && - OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers()) - return false; - - // The signatures match; this is not an overload. - return true; - } - - typedef llvm::DenseMap<const CXXMethodDecl *, const CXXMethodDecl*> - ForwardUnique_t; - ForwardUnique_t ForwardUnique; - llvm::DenseMap<const CXXMethodDecl*, const CXXMethodDecl*> UniqueOverrider; - - void BuildUniqueOverrider(const CXXMethodDecl *U, const CXXMethodDecl *MD) { - const CXXMethodDecl *PrevU = UniqueOverrider[MD]; - assert(U && "no unique overrider"); - if (PrevU == U) - return; - if (PrevU != U && PrevU != 0) { - // If already set, note the two sets as the same - if (0) - printf("%s::%s same as %s::%s\n", - PrevU->getParent()->getNameAsString().c_str(), - PrevU->getNameAsString().c_str(), - U->getParent()->getNameAsString().c_str(), - U->getNameAsString().c_str()); - ForwardUnique[PrevU] = U; - return; - } - - // Not set, set it now - if (0) - printf("marking %s::%s %p override as %s::%s\n", - MD->getParent()->getNameAsString().c_str(), - MD->getNameAsString().c_str(), - (void*)MD, - U->getParent()->getNameAsString().c_str(), - U->getNameAsString().c_str()); - UniqueOverrider[MD] = U; - - for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(), - me = MD->end_overridden_methods(); mi != me; ++mi) { - BuildUniqueOverrider(U, *mi); - } - } - - void BuildUniqueOverriders(const CXXRecordDecl *RD) { - if (0) printf("walking %s\n", RD->getNameAsCString()); - for (CXXRecordDecl::method_iterator i = RD->method_begin(), - e = RD->method_end(); i != e; ++i) { - const CXXMethodDecl *MD = *i; - if (!MD->isVirtual()) - continue; - - if (UniqueOverrider[MD] == 0) { - // Only set this, if it hasn't been set yet. - BuildUniqueOverrider(MD, MD); - if (0) - printf("top set is %s::%s %p\n", - MD->getParent()->getNameAsString().c_str(), - MD->getNameAsString().c_str(), - (void*)MD); - ForwardUnique[MD] = MD; - } - } - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - BuildUniqueOverriders(Base); - } - } - - static int DclCmp(const void *p1, const void *p2) { - const CXXMethodDecl *MD1 = *(const CXXMethodDecl *const *)p1; - const CXXMethodDecl *MD2 = *(const CXXMethodDecl *const *)p2; - - return (DeclarationName::compare(MD1->getDeclName(), MD2->getDeclName())); - } - - void MergeForwarding() { - typedef llvm::SmallVector<const CXXMethodDecl *, 100> A_t; - A_t A; - for (ForwardUnique_t::iterator I = ForwardUnique.begin(), - E = ForwardUnique.end(); I != E; ++I) { - if (I->first == I->second) - // Only add the roots of all trees - A.push_back(I->first); - } - llvm::array_pod_sort(A.begin(), A.end(), DclCmp); - for (A_t::iterator I = A.begin(), - E = A.end(); I != E; ++I) { - A_t::iterator J = I; - while (++J != E && DclCmp(I, J) == 0) - if (DclIsSame(*I, *J)) { - if (0) printf("connecting %s\n", (*I)->getNameAsString().c_str()); - ForwardUnique[*J] = *I; - } - } - } - - const CXXMethodDecl *getUnique(const CXXMethodDecl *MD) { - const CXXMethodDecl *U = UniqueOverrider[MD]; - assert(U && "unique overrider not found"); - while (ForwardUnique.count(U)) { - const CXXMethodDecl *NU = ForwardUnique[U]; - if (NU == U) break; - U = NU; - } - return U; - } - - GlobalDecl getUnique(GlobalDecl GD) { - const CXXMethodDecl *Unique = getUnique(cast<CXXMethodDecl>(GD.getDecl())); - - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Unique)) - return GlobalDecl(CD, GD.getCtorType()); - - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(Unique)) - return GlobalDecl(DD, GD.getDtorType()); - - return Unique; - } - - /// getPureVirtualFn - Return the __cxa_pure_virtual function. - llvm::Constant* getPureVirtualFn() { - if (!PureVirtualFn) { - const llvm::FunctionType *Ty = - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), - /*isVarArg=*/false); - PureVirtualFn = wrap(CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual")); - } - - return PureVirtualFn; - } - -public: - OldVtableBuilder(const CXXRecordDecl *MostDerivedClass, - const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm, - bool build, AddressPointsMapTy& AddressPoints) - : BuildVtable(build), MostDerivedClass(MostDerivedClass), LayoutClass(l), - LayoutOffset(lo), BLayout(cgm.getContext().getASTRecordLayout(l)), - rtti(0), VMContext(cgm.getModule().getContext()),CGM(cgm), - PureVirtualFn(0), - subAddressPoints(AllocAddressPoint(cgm, l, MostDerivedClass)), - AddressPoints(AddressPoints), - LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) - { - Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); - if (BuildVtable) { - QualType ClassType = CGM.getContext().getTagDeclType(MostDerivedClass); - rtti = CGM.GetAddrOfRTTIDescriptor(ClassType); - } - BuildUniqueOverriders(MostDerivedClass); - MergeForwarding(); - } - - // getVtableComponents - Returns a reference to the vtable components. - const VtableComponentsVectorTy &getVtableComponents() const { - return VtableComponents; - } - - llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getVBIndex() - { return VBIndex; } - - SavedAdjustmentsVectorTy &getSavedAdjustments() - { return SavedAdjustments; } - - llvm::Constant *wrap(Index_t i) { - llvm::Constant *m; - m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i); - return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); - } - - llvm::Constant *wrap(llvm::Constant *m) { - return llvm::ConstantExpr::getBitCast(m, Ptr8Ty); - } - -//#define D1(x) -#define D1(X) do { if (getenv("CLANG_VTABLE_DEBUG")) { X; } } while (0) - - void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset, - bool updateVBIndex, Index_t current_vbindex) { - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - Index_t next_vbindex = current_vbindex; - if (i->isVirtual() && !SeenVBase.count(Base)) { - SeenVBase.insert(Base); - if (updateVBIndex) { - next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8) - - 3*LLVMPointerWidth/8); - VBIndex[Base] = next_vbindex; - } - int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8; - VCalls.push_back((0?700:0) + BaseOffset); - D1(printf(" vbase for %s at %d delta %d most derived %s\n", - Base->getNameAsCString(), - (int)-VCalls.size()-3, (int)BaseOffset, - MostDerivedClass->getNameAsCString())); - } - // We also record offsets for non-virtual bases to closest enclosing - // virtual base. We do this so that we don't have to search - // for the nearst virtual base class when generating thunks. - if (updateVBIndex && VBIndex.count(Base) == 0) - VBIndex[Base] = next_vbindex; - GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex); - } - } - - void StartNewTable() { - SeenVBase.clear(); - } - - Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B, - Index_t Offset = 0) { - - if (B == D) - return Offset; - - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D); - for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(), - e = D->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - int64_t BaseOffset = 0; - if (!i->isVirtual()) - BaseOffset = Offset + Layout.getBaseClassOffset(Base); - int64_t o = getNVOffset_1(Base, B, BaseOffset); - if (o >= 0) - return o; - } - - return -1; - } - - /// getNVOffset - Returns the non-virtual offset for the given (B) base of the - /// derived class D. - Index_t getNVOffset(QualType qB, QualType qD) { - qD = qD->getPointeeType(); - qB = qB->getPointeeType(); - CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl()); - CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl()); - int64_t o = getNVOffset_1(D, B); - if (o >= 0) - return o; - - assert(false && "FIXME: non-virtual base not found"); - return 0; - } - - /// getVbaseOffset - Returns the index into the vtable for the virtual base - /// offset for the given (B) virtual base of the derived class D. - Index_t getVbaseOffset(QualType qB, QualType qD) { - qD = qD->getPointeeType(); - qB = qB->getPointeeType(); - CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl()); - CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl()); - if (D != MostDerivedClass) - return CGM.getVTables().getVirtualBaseOffsetOffset(D, B); - llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i; - i = VBIndex.find(B); - if (i != VBIndex.end()) - return i->second; - - assert(false && "FIXME: Base not found"); - return 0; - } - - bool OverrideMethod(GlobalDecl GD, bool MorallyVirtual, - Index_t OverrideOffset, Index_t Offset, - int64_t CurrentVBaseOffset); - - /// AppendMethods - Append the current methods to the vtable. - void AppendMethodsToVtable(); - - llvm::Constant *WrapAddrOf(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - - const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD); - - return wrap(CGM.GetAddrOfFunction(GD, Ty)); - } - - void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset, - int64_t CurrentVBaseOffset) { - for (Path_t::reverse_iterator i = Path->rbegin(), - e = Path->rend(); i != e; ++i) { - const CXXRecordDecl *RD = i->first; - int64_t OverrideOffset = i->second; - for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; - ++mi) { - const CXXMethodDecl *MD = *mi; - - if (!MD->isVirtual()) - continue; - - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - // Override both the complete and the deleting destructor. - GlobalDecl CompDtor(DD, Dtor_Complete); - OverrideMethod(CompDtor, MorallyVirtual, OverrideOffset, Offset, - CurrentVBaseOffset); - - GlobalDecl DeletingDtor(DD, Dtor_Deleting); - OverrideMethod(DeletingDtor, MorallyVirtual, OverrideOffset, Offset, - CurrentVBaseOffset); - } else { - OverrideMethod(MD, MorallyVirtual, OverrideOffset, Offset, - CurrentVBaseOffset); - } - } - } - } - - void AddMethod(const GlobalDecl GD, bool MorallyVirtual, Index_t Offset, - int64_t CurrentVBaseOffset) { - // If we can find a previously allocated slot for this, reuse it. - if (OverrideMethod(GD, MorallyVirtual, Offset, Offset, - CurrentVBaseOffset)) - return; - - D1(printf(" vfn for %s at %d\n", - dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsString().c_str(), - (int)Methods.size())); - - // We didn't find an entry in the vtable that we could use, add a new - // entry. - Methods.AddMethod(GD); - - VCallOffset[GD] = Offset/8 - CurrentVBaseOffset/8; - - if (MorallyVirtual) { - GlobalDecl UGD = getUnique(GD); - const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl()); - - assert(UMD && "final overrider not found"); - - Index_t &idx = VCall[UMD]; - // Allocate the first one, after that, we reuse the previous one. - if (idx == 0) { - VCallOffsetForVCall[UGD] = Offset/8; - NonVirtualOffset[UMD] = Offset/8 - CurrentVBaseOffset/8; - idx = VCalls.size()+1; - VCalls.push_back(Offset/8 - CurrentVBaseOffset/8); - D1(printf(" vcall for %s at %d with delta %d\n", - dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsString().c_str(), - (int)-VCalls.size()-3, (int)VCalls[idx-1])); - } - } - } - - void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual, - Index_t Offset, int64_t CurrentVBaseOffset) { - for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; - ++mi) { - const CXXMethodDecl *MD = *mi; - if (!MD->isVirtual()) - continue; - - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - // For destructors, add both the complete and the deleting destructor - // to the vtable. - AddMethod(GlobalDecl(DD, Dtor_Complete), MorallyVirtual, Offset, - CurrentVBaseOffset); - AddMethod(GlobalDecl(DD, Dtor_Deleting), MorallyVirtual, Offset, - CurrentVBaseOffset); - } else - AddMethod(MD, MorallyVirtual, Offset, CurrentVBaseOffset); - } - } - - void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout, - const CXXRecordDecl *PrimaryBase, - bool PrimaryBaseWasVirtual, bool MorallyVirtual, - int64_t Offset, int64_t CurrentVBaseOffset, - Path_t *Path) { - Path->push_back(std::make_pair(RD, Offset)); - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - if (i->isVirtual()) - continue; - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - uint64_t o = Offset + Layout.getBaseClassOffset(Base); - StartNewTable(); - GenerateVtableForBase(Base, o, MorallyVirtual, false, - true, Base == PrimaryBase && !PrimaryBaseWasVirtual, - CurrentVBaseOffset, Path); - } - Path->pop_back(); - } - -// #define D(X) do { X; } while (0) -#define D(X) - - void insertVCalls(int InsertionPoint) { - D1(printf("============= combining vbase/vcall\n")); - D(VCalls.insert(VCalls.begin(), 673)); - D(VCalls.push_back(672)); - - VtableComponents.insert(VtableComponents.begin() + InsertionPoint, - VCalls.size(), 0); - if (BuildVtable) { - // The vcalls come first... - for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(), - e = VCalls.rend(); - i != e; ++i) - VtableComponents[InsertionPoint++] = wrap((0?600:0) + *i); - } - VCalls.clear(); - VCall.clear(); - VCallOffsetForVCall.clear(); - VCallOffset.clear(); - NonVirtualOffset.clear(); - } - - void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset, - Index_t AddressPoint) { - D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n", - RD->getNameAsCString(), MostDerivedClass->getNameAsCString(), - LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint)); - subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint; - AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint; - - // Now also add the address point for all our primary bases. - while (1) { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - RD = Layout.getPrimaryBase(); - const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); - // FIXME: Double check this. - if (RD == 0) - break; - if (PrimaryBaseWasVirtual && - BLayout.getVBaseClassOffset(RD) != Offset) - break; - D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n", - RD->getNameAsCString(), MostDerivedClass->getNameAsCString(), - LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint)); - subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint; - AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint; - } - } - - - void FinishGenerateVtable(const CXXRecordDecl *RD, - const ASTRecordLayout &Layout, - const CXXRecordDecl *PrimaryBase, - bool ForNPNVBases, bool WasPrimaryBase, - bool PrimaryBaseWasVirtual, - bool MorallyVirtual, int64_t Offset, - bool ForVirtualBase, int64_t CurrentVBaseOffset, - Path_t *Path) { - bool alloc = false; - if (Path == 0) { - alloc = true; - Path = new Path_t; - } - - StartNewTable(); - extra = 0; - Index_t AddressPoint = 0; - int VCallInsertionPoint = 0; - if (!ForNPNVBases || !WasPrimaryBase) { - bool DeferVCalls = MorallyVirtual || ForVirtualBase; - VCallInsertionPoint = VtableComponents.size(); - if (!DeferVCalls) { - insertVCalls(VCallInsertionPoint); - } else - // FIXME: just for extra, or for all uses of VCalls.size post this? - extra = -VCalls.size(); - - // Add the offset to top. - VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0); - - // Add the RTTI information. - VtableComponents.push_back(rtti); - - AddressPoint = VtableComponents.size(); - - AppendMethodsToVtable(); - } - - // and then the non-virtual bases. - NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, - MorallyVirtual, Offset, CurrentVBaseOffset, Path); - - if (ForVirtualBase) { - // FIXME: We're adding to VCalls in callers, we need to do the overrides - // in the inner part, so that we know the complete set of vcalls during - // the build and don't have to insert into methods. Saving out the - // AddressPoint here, would need to be fixed, if we didn't do that. Also - // retroactively adding vcalls for overrides later wind up in the wrong - // place, the vcall slot has to be alloted during the walk of the base - // when the function is first introduces. - AddressPoint += VCalls.size(); - insertVCalls(VCallInsertionPoint); - } - - if (!ForNPNVBases || !WasPrimaryBase) - AddAddressPoints(RD, Offset, AddressPoint); - - if (alloc) { - delete Path; - } - } - - void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset, - bool updateVBIndex, Index_t current_vbindex, - int64_t CurrentVBaseOffset) { - if (!RD->isDynamicClass()) - return; - - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); - - // vtables are composed from the chain of primaries. - if (PrimaryBase && !PrimaryBaseWasVirtual) { - D1(printf(" doing primaries for %s most derived %s\n", - RD->getNameAsCString(), MostDerivedClass->getNameAsCString())); - Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset, - updateVBIndex, current_vbindex, CurrentVBaseOffset); - } - - D1(printf(" doing vcall entries for %s most derived %s\n", - RD->getNameAsCString(), MostDerivedClass->getNameAsCString())); - - // And add the virtuals for the class to the primary vtable. - AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset); - } - - void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset, - bool updateVBIndex, Index_t current_vbindex, - bool RDisVirtualBase, int64_t CurrentVBaseOffset, - bool bottom) { - if (!RD->isDynamicClass()) - return; - - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); - - // vtables are composed from the chain of primaries. - if (PrimaryBase) { - int BaseCurrentVBaseOffset = CurrentVBaseOffset; - if (PrimaryBaseWasVirtual) { - IndirectPrimary.insert(PrimaryBase); - BaseCurrentVBaseOffset = BLayout.getVBaseClassOffset(PrimaryBase); - } - - D1(printf(" doing primaries for %s most derived %s\n", - RD->getNameAsCString(), MostDerivedClass->getNameAsCString())); - - VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset, - updateVBIndex, current_vbindex, PrimaryBaseWasVirtual, - BaseCurrentVBaseOffset, false); - } - - D1(printf(" doing vbase entries for %s most derived %s\n", - RD->getNameAsCString(), MostDerivedClass->getNameAsCString())); - GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex); - - if (RDisVirtualBase || bottom) { - Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex, - CurrentVBaseOffset); - } - } - - void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0, - bool MorallyVirtual = false, - bool ForVirtualBase = false, - bool ForNPNVBases = false, - bool WasPrimaryBase = true, - int CurrentVBaseOffset = 0, - Path_t *Path = 0) { - if (!RD->isDynamicClass()) - return; - - // Construction vtable don't need parts that have no virtual bases and - // aren't morally virtual. - if ((LayoutClass != MostDerivedClass) && - RD->getNumVBases() == 0 && !MorallyVirtual) - return; - - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); - - extra = 0; - D1(printf("building entries for base %s most derived %s\n", - RD->getNameAsCString(), MostDerivedClass->getNameAsCString())); - - if (ForVirtualBase) - extra = VCalls.size(); - - if (!ForNPNVBases || !WasPrimaryBase) { - VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, - ForVirtualBase, CurrentVBaseOffset, true); - - if (Path) - OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset); - } - - FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase, - PrimaryBaseWasVirtual, MorallyVirtual, Offset, - ForVirtualBase, CurrentVBaseOffset, Path); - } - - void GenerateVtableForVBases(const CXXRecordDecl *RD, - int64_t Offset = 0, - Path_t *Path = 0) { - bool alloc = false; - if (Path == 0) { - alloc = true; - Path = new Path_t; - } - // FIXME: We also need to override using all paths to a virtual base, - // right now, we just process the first path - Path->push_back(std::make_pair(RD, Offset)); - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (i->isVirtual() && !IndirectPrimary.count(Base)) { - // Mark it so we don't output it twice. - IndirectPrimary.insert(Base); - StartNewTable(); - VCall.clear(); - int64_t BaseOffset = BLayout.getVBaseClassOffset(Base); - int64_t CurrentVBaseOffset = BaseOffset; - D1(printf("vtable %s virtual base %s\n", - MostDerivedClass->getNameAsCString(), Base->getNameAsCString())); - GenerateVtableForBase(Base, BaseOffset, true, true, false, - true, CurrentVBaseOffset, Path); - } - int64_t BaseOffset; - if (i->isVirtual()) - BaseOffset = BLayout.getVBaseClassOffset(Base); - else { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - BaseOffset = Offset + Layout.getBaseClassOffset(Base); - } - - if (Base->getNumVBases()) { - GenerateVtableForVBases(Base, BaseOffset, Path); - } - } - Path->pop_back(); - if (alloc) - delete Path; - } -}; -} // end anonymous namespace - -bool OldVtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual, - Index_t OverrideOffset, Index_t Offset, - int64_t CurrentVBaseOffset) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - - const bool isPure = MD->isPure(); - - // FIXME: Should OverrideOffset's be Offset? - - for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(), - e = MD->end_overridden_methods(); mi != e; ++mi) { - GlobalDecl OGD; - GlobalDecl OGD2; - - const CXXMethodDecl *OMD = *mi; - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD)) - OGD = GlobalDecl(DD, GD.getDtorType()); - else - OGD = OMD; - - // Check whether this is the method being overridden in this section of - // the vtable. - uint64_t Index; - if (!Methods.getIndex(OGD, Index)) - continue; - - OGD2 = OGD; - - // 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 = - OMD->getType()->getAs<FunctionType>()->getResultType(); - - // Check if we need a return type adjustment. - if (!ComputeReturnAdjustmentBaseOffset(CGM.getContext(), MD, - OMD).isEmpty()) { - CanQualType &BaseReturnType = BaseReturnTypes[Index]; - - // Insert the base return type. - if (BaseReturnType.isNull()) - BaseReturnType = - CGM.getContext().getCanonicalType(OverriddenReturnType); - } - - Methods.OverrideMethod(OGD, GD); - - GlobalDecl UGD = getUnique(GD); - const CXXMethodDecl *UMD = cast<CXXMethodDecl>(UGD.getDecl()); - assert(UGD.getDecl() && "unique overrider not found"); - assert(UGD == getUnique(OGD) && |