[cfe-commits] r96133 - /cfe/trunk/lib/CodeGen/CGVtable.cpp

Anders Carlsson andersca at mac.com
Sat Feb 13 15:17:31 PST 2010


Author: andersca
Date: Sat Feb 13 17:17:31 2010
New Revision: 96133

URL: http://llvm.org/viewvc/llvm-project?rev=96133&view=rev
Log:
Add support for very simple non-virtual this adjustments in the FinalOverriders class.

Modified:
    cfe/trunk/lib/CodeGen/CGVtable.cpp

Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=96133&r1=96132&r2=96133&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Sat Feb 13 17:17:31 2010
@@ -42,11 +42,11 @@
     /// NonVirtualOffset - The offset from the derived class to the base class.
     /// Or the offset from the virtual base class to the base class, if the path
     /// from the derived class to the base class involves a virtual base class.
-    uint64_t NonVirtualOffset;
+    int64_t NonVirtualOffset;
     
     BaseOffset() : DerivedClass(0), VirtualBase(0), NonVirtualOffset(0) { }
     BaseOffset(const CXXRecordDecl *DerivedClass,
-               const CXXRecordDecl *VirtualBase, uint64_t NonVirtualOffset)
+               const CXXRecordDecl *VirtualBase, int64_t NonVirtualOffset)
       : DerivedClass(DerivedClass), VirtualBase(VirtualBase), 
       NonVirtualOffset(NonVirtualOffset) { }
 
@@ -90,6 +90,10 @@
   /// need to perform return value adjustments.
   AdjustmentOffsetsMapTy ReturnAdjustments;
   
+  /// ThisAdjustments - Holds 'this' adjustments for all the overriders that
+  /// need them.
+  AdjustmentOffsetsMapTy ThisAdjustments;
+
   typedef llvm::SmallVector<uint64_t, 1> OffsetVectorTy;
   
   /// SubobjectOffsetsMapTy - This map is used for keeping track of all the
@@ -131,6 +135,11 @@
                           const CXXMethodDecl *NewMD,
                           SubobjectOffsetsMapTy &Offsets);
   
+  /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
+  /// the 'this' pointer from BaseRD to DerivedRD.
+  BaseOffset ComputeThisAdjustmentBaseOffset(const CXXRecordDecl *BaseRD,
+                                             const CXXRecordDecl *DerivedRD);
+                                             
   static void MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
                                     SubobjectOffsetsMapTy &Offsets);
 
@@ -210,9 +219,8 @@
 }
 
 static FinalOverriders::BaseOffset 
-ComputeBaseOffset(ASTContext &Context,
-                  const CXXRecordDecl *DerivedRD,
-                  const CXXRecordDecl *BaseRD) {
+ComputeBaseOffset(ASTContext &Context, const CXXRecordDecl *BaseRD,
+                  const CXXRecordDecl *DerivedRD) {
   CXXBasePaths Paths(/*FindAmbiguities=*/false,
                      /*RecordPaths=*/true, /*DetectVirtual=*/false);
   
@@ -222,7 +230,7 @@
     return FinalOverriders::BaseOffset();
   }
 
-  uint64_t NonVirtualOffset = 0;
+  int64_t NonVirtualOffset = 0;
 
   const CXXBasePath &Path = Paths.front();
   
@@ -264,9 +272,9 @@
 }
 
 static FinalOverriders::BaseOffset
