[cfe-commits] r173035 - in /cfe/trunk: include/clang/AST/VTableBuilder.h lib/AST/VTableBuilder.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/microsoft-abi-constructors.cpp test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp

Timur Iskhodzhanov timurrrr at google.com
Mon Jan 21 05:02:42 PST 2013


Author: timurrrr
Date: Mon Jan 21 07:02:41 2013
New Revision: 173035

URL: http://llvm.org/viewvc/llvm-project?rev=173035&view=rev
Log:
First step towards vftable generation with -cxx-abi microsoft PR13231

Added:
    cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/VTableBuilder.h
    cfe/trunk/lib/AST/VTableBuilder.cpp
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp

Modified: cfe/trunk/include/clang/AST/VTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/VTableBuilder.h?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/VTableBuilder.h (original)
+++ cfe/trunk/include/clang/AST/VTableBuilder.h Mon Jan 21 07:02:41 2013
@@ -215,12 +215,15 @@
   /// Address points - Address points for all vtables.
   AddressPointsMapTy AddressPoints;
 
+  bool IsMicrosoftABI;
+
 public:
   VTableLayout(uint64_t NumVTableComponents,
                const VTableComponent *VTableComponents,
                uint64_t NumVTableThunks,
                const VTableThunkTy *VTableThunks,
-               const AddressPointsMapTy &AddressPoints);
+               const AddressPointsMapTy &AddressPoints,
+               bool IsMicrosoftABI);
   ~VTableLayout();
 
   uint64_t getNumVTableComponents() const {
@@ -252,7 +255,7 @@
            "Did not find address point!");
 
     uint64_t AddressPoint = AddressPoints.lookup(Base);
-    assert(AddressPoint && "Address point must not be zero!");
+    assert(AddressPoint != 0 || IsMicrosoftABI);
 
     return AddressPoint;
   }
@@ -271,6 +274,8 @@
   typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
 
 private:
+  bool IsMicrosoftABI;
+
   /// MethodVTableIndices - Contains the index (relative to the vtable address
   /// point) where the function pointer for a virtual function is stored.
   typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
@@ -306,10 +311,21 @@
   /// given record decl.
   void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
 
+  /// ErrorUnsupported - Print out an error that the v-table layout code
+  /// doesn't support the particular C++ feature yet.
+  void ErrorUnsupported(StringRef Feature, SourceLocation Location);
+
 public:
-  VTableContext(ASTContext &Context) : Context(Context) {}
+  VTableContext(ASTContext &Context);
   ~VTableContext();
 
+  bool isMicrosoftABI() const {
+    // FIXME: Currently, this method is only used in the VTableContext and
+    // VTableBuilder code which is ABI-specific. Probably we can remove it
+    // when we add a layer of abstraction for vtable generation.
+    return IsMicrosoftABI;
+  }
+
   const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
     ComputeVTableRelatedInformation(RD);
     assert(VTableLayouts.count(RD) && "No layout for this record decl!");

Modified: cfe/trunk/lib/AST/VTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/lib/AST/VTableBuilder.cpp (original)
+++ cfe/trunk/lib/AST/VTableBuilder.cpp Mon Jan 21 07:02:41 2013
@@ -1002,6 +1002,10 @@
       dumpLayout(llvm::errs());
   }
 
+  bool isMicrosoftABI() const {
+    return VTables.isMicrosoftABI();
+  }
+
   uint64_t getNumThunks() const {
     return Thunks.size();
   }
@@ -1296,9 +1300,18 @@
     assert(ReturnAdjustment.isEmpty() && 
            "Destructor can't have return adjustment!");
 
-    // Add both the complete destructor and the deleting destructor.
-    Components.push_back(VTableComponent::MakeCompleteDtor(DD));
-    Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+    // FIXME: Should probably add a layer of abstraction for vtable generation.
+    if (!isMicrosoftABI()) {
+      // Add both the complete destructor and the deleting destructor.
+      Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+      Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+    } else {
+      // Add only one destructor in MS mode.
+      // FIXME: The virtual destructors are handled differently in MS ABI,
+      // we should add such a support later. For now, put the complete
+      // destructor into the vftable just to make its layout right.
+      Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+    }
   } else {
     // Add the return adjustment if necessary.
     if (!ReturnAdjustment.isEmpty())
@@ -1613,14 +1626,19 @@
   if (Base.getBase() == MostDerivedClass)
     VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
 
-  // Add the offset to top.
-  CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
-  Components.push_back(
-    VTableComponent::MakeOffsetToTop(OffsetToTop));
-  
-  // Next, add the RTTI.
-  Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
-  
+  // FIXME: Should probably add a layer of abstraction for vtable generation.
+  if (!isMicrosoftABI()) {
+    // Add the offset to top.
+    CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
+    Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
+
+    // Next, add the RTTI.
+    Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
+  } else {
+    // FIXME: unclear what to do with RTTI in MS ABI as emitting it anywhere
+    // breaks the vftable layout. Just skip RTTI for now, can't mangle anyway.
+  }
+
   uint64_t AddressPoint = Components.size();
 
   // Now go through all virtual member functions and add them.
@@ -2121,10 +2139,16 @@
                                   MD);
 
     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
