[cfe-commits] r90168 - in /cfe/trunk: include/clang/AST/RecordLayout.h lib/AST/RecordLayoutBuilder.cpp lib/CodeGen/CGRecordLayoutBuilder.cpp lib/CodeGen/CGVtable.cpp lib/CodeGen/CGVtable.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenTypes.h

Anders Carlsson andersca at mac.com
Mon Nov 30 15:41:22 PST 2009


Author: andersca
Date: Mon Nov 30 17:41:22 2009
New Revision: 90168

URL: http://llvm.org/viewvc/llvm-project?rev=90168&view=rev
Log:
Have ASTRecordLayout keep track of the key function, in preparation of fixing a synthetic ctor/dtor bug.

Modified:
    cfe/trunk/include/clang/AST/RecordLayout.h
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CGVtable.cpp
    cfe/trunk/lib/CodeGen/CGVtable.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenTypes.h

Modified: cfe/trunk/include/clang/AST/RecordLayout.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=90168&r1=90167&r2=90168&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/RecordLayout.h (original)
+++ cfe/trunk/include/clang/AST/RecordLayout.h Mon Nov 30 17:41:22 2009
@@ -119,6 +119,13 @@
     /// VBaseOffsets - Contains a map from vbase classes to their offset.
     /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
     llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets;
+    
+    /// KeyFunction - The key function, according to the Itanium C++ ABI,
+    /// section 5.2.3:
+    ///
+    /// ...the first non-pure virtual function that is not inline at the point
+    /// of class definition.
+    const CXXMethodDecl *KeyFunction;
   };
 
   /// CXXInfo - If the record layout is for a C++ record, this will have
@@ -147,7 +154,8 @@
                   const std::pair<const CXXRecordDecl *, uint64_t> *bases,
                   unsigned numbases,
                   const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
-                  unsigned numvbases)
+                  unsigned numvbases,
+                  const CXXMethodDecl *KeyFunction)
   : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
   FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) {
     if (FieldCount > 0)  {
@@ -163,6 +171,7 @@
       CXXInfo->BaseOffsets[bases[i].first] = bases[i].second;
     for (unsigned i = 0; i != numvbases; ++i)
       CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second;
+    CXXInfo->KeyFunction = KeyFunction;
   }
 
   ~ASTRecordLayout() {
@@ -245,6 +254,13 @@
     return CXXInfo->VBaseOffsets[VBase];
   }
   
+  /// getKeyFunction - Get the key function.                  
+  const CXXMethodDecl *getKeyFunction() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+    return CXXInfo->KeyFunction;
+  }
+  
   primary_base_info_iterator primary_base_begin() const {
     assert(CXXInfo && "Record layout does not have C++ specific info!");
   

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=90168&r1=90167&r2=90168&view=diff

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Mon Nov 30 17:41:22 2009
@@ -663,6 +663,31 @@
   Alignment = NewAlignment;
 }
 
+static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) {
+  if (!RD->isDynamicClass())
+    return 0;
+  
+  for (CXXRecordDecl::method_iterator I = RD->method_begin(), 
+       E = RD->method_end(); I != E; ++I) {
+    const CXXMethodDecl *MD = *I;
+    
+    if (!MD->isVirtual())
+      continue;
+    
+    if (MD->isPure())
+      continue;
+    
+    const FunctionDecl *fn;
+    if (MD->getBody(fn) && !fn->isOutOfLine())
+      continue;
+    
+    // We found it.
+    return MD;
+  }
+  
+  return 0;
+}
+
 const ASTRecordLayout *
 ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
                                       const RecordDecl *D) {
@@ -686,6 +711,8 @@
   uint64_t NonVirtualSize =
     IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
 
+  const CXXMethodDecl *KeyFunction = GetKeyFunction(cast<CXXRecordDecl>(D));
+  
   return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
                              Builder.FieldOffsets.data(),
                              Builder.FieldOffsets.size(),
@@ -695,7 +722,8 @@
                              Builder.Bases.data(),
                              Builder.Bases.size(),
                              Builder.VBases.data(),
-                             Builder.VBases.size());
+                             Builder.VBases.size(),
+                             KeyFunction);
 }
 
 const ASTRecordLayout *

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Mon Nov 30 17:41:22 2009
@@ -330,32 +330,6 @@
 
 }
 
-static const CXXMethodDecl *GetKeyFunction(const RecordDecl *D) {
-  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
-  if (!RD || !RD->isDynamicClass())
-    return 0;
-  
-  for (CXXRecordDecl::method_iterator I = RD->method_begin(), 
-       E = RD->method_end(); I != E; ++I) {
-    const CXXMethodDecl *MD = *I;
-    
-    if (!MD->isVirtual())
-      continue;
-    
-    if (MD->isPure())
-      continue;
-
-    const FunctionDecl *fn;
-    if (MD->getBody(fn) && !fn->isOutOfLine())
-      continue;
-
-    // We found it.
-    return MD;
-  }
-  
-  return 0;
-}
-
 CGRecordLayout *
 CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types,
                                      const RecordDecl *D) {
@@ -385,7 +359,5 @@
     Types.addBitFieldInfo(Info.FD, Info.FieldNo, Info.Start, Info.Size);
   }
 
-  const CXXMethodDecl *KeyFunction = GetKeyFunction(D);
-
-  return new CGRecordLayout(Ty, Builder.ContainsMemberPointer, KeyFunction);
+  return new CGRecordLayout(Ty, Builder.ContainsMemberPointer);
 }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Mon Nov 30 17:41:22 2009