-ComputeReturnTypeBaseOffset(ASTContext &Context, 
-                            const CXXMethodDecl *DerivedMD,
-                            const CXXMethodDecl *BaseMD) {
+ComputeReturnAdjustmentBaseOffset(ASTContext &Context, 
+                                  const CXXMethodDecl *DerivedMD,
+                                  const CXXMethodDecl *BaseMD) {
   const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
   const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
   
@@ -314,9 +322,30 @@
   const CXXRecordDecl *BaseRD = 
     cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
 
-  return ComputeBaseOffset(Context, DerivedRD, BaseRD);
+  return ComputeBaseOffset(Context, BaseRD, DerivedRD);
 }
 
+FinalOverriders::BaseOffset
+FinalOverriders::ComputeThisAdjustmentBaseOffset(const CXXRecordDecl *BaseRD,
+                                               const CXXRecordDecl *DerivedRD) {
+  CXXBasePaths Paths(/*FindAmbiguities=*/false,
+                     /*RecordPaths=*/true, /*DetectVirtual=*/true);
+
+  if (!const_cast<CXXRecordDecl *>(DerivedRD)->
+      isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
+    assert(false && "Class must be derived from the passed in base class!");
+    return FinalOverriders::BaseOffset();
+  }
+
+  assert(!Paths.getDetectedVirtual() && "FIXME: Handle virtual bases!");
+
+  // FIXME: We need to go through all paths here, just not the first one.
+  BaseOffset Offset = ComputeBaseOffset(Context, BaseRD, DerivedRD);
+
+  Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
+  return Offset;
+}
+  
 void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
                                          BaseSubobject NewBase,
                                          const CXXMethodDecl *NewMD,
@@ -347,11 +376,13 @@
 
       assert(Overrider.Method && "Did not find existing overrider!");
 
-      // Get the return adjustment base offset.
+      // Check if we need return adjustments or base adjustments.
       // (We don't want to do this for pure virtual member functions).
       if (!NewMD->isPure()) {
+        // Get the return adjustment base offset.
         BaseOffset ReturnBaseOffset =
-          ComputeReturnTypeBaseOffset(Context, NewMD, OverriddenMD);
+          ComputeReturnAdjustmentBaseOffset(Context, NewMD, OverriddenMD);
+
         if (!ReturnBaseOffset.isEmpty()) {
           // Store the return adjustment base offset.
           ReturnAdjustments[SubobjectAndMethod] = ReturnBaseOffset;
@@ -359,7 +390,13 @@
         
         // Check if we need a 'this' adjustment base offset as well.
         if (Offset != NewBase.getBaseOffset()) {
-          assert(false && "FIXME: Handle 'this' adjustments!");
+          BaseOffset ThisBaseOffset =
+            ComputeThisAdjustmentBaseOffset(OverriddenMD->getParent(),
+                                            NewMD->getParent());
+          assert(!ThisBaseOffset.isEmpty() && 
+                 "Should not get an empty 'this' adjustment!");
+          
+          ThisAdjustments[SubobjectAndMethod] = ThisBaseOffset;
         }
       }
 
@@ -492,6 +529,18 @@
              
       Out << Offset.NonVirtualOffset << " nv]";
     }
+    
+    AI = ThisAdjustments.find(std::make_pair(Base, MD));
+    if (AI != ThisAdjustments.end()) {
+      const BaseOffset &Offset = AI->second;
+      
+      Out << " [this-adj: ";
+      if (Offset.VirtualBase)
+        Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, ";
+      
+      Out << Offset.NonVirtualOffset << " nv]";
+    }
+    
     Out << "\n";
   }  
 }
@@ -786,7 +835,8 @@
     // then we can just use the member function from the primary base.
     if (const CXXMethodDecl *OverriddenMD = 
         OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
-      if (ComputeReturnTypeBaseOffset(Context, MD, OverriddenMD).isEmpty())
+      if (ComputeReturnAdjustmentBaseOffset(Context, MD, 
+                                            OverriddenMD).isEmpty())
         continue;
     }
 
@@ -1908,7 +1958,8 @@
       OMD->getType()->getAs<FunctionType>()->getResultType();
     
     // Check if we need a return type adjustment.
-    if (!ComputeReturnTypeBaseOffset(CGM.getContext(), MD, OMD).isEmpty()) {
+    if (!ComputeReturnAdjustmentBaseOffset(CGM.getContext(), MD, 
+                                           OMD).isEmpty()) {
       CanQualType &BaseReturnType = BaseReturnTypes[Index];
 
       // Insert the base return type.
@@ -2108,8 +2159,8 @@
           OverridesMethodInPrimaryBase(MD, PrimaryBases)) {
       // Check if converting from the return type of the method to the 
       // return type of the overridden method requires conversion.
-      if (ComputeReturnTypeBaseOffset(CGM.getContext(), MD, 
-                                      OverriddenMD).isEmpty()) {
+      if (ComputeReturnAdjustmentBaseOffset(CGM.getContext(), MD, 
+                                            OverriddenMD).isEmpty()) {
         // This index is shared between the index in the vtable of the primary
         // base class.
         if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {





More information about the cfe-commits mailing list