-      IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))] =
-        MethodName + " [complete]";
-      IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] =
-        MethodName + " [deleting]";
+      // FIXME: Should add a layer of abstraction for vtable generation.
+      if (!isMicrosoftABI()) {
+        IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))]
+          = MethodName + " [complete]";
+        IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))]
+          = MethodName + " [deleting]";
+      } else {
+        IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))]
+          = MethodName;
+      }
     } else {
       IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName;
     }
@@ -2155,12 +2179,14 @@
                            const VTableComponent *VTableComponents,
                            uint64_t NumVTableThunks,
                            const VTableThunkTy *VTableThunks,
-                           const AddressPointsMapTy &AddressPoints)
+                           const AddressPointsMapTy &AddressPoints,
+                           bool IsMicrosoftABI)
   : NumVTableComponents(NumVTableComponents),
     VTableComponents(new VTableComponent[NumVTableComponents]),
     NumVTableThunks(NumVTableThunks),
     VTableThunks(new VTableThunkTy[NumVTableThunks]),
-    AddressPoints(AddressPoints) {
+    AddressPoints(AddressPoints),
+    IsMicrosoftABI(IsMicrosoftABI) {
   std::copy(VTableComponents, VTableComponents+NumVTableComponents,
             this->VTableComponents.get());
   std::copy(VTableThunks, VTableThunks+NumVTableThunks,
@@ -2169,6 +2195,10 @@
 
 VTableLayout::~VTableLayout() { }
 
+VTableContext::VTableContext(ASTContext &Context)
+  : Context(Context),
+  IsMicrosoftABI(Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) { }
+
 VTableContext::~VTableContext() {
   llvm::DeleteContainerSeconds(VTableLayouts);
 }
@@ -2240,12 +2270,17 @@
         if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
           const CXXDestructorDecl *OverriddenDD = 
             cast<CXXDestructorDecl>(OverriddenMD);
-          
-          // Add both the complete and deleting entries.
-          MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = 
-            getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
-          MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = 
-            getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
+
+          if (!isMicrosoftABI()) {
+            // Add both the complete and deleting entries.
+            MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
+              getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
+            MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
+              getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
+          } else {
+            MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
+              getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
+          }
         } else {
           MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD);
         }
@@ -2263,11 +2298,19 @@
         continue;
       } 
 
-      // Add the complete dtor.
-      MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
-      
-      // Add the deleting dtor.
-      MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
+      if (!isMicrosoftABI()) {
+        // Add the complete dtor.
+        MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
+
+        // Add the deleting dtor.
+        MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
+      } else {
+        // Add only the deleting dtor.
+        // FIXME: The virtual destructors are handled differently in MS ABI,
+        // we should add such a support later. For now, put the complete
+        // destructor into the vftable indices.
+        MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
+      }
     } else {
       // Add the entry.
       MethodVTableIndices[MD] = CurrentIndex++;
@@ -2279,6 +2322,11 @@
     //   If a class has an implicitly-defined virtual destructor, 
     //   its entries come after the declared virtual function pointers.
 
+    if (isMicrosoftABI()) {
+      ErrorUnsupported("implicit virtual destructor in the Microsoft ABI",
+                       ImplicitVirtualDtor->getLocation());
+    }
+
     // Add the complete dtor.
     MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] = 
       CurrentIndex++;
@@ -2358,7 +2406,8 @@
                           Builder.vtable_component_begin(),
                           VTableThunks.size(),
                           VTableThunks.data(),
-                          Builder.getAddressPoints());
+                          Builder.getAddressPoints(),
+                          Builder.isMicrosoftABI());
 }
 
 void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
@@ -2398,6 +2447,14 @@
   }
 }
 
+void VTableContext::ErrorUnsupported(StringRef Feature,
+                                     SourceLocation Location) {
+  clang::DiagnosticsEngine &Diags = Context.getDiagnostics();
+  unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+                                  "v-table layout for %0 is not supported yet");
+  Diags.Report(Context.getFullLoc(Location), DiagID) << Feature;
+}
+
 VTableLayout *VTableContext::createConstructionVTableLayout(
                                           const CXXRecordDecl *MostDerivedClass,
                                           CharUnits MostDerivedClassOffset,

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Mon Jan 21 07:02:41 2013
@@ -207,7 +207,7 @@
 }
 
 void MicrosoftCXXABI::EmitVTables(const CXXRecordDecl *Class) {
-  // FIXME: implement
+  CGM.getVTables().GenerateClassData(CGM.getVTableLinkage(Class), Class);
 }
 
 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp Mon Jan 21 07:02:41 2013
@@ -22,3 +22,14 @@
 // CHECK: ret
 }
 