@@ -1060,10 +1060,10 @@
     if (LayoutClass != RD)
       CreateDefinition = true;
     else {
-      // We have to convert it to have a record layout.
-      Types.ConvertTagDeclType(LayoutClass);
-      const CGRecordLayout &CGLayout = Types.getCGRecordLayout(LayoutClass);
-      if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
+      const ASTRecordLayout &Layout = 
+        getContext().getASTRecordLayout(LayoutClass);
+      
+      if (const CXXMethodDecl *KeyFunction = Layout.getKeyFunction()) {
         if (!KeyFunction->getBody()) {
           // If there is a KeyFunction, and it isn't defined, just build a
           // reference to the vtable.
@@ -1316,10 +1316,9 @@
   vtbl = CGM.GenerateVtable(RD, RD);
 
   bool CreateDefinition = true;
-  // We have to convert it to have a record layout.
-  CGM.getTypes().ConvertTagDeclType(RD);
-  const CGRecordLayout &CGLayout = CGM.getTypes().getCGRecordLayout(RD);
-  if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
+
+  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+  if (const CXXMethodDecl *KeyFunction = Layout.getKeyFunction()) {
     if (!KeyFunction->getBody()) {
       // If there is a KeyFunction, and it isn't defined, just build a
       // reference to the vtable.
@@ -1339,3 +1338,31 @@
                                             uint64_t Offset) {
   return CGM.GenerateVtable(LayoutClass, RD, Offset);
 }
+
+void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+  const CXXRecordDecl *RD = MD->getParent();
+
+  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+  
+  // Get the key function.
+  const CXXMethodDecl *KeyFunction = Layout.getKeyFunction();
+  
+  if (!KeyFunction) {
+    // If there's no key function, we don't want to emit the vtable here.
+    return;
+  }
+
+  // Check if we have the key function.
+  if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
+    return;
+  
+  // If the key function is a destructor, we only want to emit the vtable once,
+  // so do it for the complete destructor.
+  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Complete)
+    return;
+
+  // Emit the data.
+  GenerateClassData(RD);
+}
+

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.h (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.h Mon Nov 30 17:41:22 2009
@@ -91,6 +91,11 @@
   
   void ComputeMethodVtableIndices(const CXXRecordDecl *RD);
   
+  /// GenerateClassData - Generate all the class data requires to be generated
+  /// upon definition of a KeyFunction.  This includes the vtable, the
+  /// rtti data structure and the VTT.
+  void GenerateClassData(const CXXRecordDecl *RD);
+  
 public:
   CGVtableInfo(CodeGenModule &CGM)
     : CGM(CGM) { }
@@ -111,10 +116,9 @@
   llvm::Constant *getVtable(const CXXRecordDecl *RD);
   llvm::Constant *getCtorVtable(const CXXRecordDecl *RD,
                                 const CXXRecordDecl *Class, uint64_t Offset);
-  /// GenerateClassData - Generate all the class data requires to be generated
-  /// upon definition of a KeyFunction.  This includes the vtable, the
-  /// rtti data structure and the VTT.
-  void GenerateClassData(const CXXRecordDecl *RD);
+  
+  
+  void MaybeEmitVtable(GlobalDecl GD);
 };
 
 }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Nov 30 17:41:22 2009
@@ -21,6 +21,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/RecordLayout.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
@@ -614,18 +615,9 @@
                                  Context.getSourceManager(),
                                  "Generating code for declaration");
   
-  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
-    const CXXRecordDecl *RD = MD->getParent();
-    // We have to convert it to have a record layout.
-    Types.ConvertTagDeclType(RD);
-    const CGRecordLayout &CGLayout = Types.getCGRecordLayout(RD);
-    // A definition of a KeyFunction, generates all the class data, such
-    // as vtable, rtti and the VTT.
-    if (CGLayout.getKeyFunction()
-        && (CGLayout.getKeyFunction()->getCanonicalDecl()
-            == MD->getCanonicalDecl()))
-      getVtableInfo().GenerateClassData(RD);
-  }
+  if (isa<CXXMethodDecl>(D))
+    getVtableInfo().MaybeEmitVtable(GD);
+  
   if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
     EmitCXXConstructor(CD, GD.getCtorType());
   else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D))

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=90168&r1=90167&r2=90168&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Mon Nov 30 17:41:22 2009
@@ -64,17 +64,9 @@
     /// is a member pointer, or a struct that contains a member pointer.
     bool ContainsMemberPointer;
 
-    /// KeyFunction - The key function of the record layout (if one exists),
-    /// which is the first non-pure virtual function that is not inline at the
-    /// point of class definition.
-    /// See http://www.codesourcery.com/public/cxx-abi/abi.html#vague-vtable.
-    const CXXMethodDecl *KeyFunction;
-    
   public:
-    CGRecordLayout(const llvm::Type *T, bool ContainsMemberPointer,
-                   const CXXMethodDecl *KeyFunction)
-      : LLVMType(T), ContainsMemberPointer(ContainsMemberPointer),
-        KeyFunction(KeyFunction) { }
+    CGRecordLayout(const llvm::Type *T, bool ContainsMemberPointer)
+      : LLVMType(T), ContainsMemberPointer(ContainsMemberPointer) { }
 
     /// getLLVMType - Return llvm type associated with this record.
     const llvm::Type *getLLVMType() const {
@@ -84,10 +76,6 @@
     bool containsMemberPointer() const {
       return ContainsMemberPointer;
     }
-
-    const CXXMethodDecl *getKeyFunction() const {
-      return KeyFunction;
-    }
   };
 
 /// CodeGenTypes - This class organizes the cross-module state that is used





More information about the cfe-commits mailing list