[cfe-commits] r105805 - in /cfe/trunk: lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/mangle-ms.cpp

Charles Davis cdavis at mines.edu
Thu Jun 10 20:07:33 PDT 2010


Author: cdavis
Date: Thu Jun 10 22:07:32 2010
New Revision: 105805

URL: http://llvm.org/viewvc/llvm-project?rev=105805&view=rev
Log:
Start implementing the Microsoft-style name mangler. Mangle simple names
(but not their types; that's later).

NOTE: Right now, variables in the global namespace don't get mangled, even
though they're supposed to be. This is because the default mangler
implements the shouldMangleDeclName() method that tells clang not to mangle
them. This will be fixed in a later patch.

Added:
    cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
Modified:
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=105805&r1=105804&r2=105805&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Thu Jun 10 22:07:32 2010
@@ -29,6 +29,35 @@
 
 namespace {
 
+/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
+/// Microsoft Visual C++ ABI.
+class MicrosoftCXXNameMangler {
+  MangleContext &Context;
+  llvm::raw_svector_ostream Out;
+
+  ASTContext &getASTContext() const { return Context.getASTContext(); }
+
+public:
+  MicrosoftCXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res)
+  : Context(C), Out(Res) { }
+
+  llvm::raw_svector_ostream &getStream() { return Out; }
+
+  void mangle(const NamedDecl *D, llvm::StringRef Prefix = "?");
+  void mangleName(const NamedDecl *ND);
+
+private:
+  void mangleUnqualifiedName(const NamedDecl *ND) {
+    mangleUnqualifiedName(ND, ND->getDeclName());
+  }
+  void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
+  void mangleSourceName(const IdentifierInfo *II);
+  void manglePostfix(const DeclContext *DC, bool NoFunction=false);
+
+  void mangleObjCMethodName(const ObjCMethodDecl *MD);
+
+};
+
 /// MicrosoftMangleContext - Overrides the default MangleContext for the
 /// Microsoft Visual C++ ABI.
 class MicrosoftMangleContext : public MangleContext {
@@ -72,9 +101,176 @@
 
 }
 
+void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
+                                     llvm::StringRef Prefix) {
+  // MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
+  // Therefore it's really important that we don't decorate the
+  // name with leading underscores or leading/trailing at signs. So, emit a
+  // asm marker at the start so we get the name right.
+  Out << '\01';  // LLVM IR Marker for __asm("foo")
+
+  // Any decl can be declared with __asm("foo") on it, and this takes precedence
+  // over all other naming in the .o file.
+  if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
+    // If we have an asm name, then we use it as the mangling.
+    Out << ALA->getLabel();
+    return;
+  }
+
+  // <mangled-name> ::= ? <name> <type>
+  Out << Prefix;
+  mangleName(D);
+  // TODO: Mangle type.
+}
+
+void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
+  // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
+  const DeclContext *DC = ND->getDeclContext();
+
+  // Always start with the unqualified name.
+  mangleUnqualifiedName(ND);    
+
+  // If this is an extern variable declared locally, the relevant DeclContext
+  // is that of the containing namespace, or the translation unit.
+  if (isa<FunctionDecl>(DC) && ND->hasLinkage())
+    while (!DC->isNamespace() && !DC->isTranslationUnit())
+      DC = DC->getParent();
+
+  manglePostfix(DC);
+
+  // Terminate the whole name with an '@'.
+  Out << '@';
+}
+
+void
+MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+                                               DeclarationName Name) {
+  //  <unqualified-name> ::= <operator-name>
+  //                     ::= <ctor-dtor-name>
+  //                     ::= <source-name>
+  switch (Name.getNameKind()) {
+    case DeclarationName::Identifier: {
+      if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+        mangleSourceName(II);
+        break;
+      }
+      
+      // Otherwise, an anonymous entity.  We must have a declaration.
+      assert(ND && "mangling empty name without declaration");
+      
+      if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
+        if (NS->isAnonymousNamespace()) {
+          Out << "?A";
+          break;
+        }
+      }
+      
+      // We must have an anonymous struct.
+      const TagDecl *TD = cast<TagDecl>(ND);
+      if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
+        assert(TD->getDeclContext() == D->getDeclContext() &&
+               "Typedef should not be in another decl context!");
+        assert(D->getDeclName().getAsIdentifierInfo() &&
+               "Typedef was not named!");
+        mangleSourceName(D->getDeclName().getAsIdentifierInfo());
+        break;
+      }
+
+      // TODO: How does VC mangle anonymous structs?
+      assert(false && "Don't know how to mangle anonymous types yet!");
+      break;
+    }
+      
+    case DeclarationName::ObjCZeroArgSelector:
+    case DeclarationName::ObjCOneArgSelector:
+    case DeclarationName::ObjCMultiArgSelector:
+      assert(false && "Can't mangle Objective-C selector names here!");
+      break;
+      
+    case DeclarationName::CXXConstructorName:
+      assert(false && "Can't mangle constructors yet!");
+      break;
+      
+    case DeclarationName::CXXDestructorName:
+      assert(false && "Can't mangle destructors yet!");
+      break;
+      
+    case DeclarationName::CXXConversionFunctionName:
+      // <operator-name> ::= ?B # (cast)
+      // The target type is encoded as the return type.
+      Out << "?B";
+      break;
+      
+    case DeclarationName::CXXOperatorName:
+      assert(false && "Can't mangle operators yet!");
+      
+    case DeclarationName::CXXLiteralOperatorName:
+      // FIXME: Was this added in VS2010? Does MS even know how to mangle this?
+      assert(false && "Don't know how to mangle literal operators yet!");
+      break;
+      
+    case DeclarationName::CXXUsingDirective:
+      assert(false && "Can't mangle a using directive name!");
+      break;
+  }
+}
+
+void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
+                                            bool NoFunction) {
+  // <postfix> ::= <unqualified-name> [<postfix>]
+  //           ::= <template-postfix> <template-args> [<postfix>]
+  //           ::= <template-param>
+  //           ::= <substitution> [<postfix>]
+
+  if (!DC) return;
+
+  while (isa<LinkageSpecDecl>(DC))
+    DC = DC->getParent();
+
+  if (DC->isTranslationUnit())
+    return;
+
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
+    llvm::SmallString<64> Name;
+    Context.mangleBlock(BD, Name);
+    Out << Name << '@';
+    return manglePostfix(DC->getParent(), NoFunction);
+  }
+
+  if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
+    return;
+  else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
+    mangleObjCMethodName(Method);
+  else {
+    mangleUnqualifiedName(cast<NamedDecl>(DC));
+    manglePostfix(DC->getParent(), NoFunction);
+  }
+}
+
+void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
+  // <source name> ::= <identifier> @
+  Out << II->getName() << '@';
+}
+
+void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
+  llvm::SmallString<64> Buffer;
+  MiscNameMangler(Context, Buffer).mangleObjCMethodName(MD);
+  Out << Buffer;
+}
+
 void MicrosoftMangleContext::mangleName(const NamedDecl *D,
                                         llvm::SmallVectorImpl<char> &Name) {
-  assert(false && "Can't yet mangle names!");
+  assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
+         "Invalid mangleName() call, argument is not a variable or function!");
+  assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
+         "Invalid mangleName() call on 'structor decl!");
+
+  PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+                                 getASTContext().getSourceManager(),
+                                 "Mangling declaration");
+
+  MicrosoftCXXNameMangler Mangler(*this, Name);
+  return Mangler.mangle(D);
 }
 void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,
                                          const ThunkInfo &Thunk,

Added: cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms.cpp?rev=105805&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms.cpp Thu Jun 10 22:07:32 2010
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-apple-darwin10 | FileCheck %s
+
+//int a; // FIXME: All names not in an extern "C" block are mangled
+
+namespace N { int b; }
+// CHECK: @"\01?b at N@@"





More information about the cfe-commits mailing list