+struct B {
+  virtual ~B();
+  virtual void foo();
+};
+
+void check_vftable_offset() {
+  B b;
+// The vftable pointer should point at the beginning of the vftable.
+// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %struct.B* {{.*}} to i8***
+// CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7B@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]
+}

Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp?rev=173035&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp Mon Jan 21 07:02:41 2013
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o - > %t 2>&1
+// RUN: FileCheck --check-prefix=EMITS-VTABLE %s < %t
+// RUN: FileCheck --check-prefix=CHECK-A %s < %t
+// RUN: FileCheck --check-prefix=CHECK-B %s < %t
+// RUN: FileCheck --check-prefix=CHECK-C %s < %t
+// RUN: FileCheck --check-prefix=CHECK-D %s < %t
+// RUN: FileCheck --check-prefix=CHECK-E %s < %t
+// RUN: FileCheck --check-prefix=CHECK-F %s < %t
+// RUN: FileCheck --check-prefix=CHECK-G %s < %t
+
+struct A {
+  // CHECK-A: Vtable for 'A' (3 entries)
+  // CHECK-A-NEXT: 0 | void A::f()
+  // CHECK-A-NEXT: 1 | void A::g()
+  // CHECK-A-NEXT: 2 | void A::h()
+  // EMITS-VTABLE: @"\01??_7A@@6B@" = unnamed_addr constant [3 x i8*]
+  virtual void f();
+  virtual void g();
+  virtual void h();
+  int ia;
+};
+void A::f() {}
+
+struct B : A {
+  // CHECK-B: Vtable for 'B' (5 entries)
+  // CHECK-B-NEXT: 0 | void B::f()
+  // CHECK-B-NEXT: 1 | void A::g()
+  // CHECK-B-NEXT: 2 | void A::h()
+  // CHECK-B-NEXT: 3 | void B::i()
+  // CHECK-B-NEXT: 4 | void B::j()
+  // EMITS-VTABLE: @"\01??_7B@@6B@" = unnamed_addr constant [5 x i8*]
+  virtual void f();  // overrides A::f()
+  virtual void i();
+  virtual void j();
+};
+void B::f() {}
+
+struct C {
+  // CHECK-C: Vtable for 'C' (2 entries)
+  // CHECK-C-NEXT: 0 | C::~C()
+  // CHECK-C-NEXT: 1 | void C::f()
+  // CHECK-C: VTable indices for 'C' (2 entries).
+  // CHECK-C-NEXT: 0 | C::~C()
+  // CHECK-C-NEXT: 1 | void C::f()
+  // Never used, so doesn't emit a vtable.
+  virtual ~C();
+
+  virtual void f();
+};
+void C::f() {}
+
+struct D {
+  // CHECK-D: Vtable for 'D' (2 entries)
+  // CHECK-D-NEXT: 0 | void D::f()
+  // CHECK-D-NEXT: 1 | D::~D()
+  // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]
+  virtual void f();
+
+  virtual ~D();
+};
+void D::f() {}
+
+struct E : A {
+  // CHECK-E: Vtable for 'E' (5 entries)
+  // CHECK-E-NEXT: 0 | void A::f()
+  // CHECK-E-NEXT: 1 | void A::g()
+  // CHECK-E-NEXT: 2 | void A::h()
+  // CHECK-E-NEXT: 3 | E::~E()
+  // CHECK-E-NEXT: 4 | void E::i()
+  // CHECK-E: VTable indices for 'E' (2 entries).
+  // CHECK-E-NEXT: 3 | E::~E()
+  // CHECK-E-NEXT: 4 | void E::i()
+
+  // Never used, so doesn't emit a vtable.
+  virtual ~E();
+  virtual void i();
+};
+void E::i() {}
+
+struct F : A {
+  // CHECK-F: Vtable for 'F' (5 entries)
+  // CHECK-F-NEXT: 0 | void A::f()
+  // CHECK-F-NEXT: 1 | void A::g()
+  // CHECK-F-NEXT: 2 | void A::h()
+  // CHECK-F-NEXT: 3 | void F::i()
+  // CHECK-F-NEXT: 4 | F::~F()
+  // CHECK-F: VTable indices for 'F' (2 entries).
+  // CHECK-F-NEXT: 3 | void F::i()
+  // CHECK-F-NEXT: 4 | F::~F()
+  // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]
+  virtual void i();
+  virtual ~F();
+};
+void F::i() {}
+
+struct G : E {
+  // CHECK-G: Vtable for 'G' (6 entries)
+  // CHECK-G-NEXT: 0 | void G::f()
+  // CHECK-G-NEXT: 1 | void A::g()
+  // CHECK-G-NEXT: 2 | void A::h()
+  // CHECK-G-NEXT: 3 | G::~G()
+  // CHECK-G-NEXT: 4 | void E::i()
+  // CHECK-G-NEXT: 5 | void G::j()
+  // CHECK-G: VTable indices for 'G' (3 entries).
+  // CHECK-G-NEXT: 0 | void G::f()
+  // CHECK-G-NEXT: 3 | G::~G()
+  // CHECK-G-NEXT: 5 | void G::j()
+  // Never used, so doesn't emit a vtable.
+  virtual void f();  // overrides A::f()
+  virtual ~G();
+  virtual void j();
+};
+void G::j() {}

Propchange: cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF





More information about the cfe-commits mailing list