[PATCH] [ms-cxxabi] Implement vbtable name mangling

Reid Kleckner rnk at google.com
Sat Apr 6 15:44:25 PDT 2013


Hi rjmccall,

In Itanium, dynamic classes have one vtable with several different
address points for dynamic base classes that can't share vtables.

In the MS C++ ABI, each vbtable that can't be shared gets its own
symbol, similar to how ctor vtables work in Itanium.  However, instead
of mangling the subobject offset into the symbol, the unique portions of
the inheritance path are mangled into the symbol to make it unique.

Future patches that actually use this mangling with tests are
forthcoming.

http://llvm-reviews.chandlerc.com/D636

Files:
  include/clang/AST/DeclCXX.h
  include/clang/AST/Mangle.h
  lib/AST/DeclCXX.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp

Index: include/clang/AST/DeclCXX.h
===================================================================
--- include/clang/AST/DeclCXX.h
+++ include/clang/AST/DeclCXX.h
@@ -705,6 +705,10 @@
   /// are not the current instantiation.
   bool hasAnyDependentBases() const;
 
+  /// \brief Determine whether this class has any direct virtual bases.  Classes
+  /// with direct virtual bases have a vbtable in the MS ABI.
+  bool hasDirectVirtualBase() const;
+
   /// Iterator access to method members.  The method iterator visits
   /// all method members of the class, including non-instance methods,
   /// special methods, etc.
Index: include/clang/AST/Mangle.h
===================================================================
--- include/clang/AST/Mangle.h
+++ include/clang/AST/Mangle.h
@@ -110,6 +110,9 @@
                                raw_ostream &) = 0;
   virtual void mangleCXXVTT(const CXXRecordDecl *RD,
                             raw_ostream &) = 0;
+  virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
+                                llvm::ArrayRef<const CXXRecordDecl *> BasePath,
+                                raw_ostream &Out) = 0;
   virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
                                    const CXXRecordDecl *Type,
                                    raw_ostream &) = 0;
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -379,6 +379,15 @@
   return !forallBases(SawBase, 0);
 }
 
+bool CXXRecordDecl::hasDirectVirtualBase() const {
+  for (CXXRecordDecl::base_class_const_iterator I = this->bases_begin(),
+       E = this->bases_end(); I != E; ++I) {
+    if (I->isVirtual())
+      return true;
+  }
+  return false;
+}
+
 bool CXXRecordDecl::isTriviallyCopyable() const {
   // C++0x [class]p5:
   //   A trivially copyable class is a class that:
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -130,6 +130,9 @@
                        raw_ostream &);
   void mangleCXXVTT(const CXXRecordDecl *RD,
                     raw_ostream &);
+  void mangleCXXVBTable(const CXXRecordDecl *Derived,
+                        llvm::ArrayRef<const CXXRecordDecl *> BasePath,
+                        raw_ostream &Out);
   void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
                            const CXXRecordDecl *Type,
                            raw_ostream &);
@@ -3546,6 +3549,13 @@
   Mangler.mangleNameOrStandardSubstitution(RD);
 }
 
+void ItaniumMangleContext::
+mangleCXXVBTable(const CXXRecordDecl *Derived,
+                 llvm::ArrayRef<const CXXRecordDecl *> BasePath,
+                 raw_ostream &Out) {
+  llvm_unreachable("The Itanium C++ ABI does not have virtual base tables!");
+}
+
 void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
                                                int64_t Offset,
                                                const CXXRecordDecl *Type,
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -145,6 +145,9 @@
                                raw_ostream &);
   virtual void mangleCXXVTT(const CXXRecordDecl *RD,
                             raw_ostream &);
+  virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
+                                llvm::ArrayRef<const CXXRecordDecl *> BasePath,
+                                raw_ostream &Out);
   virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
                                    const CXXRecordDecl *Type,
                                    raw_ostream &);
@@ -1727,15 +1730,56 @@
   // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
   // is always '6' for vftables and '7' for vbtables. (The difference is
   // beyond me.)
-  // TODO: vbtables.
   MicrosoftCXXNameMangler Mangler(*this, Out);
   Mangler.getStream() << "\01??_7";
   Mangler.mangleName(RD);
   Mangler.getStream() << "6B";
   // TODO: If the class has more than one vtable, mangle in the class it came
   // from.
   Mangler.getStream() << '@';
 }
+
+void MicrosoftMangleContext::
+mangleCXXVBTable(const CXXRecordDecl *Derived,
+                 llvm::ArrayRef<const CXXRecordDecl *> BasePath,
+                 raw_ostream &Out) {
+  assert(BasePath[0] == Derived);
+  // vbtables are mangled like vftables except they use '8' and '7' instead of
+  // '7' and '6' as above.
+  MicrosoftCXXNameMangler Mangler(*this, Out);
+  Mangler.getStream() << "\01??_8";
+  Mangler.mangleName(Derived);
+  Mangler.getStream() << "7B";  // '7' for vbtable, 'B' for const.
+
+  if (BasePath.size() > 1) {
+    for (llvm::ArrayRef<const CXXRecordDecl *>::reverse_iterator
+         I = BasePath.rbegin(), E = BasePath.rend() - 1; I != E;) {
+      const CXXRecordDecl *Base = *I;
+      assert(Base != Derived);
+      ++I;
+      // If Base is the only non-virtual base of its parent, we can skip this
+      // link in the path and still guarantee that this is a unique symbol.
+      if ((*I)->getNumBases() == 1 && !(*I)->hasDirectVirtualBase())
+        continue;
+      Mangler.mangleName(Base);
+    }
+  } else {
+    // Emit Derived if it is not the first class in its hierarchy with a
+    // vbtable.  Otherwise, skip it.
+    unsigned NumDirectVBases = 0;
+    for (CXXRecordDecl::base_class_const_iterator I = Derived->bases_begin(),
+         E = Derived->bases_end(); I != E; ++I) {
+      if (I->isVirtual())
+        ++NumDirectVBases;
+    }
+    assert(Derived->getNumVBases() >= NumDirectVBases);
+    if (Derived->getNumVBases() > NumDirectVBases)
+      Mangler.mangleName(Derived);
+  }
+
+  Mangler.getStream() << '@';
+}
+
 void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
                                           raw_ostream &) {
   llvm_unreachable("The MS C++ ABI does not have virtual table tables!");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D636.1.patch
Type: text/x-patch
Size: 6126 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130406/eac9011e/attachment.bin>


More information about the cfe-commits mailing list