Use the new CovariantThunkAdjustment in the vtable builder.
Make the pure virtual methods map a set instead. llvm-svn: 89961
This commit is contained in:
		
							parent
							
								
									5fe97e7aca
								
							
						
					
					
						commit
						d420a31fe9
					
				| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
#include "CodeGenFunction.h"
 | 
					#include "CodeGenFunction.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "clang/AST/RecordLayout.h"
 | 
					#include "clang/AST/RecordLayout.h"
 | 
				
			||||||
 | 
					#include "llvm/ADT/DenseSet.h"
 | 
				
			||||||
#include <cstdio>
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace clang;
 | 
					using namespace clang;
 | 
				
			||||||
| 
						 | 
					@ -63,21 +64,43 @@ private:
 | 
				
			||||||
    /// Index - The index in the vtable.
 | 
					    /// Index - The index in the vtable.
 | 
				
			||||||
    uint64_t Index;
 | 
					    uint64_t Index;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// ThisAdjustment - The thunk adjustment.
 | 
					    /// Adjustment - The thunk adjustment.
 | 
				
			||||||
    ThunkAdjustment Adjustment;
 | 
					    ThunkAdjustment Adjustment;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  typedef llvm::DenseMap<GlobalDecl, int> Pures_t;
 | 
					  /// Thunks - The thunks in a vtable.
 | 
				
			||||||
  Pures_t Pures;
 | 
					 | 
				
			||||||
  typedef std::pair<Index_t, Index_t>  CallOffset;
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  typedef llvm::DenseMap<GlobalDecl, Thunk> ThunksMapTy;
 | 
					  typedef llvm::DenseMap<GlobalDecl, Thunk> ThunksMapTy;
 | 
				
			||||||
  ThunksMapTy Thunks;
 | 
					  ThunksMapTy Thunks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  typedef llvm::DenseMap<GlobalDecl,
 | 
					  /// CovariantThunk - Represents a single covariant thunk.
 | 
				
			||||||
                         std::pair<std::pair<CallOffset, CallOffset>,
 | 
					  struct CovariantThunk {
 | 
				
			||||||
                                   CanQualType> > CovariantThunks_t;
 | 
					    CovariantThunk()
 | 
				
			||||||
  CovariantThunks_t CovariantThunks;
 | 
					      : Index(0) { }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    CovariantThunk(uint64_t Index, const ThunkAdjustment &ThisAdjustment,
 | 
				
			||||||
 | 
					                   const ThunkAdjustment &ReturnAdjustment, 
 | 
				
			||||||
 | 
					                   CanQualType ReturnType) 
 | 
				
			||||||
 | 
					      : Index(Index), Adjustment(ThisAdjustment, ReturnAdjustment), 
 | 
				
			||||||
 | 
					      ReturnType(ReturnType) { }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Index - The index in the vtable.
 | 
				
			||||||
 | 
					    uint64_t Index;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Adjustment - The covariant thunk adjustment.
 | 
				
			||||||
 | 
					    CovariantThunkAdjustment Adjustment;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// ReturnType - The return type of the function.
 | 
				
			||||||
 | 
					    CanQualType ReturnType;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /// CovariantThunks - The covariant thunks in a vtable.
 | 
				
			||||||
 | 
					  typedef llvm::DenseMap<GlobalDecl, CovariantThunk> CovariantThunksMapTy;
 | 
				
			||||||
 | 
					  CovariantThunksMapTy CovariantThunks;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /// PureVirtualMethods - Pure virtual methods.
 | 
				
			||||||
 | 
					  typedef llvm::DenseSet<GlobalDecl> PureVirtualMethodsSetTy;
 | 
				
			||||||
 | 
					  PureVirtualMethodsSetTy PureVirtualMethods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::vector<Index_t> VCalls;
 | 
					  std::vector<Index_t> VCalls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
 | 
					  typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
 | 
				
			||||||
| 
						 | 
					@ -268,22 +291,23 @@ public:
 | 
				
			||||||
        CanQualType oret = CGM.getContext().getCanonicalType(nc_oret);
 | 
					        CanQualType oret = CGM.getContext().getCanonicalType(nc_oret);
 | 
				
			||||||
        QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
 | 
					        QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
 | 
				
			||||||
        CanQualType ret = CGM.getContext().getCanonicalType(nc_ret);
 | 
					        CanQualType ret = CGM.getContext().getCanonicalType(nc_ret);
 | 
				
			||||||
        CallOffset ReturnOffset = std::make_pair(0, 0);
 | 
					        ThunkAdjustment ReturnAdjustment;
 | 
				
			||||||
        if (oret != ret) {
 | 
					        if (oret != ret) {
 | 
				
			||||||
          // FIXME: calculate offsets for covariance
 | 
					          // FIXME: calculate offsets for covariance
 | 
				
			||||||
          if (CovariantThunks.count(OMD)) {
 | 
					          CovariantThunksMapTy::iterator i = CovariantThunks.find(OMD);
 | 
				
			||||||
            oret = CovariantThunks[OMD].second;
 | 
					          if (i != CovariantThunks.end()) {
 | 
				
			||||||
            CovariantThunks.erase(OMD);
 | 
					            oret = i->second.ReturnType;
 | 
				
			||||||
 | 
					            CovariantThunks.erase(i);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          // FIXME: Double check oret
 | 
					          // FIXME: Double check oret
 | 
				
			||||||
          Index_t nv = getNVOffset(oret, ret)/8;
 | 
					          Index_t nv = getNVOffset(oret, ret)/8;
 | 
				
			||||||
          ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
 | 
					          ReturnAdjustment = ThunkAdjustment(nv, getVbaseOffset(oret, ret));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Index[GD] = i;
 | 
					        Index[GD] = i;
 | 
				
			||||||
        submethods[i] = m;
 | 
					        submethods[i] = m;
 | 
				
			||||||
        if (isPure)
 | 
					        if (isPure)
 | 
				
			||||||
          Pures[GD] = 1;
 | 
					          PureVirtualMethods.insert(GD);
 | 
				
			||||||
        Pures.erase(OGD);
 | 
					        PureVirtualMethods.erase(OGD);
 | 
				
			||||||
        Thunks.erase(OGD);
 | 
					        Thunks.erase(OGD);
 | 
				
			||||||
        if (MorallyVirtual || VCall.count(OGD)) {
 | 
					        if (MorallyVirtual || VCall.count(OGD)) {
 | 
				
			||||||
          Index_t &idx = VCall[OGD];
 | 
					          Index_t &idx = VCall[OGD];
 | 
				
			||||||
| 
						 | 
					@ -312,18 +336,15 @@ public:
 | 
				
			||||||
          if (VCalls[idx-1] == 0)
 | 
					          if (VCalls[idx-1] == 0)
 | 
				
			||||||
            VirtualAdjustment = 0;
 | 
					            VirtualAdjustment = 0;
 | 
				
			||||||
          
 | 
					          
 | 
				
			||||||
          CallOffset ThisOffset = std::make_pair(NonVirtualAdjustment, 
 | 
					 | 
				
			||||||
                                                 VirtualAdjustment);
 | 
					 | 
				
			||||||
          ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
 | 
					          ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
 | 
				
			||||||
                                         VirtualAdjustment);
 | 
					                                         VirtualAdjustment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // FIXME: Do we always have to build a covariant thunk to save oret,
 | 
					          // FIXME: Do we always have to build a covariant thunk to save oret,
 | 
				
			||||||
          // which is the containing virtual base class?
 | 
					          // which is the containing virtual base class?
 | 
				
			||||||
          if (ReturnOffset.first || ReturnOffset.second)
 | 
					          if (!ReturnAdjustment.isEmpty()) {
 | 
				
			||||||
            CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
 | 
					            CovariantThunks[GD] = 
 | 
				
			||||||
                                                                ReturnOffset),
 | 
					              CovariantThunk(i, ThisAdjustment, ReturnAdjustment, oret);
 | 
				
			||||||
                                                 oret);
 | 
					          } else if (!isPure && !ThisAdjustment.isEmpty())
 | 
				
			||||||
          else if (!isPure && !ThisAdjustment.isEmpty())
 | 
					 | 
				
			||||||
            Thunks[GD] = Thunk(i, ThisAdjustment);
 | 
					            Thunks[GD] = Thunk(i, ThisAdjustment);
 | 
				
			||||||
          return true;
 | 
					          return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -331,15 +352,13 @@ public:
 | 
				
			||||||
        // FIXME: finish off
 | 
					        // FIXME: finish off
 | 
				
			||||||
        int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8;
 | 
					        int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (NonVirtualAdjustment || ReturnOffset.first || ReturnOffset.second) {
 | 
					        if (NonVirtualAdjustment || !ReturnAdjustment.isEmpty()) {
 | 
				
			||||||
          CallOffset ThisOffset = std::make_pair(NonVirtualAdjustment, 0);
 | 
					 | 
				
			||||||
          ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
 | 
					          ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
 | 
				
			||||||
          
 | 
					          
 | 
				
			||||||
          if (ReturnOffset.first || ReturnOffset.second)
 | 
					          if (!ReturnAdjustment.isEmpty()) {
 | 
				
			||||||
            CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
 | 
					            CovariantThunks[GD] = 
 | 
				
			||||||
                                                                ReturnOffset),
 | 
					              CovariantThunk(i, ThisAdjustment, ReturnAdjustment, oret);
 | 
				
			||||||
                                                 oret);
 | 
					          } else if (!isPure)
 | 
				
			||||||
          else if (!isPure)
 | 
					 | 
				
			||||||
            Thunks[GD] = Thunk(i, ThisAdjustment);
 | 
					            Thunks[GD] = Thunk(i, ThisAdjustment);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
| 
						 | 
					@ -363,31 +382,26 @@ public:
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Thunks.clear();
 | 
					    Thunks.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (CovariantThunks_t::iterator i = CovariantThunks.begin(),
 | 
					    for (CovariantThunksMapTy::const_iterator i = CovariantThunks.begin(),
 | 
				
			||||||
           e = CovariantThunks.end();
 | 
					         e = CovariantThunks.end(); i != e; ++i) {
 | 
				
			||||||
         i != e; ++i) {
 | 
					 | 
				
			||||||
      GlobalDecl GD = i->first;
 | 
					      GlobalDecl GD = i->first;
 | 
				
			||||||
      const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
 | 
					      const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
 | 
				
			||||||
      if (MD->isPure())
 | 
					      if (MD->isPure())
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      Index_t idx = Index[GD];
 | 
					 | 
				
			||||||
      Index_t nv_t = i->second.first.first.first;
 | 
					 | 
				
			||||||
      Index_t v_t = i->second.first.first.second;
 | 
					 | 
				
			||||||
      Index_t nv_r = i->second.first.second.first;
 | 
					 | 
				
			||||||
      Index_t v_r = i->second.first.second.second;
 | 
					 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      CovariantThunkAdjustment Adjustment(ThunkAdjustment(nv_t, v_t),
 | 
					      const CovariantThunk &Thunk = i->second;
 | 
				
			||||||
                                          ThunkAdjustment(nv_r, v_r));
 | 
					      assert(Thunk.Index == Index[GD] && "Thunk index mismatch!");
 | 
				
			||||||
      submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, Adjustment);
 | 
					      submethods[Thunk.Index] = 
 | 
				
			||||||
 | 
					        CGM.BuildCovariantThunk(MD, Extern, Thunk.Adjustment);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    CovariantThunks.clear();
 | 
					    CovariantThunks.clear();
 | 
				
			||||||
    for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
 | 
					
 | 
				
			||||||
         i != e; ++i) {
 | 
					    for (PureVirtualMethodsSetTy::iterator i = PureVirtualMethods.begin(),
 | 
				
			||||||
      GlobalDecl GD = i->first;
 | 
					         e = PureVirtualMethods.end(); i != e; ++i) {
 | 
				
			||||||
      Index_t idx = Index[GD];
 | 
					      GlobalDecl GD = *i;
 | 
				
			||||||
      submethods[idx] = cxa_pure;
 | 
					      submethods[Index[GD]] = cxa_pure;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Pures.clear();
 | 
					    PureVirtualMethods.clear();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  llvm::Constant *WrapAddrOf(GlobalDecl GD) {
 | 
					  llvm::Constant *WrapAddrOf(GlobalDecl GD) {
 | 
				
			||||||
| 
						 | 
					@ -448,7 +462,7 @@ public:
 | 
				
			||||||
    D1(printf("  vfn for %s at %d\n", MD->getNameAsString().c_str(),
 | 
					    D1(printf("  vfn for %s at %d\n", MD->getNameAsString().c_str(),
 | 
				
			||||||
              (int)Index[GD]));
 | 
					              (int)Index[GD]));
 | 
				
			||||||
    if (MD->isPure())
 | 
					    if (MD->isPure())
 | 
				
			||||||
      Pures[GD] = 1;
 | 
					      PureVirtualMethods.insert(GD);
 | 
				
			||||||
    if (MorallyVirtual) {
 | 
					    if (MorallyVirtual) {
 | 
				
			||||||
      VCallOffset[GD] = Offset/8;
 | 
					      VCallOffset[GD] = Offset/8;
 | 
				
			||||||
      Index_t &idx = VCall[GD];
 | 
					      Index_t &idx = VCall[GD];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue