]> granicus.if.org Git - clang/commitdiff
Add basic support for C++ name mangling according to the Itanium C++
authorDouglas Gregor <dgregor@apple.com>
Fri, 13 Feb 2009 00:10:09 +0000 (00:10 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 13 Feb 2009 00:10:09 +0000 (00:10 +0000)
ABI to the CodeGen library. Since C++ code-generation is so
incomplete, we can't exercise much of this mangling code. However, a
few smoke tests show that it's doing the same thing as GCC. When C++
codegen matures, we'll extend the ABI tester to verify name-mangling
as well, and complete the implementation here.

At this point, the major client of name mangling is in the uses of the
new "overloadable" attribute in C, which allows overloading. Any
"overloadable" function in C (or in an extern "C" block in C++) will
be mangled the same way that the corresponding C++ function would be
mangled.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64413 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclBase.h
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CMakeLists.txt
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/Mangle.cpp [new file with mode: 0644]
lib/CodeGen/Mangle.h [new file with mode: 0644]
test/CodeGen/overloadable.c [new file with mode: 0644]
test/CodeGenCXX/mangle.cpp [new file with mode: 0644]

index 5c03b332ef9233561ce796a569ae8ccc019d9e65..30d994b9df4c6c0869527b1ae85caeee16323fe8 100644 (file)
@@ -474,6 +474,10 @@ public:
     return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
   }
 
+  bool isTranslationUnit() const {
+    return DeclKind == Decl::TranslationUnit;
+  }
+
   bool isRecord() const {
     return DeclKind == Decl::Record || DeclKind == Decl::CXXRecord;
   }
index a32b78dedb95f37fc780a5d0455f7ea6495daed9..3b912ce3d65445d55c4222b388f950c8d5ab91ec 100644 (file)
@@ -101,7 +101,7 @@ CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D,
 
   std::string ContextName;
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl))
-    ContextName = FD->getNameAsString();
+    ContextName = CGM.getMangledName(FD)->getName();
   else if (isa<ObjCMethodDecl>(CurFuncDecl))
     ContextName = std::string(CurFn->getNameStart(), 
                               CurFn->getNameStart() + CurFn->getNameLen());
@@ -164,7 +164,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
       // A normal fixed sized variable becomes an alloca in the entry block.
       const llvm::Type *LTy = ConvertType(Ty);
       llvm::AllocaInst *Alloc =
-        CreateTempAlloca(LTy, D.getIdentifier()->getName());
+        CreateTempAlloca(LTy, CGM.getMangledName(&D)->getName());
       unsigned align = getContext().getTypeAlign(Ty);
       if (const AlignedAttr* AA = D.getAttr<AlignedAttr>())
         align = std::max(align, AA->getAlignment());
index 7ef6fdf2af964641e4292dbf23314c72dc2e642f..83fbd72f9090588315ebbdb64c9924482eae236b 100644 (file)
@@ -714,7 +714,7 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
 
   std::string FunctionName;
   if(const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) {
-    FunctionName = FD->getNameAsString();
+    FunctionName = CGM.getMangledName(FD)->getName();
   } else {
     // Just get the mangled name.
     FunctionName = CurFn->getName();
index c59853a1b7cfc87ea8b7ebe955cdf251576e575b..1820c0b9f03b040e9bc96e56571a44e03f1fc542 100644 (file)
@@ -18,5 +18,6 @@ add_clang_library(clangCodeGen
   CodeGenFunction.cpp
   CodeGenModule.cpp
   CodeGenTypes.cpp
+  Mangle.cpp
   ModuleBuilder.cpp
   )
index b46d24a2fcb8c284469572092056476ac7856217..322f8bf565a9abe39cb2aec908cc3c824c848d45 100644 (file)
@@ -171,7 +171,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
   if (CGDebugInfo *DI = CGM.getDebugInfo()) {
     DI->setLocation(StartLoc);
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-      DI->EmitFunctionStart(FD->getIdentifier()->getName(),
+      DI->EmitFunctionStart(CGM.getMangledName(FD)->getName(),
                             RetTy, CurFn, Builder);
     } else {
       // Just use LLVM function name.
index a3b79562d140ec890ef64ccf9ad5ee037e77dffd..df4a3d07636d193098ff6232a6b03c62f616e8b5 100644 (file)
@@ -16,6 +16,7 @@
 #include "CodeGenFunction.h"
 #include "CGCall.h"
 #include "CGObjCRuntime.h"
+#include "Mangle.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclCXX.h"
@@ -148,6 +149,29 @@ static void setGlobalVisibility(llvm::GlobalValue *GV,
   }
 }
 
+/// \brief Retrieves the mangled name for the given declaration.
+///
+/// If the given declaration requires a mangled name, returns an
+/// IdentifierInfo* containing the mangled name. Otherwise, returns
+/// the name of the declaration as an identifier.
+///
+/// FIXME: Returning an IdentifierInfo* here is a total hack. We
+/// really need some kind of string abstraction that either stores a
+/// mangled name or stores an IdentifierInfo*. This will require
+/// changes to the GlobalDeclMap, too.
+///
+/// FIXME: Performance here is going to be terribly until we start
+/// caching mangled names. However, we should fix the problem above
+/// first.
+IdentifierInfo *CodeGenModule::getMangledName(const NamedDecl *ND) const {
+  std::string Name;
+  llvm::raw_string_ostream Out(Name);
+  if (!mangleName(ND, Context, Out))
+    return ND->getIdentifier();
+
+  return &Context.Idents.get(Out.str());
+}
+
 /// AddGlobalCtor - Add a function to the list that will be called before
 /// main() runs.
 void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) {
@@ -340,9 +364,10 @@ void CodeGenModule::EmitAliases() {
     llvm::GlobalValue *GA = 
       new llvm::GlobalAlias(aliasee->getType(),
                             llvm::Function::ExternalLinkage,
-                            D->getNameAsString(), aliasee, &getModule());
+                            getMangledName(D)->getName(), aliasee, 
+                            &getModule());
     
-    llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
+    llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
     if (Entry) {
       // If we created a dummy function for this then replace it.
       GA->takeName(Entry);
@@ -377,7 +402,7 @@ void CodeGenModule::EmitStatics() {
       // global symbol map.
       // FIXME: This is missing some important cases. For example, we
       // need to check for uses in an alias and in a constructor.
-      if (!GlobalDeclMap.count(D->getIdentifier())) {
+      if (!GlobalDeclMap.count(getMangledName(D))) {
         i++;
         continue;
       }
@@ -498,13 +523,13 @@ void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) {
   const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
 
   // Lookup the entry, lazily creating it if necessary.
-  llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
+  llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
   if (!Entry) {
     llvm::GlobalVariable *GV = 
       new llvm::GlobalVariable(Ty, false, 
                                llvm::GlobalValue::ExternalLinkage,
-                               0, D->getNameAsString(), &getModule(), 0,
-                               ASTTy.getAddressSpace());
+                               0, getMangledName(D)->getName(), &getModule(), 
+                               0, ASTTy.getAddressSpace());
     Entry = GV;
 
     // Handle things which are present even on external declarations.
@@ -545,14 +570,14 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
   }
   const llvm::Type* InitType = Init->getType();
 
-  llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
+  llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
   llvm::GlobalVariable *GV = cast_or_null<llvm::GlobalVariable>(Entry);
   
   if (!GV) {
     GV = new llvm::GlobalVariable(InitType, false, 
                                   llvm::GlobalValue::ExternalLinkage,
-                                  0, D->getNameAsString(), &getModule(), 0,
-                                  ASTTy.getAddressSpace());
+                                  0, getMangledName(D)->getName(), 
+                                  &getModule(), 0, ASTTy.getAddressSpace());
   } else if (GV->getType() != 
              llvm::PointerType::get(InitType, ASTTy.getAddressSpace())) {
     // We have a definition after a prototype with the wrong type.
@@ -575,8 +600,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
     // Make a new global with the correct type
     GV = new llvm::GlobalVariable(InitType, false, 
                                   llvm::GlobalValue::ExternalLinkage,
-                                  0, D->getNameAsString(), &getModule(), 0,
-                                  ASTTy.getAddressSpace());
+                                  0, getMangledName(D)->getName(), 
+                                  &getModule(), 0, ASTTy.getAddressSpace());
     // Steal the name of the old global
     GV->takeName(OldGV);
 
@@ -672,7 +697,8 @@ CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D) {
   const llvm::Type *Ty = getTypes().ConvertType(D->getType());
   llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), 
                                              llvm::Function::ExternalLinkage,
-                                             D->getNameAsString(),&getModule());
+                                             getMangledName(D)->getName(),
+                                             &getModule());
   SetFunctionAttributes(D, F);
   return F;
 }
@@ -683,7 +709,7 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
   const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
   
   // Lookup the entry, lazily creating it if necessary.
-  llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
+  llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
   if (!Entry)
     Entry = EmitForwardFunctionDefinition(D);
 
@@ -691,7 +717,7 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
 }
 
 void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
-  llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
+  llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
   if (!Entry) {
     Entry = EmitForwardFunctionDefinition(D);
   } else {
index 0c3964fd5f9157fe8ab113ea324a0762c6cfbac4..d8719efabfd265f85405e46733903fd42fd8f920 100644 (file)
@@ -88,6 +88,7 @@ class CodeGenModule {
   /// decl, they should be bitcasted on retrieval. Also note that the
   /// globals are keyed on their source name, not the global name
   /// (which may change with attributes such as asm-labels).
+  /// This key to this map should be generated using getMangledName().
   llvm::DenseMap<IdentifierInfo*, llvm::GlobalValue*> GlobalDeclMap;
 
   /// Aliases - List of aliases in module. These cannot be emitted
@@ -257,6 +258,9 @@ public:
                               const Decl *TargetDecl,
                               AttributeListType &PAL);
 
+  IdentifierInfo *getMangledName(const NamedDecl *ND) const;
+
+
 private:
   /// SetFunctionAttributesForDefinition - Set function attributes
   /// specific to a function definition.
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
new file mode 100644 (file)
index 0000000..a97ac58
--- /dev/null
@@ -0,0 +1,516 @@
+//===--------------------- Mangle.cpp - Mangle C++ Names ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements C++ name mangling according to the Itanium C++ ABI,
+// which is used in GCC 3.2 and newer (and many compilers that are
+// ABI-compatible with GCC):
+//
+//   http://www.codesourcery.com/public/cxx-abi/abi.html
+//
+//===----------------------------------------------------------------------===//
+#include "Mangle.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+  class VISIBILITY_HIDDEN CXXNameMangler {
+    ASTContext &Context;
+    llvm::raw_ostream &Out;
+
+  public:
+    CXXNameMangler(ASTContext &C, llvm::raw_ostream &os)
+      : Context(C), Out(os) { }
+
+    bool mangle(const NamedDecl *D);
+    void mangleFunctionEncoding(const FunctionDecl *FD);
+    void mangleName(const NamedDecl *ND);
+    void mangleUnqualifiedName(const NamedDecl *ND);
+    void mangleSourceName(const IdentifierInfo *II);
+    void mangleNestedName(const NamedDecl *ND);
+    void manglePrefix(const DeclContext *DC);
+    void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
+    void mangleCVQualifiers(unsigned Quals);
+    void mangleType(QualType T);
+    void mangleType(const BuiltinType *T);
+    void mangleType(const FunctionType *T);
+    void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType);
+    void mangleType(const TagType *T);
+    void mangleType(const ArrayType *T);
+    void mangleType(const MemberPointerType *T);
+    void mangleType(const TemplateTypeParmType *T);
+    void mangleExpression(Expr *E);
+  };
+}
+
+
+bool CXXNameMangler::mangle(const NamedDecl *D) {
+  // <mangled-name> ::= _Z <encoding>
+  //            ::= <data name>
+  //            ::= <special-name>
+
+  // FIXME: Actually use a visitor to decode these?
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    bool RequiresMangling = false;
+    // Clang's "overloadable" attribute extension to C/C++
+    if (FD->getAttr<OverloadableAttr>())
+      RequiresMangling = true;
+    else if (Context.getLangOptions().CPlusPlus) {
+      RequiresMangling = true;
+      if (isa<LinkageSpecDecl>(FD->getDeclContext()) &&
+          cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() 
+            == LinkageSpecDecl::lang_c) {
+        // Entities with C linkage are not mangled.
+        RequiresMangling = false;
+      } 
+    }
+
+    if (RequiresMangling) {
+      Out << "_Z";
+      mangleFunctionEncoding(FD);
+      return true;
+    }
+  } 
+
+  return false;
+}
+
+void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+  // <encoding> ::= <function name> <bare-function-type>
+  mangleName(FD);
+  mangleBareFunctionType(FD->getType()->getAsFunctionType(), false);
+}
+
+static bool isStdNamespace(const DeclContext *DC) {
+  if (!DC->isNamespace() || !DC->getParent()->isTranslationUnit())
+    return false;
+
+  const NamespaceDecl *NS = cast<NamespaceDecl>(DC);
+  const IdentifierInfo *Name = NS->getIdentifier();
+  if (Name->getLength() != 3)
+    return false;
+
+  const char *Str = Name->getName();
+  if (Str[0] != 's' || Str[1] != 't' || Str[2] != 'd')
+    return false;
+      
+  return true;
+}
+
+void CXXNameMangler::mangleName(const NamedDecl *ND) {
+  //  <name> ::= <nested-name>
+  //         ::= <unscoped-name>
+  //         ::= <unscoped-template-name> <template-args>
+  //         ::= <local-name>     # See Scope Encoding below
+  //
+  //  <unscoped-name> ::= <unqualified-name>
+  //                  ::= St <unqualified-name>   # ::std::
+  if (ND->getDeclContext()->isTranslationUnit()) 
+    mangleUnqualifiedName(ND);
+  else if (isStdNamespace(ND->getDeclContext())) {
+    Out << "St";
+    mangleUnqualifiedName(ND);
+  } else {
+    mangleNestedName(ND);
+  }
+}
+
+void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
+  //  <unqualified-name> ::= <operator-name>
+  //                     ::= <ctor-dtor-name>  
+  //                     ::= <source-name>   
+  DeclarationName Name = ND->getDeclName();
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+    mangleSourceName(Name.getAsIdentifierInfo());
+    break;
+
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    assert(false && "Can't mangle Objective-C selector names here!");
+    break;
+
+  case DeclarationName::CXXConstructorName:
+    // <ctor-dtor-name> ::= C1  # complete object constructor
+    //                  ::= C2  # base object constructor
+    //                  ::= C3  # complete object allocating constructor
+    //
+    // FIXME: We don't even have all of these constructors
+    // in the AST yet.
+    Out << "C1";
+    break;
+
+  case DeclarationName::CXXDestructorName:
+    // <ctor-dtor-name> ::= D0  # deleting destructor
+    //                  ::= D1  # complete object destructor
+    //                  ::= D2  # base object destructor
+    //
+    // FIXME: We don't even have all of these destructors in the AST
+    // yet.
+    Out << "D0";
+    break;
+
+  case DeclarationName::CXXConversionFunctionName:
+    assert(false && "Not sure how to mangle conversion functions yet");
+    break;
+
+  case DeclarationName::CXXOperatorName:
+    mangleOperatorName(Name.getCXXOverloadedOperator(),
+                       cast<FunctionDecl>(ND)->getNumParams());
+    break;
+
+  case DeclarationName::CXXUsingDirective:
+    assert(false && "Can't mangle a using directive name!");
+  }
+}
+
+void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
+  // <source-name> ::= <positive length number> <identifier>
+  // <number> ::= [n] <non-negative decimal integer>
+  // <identifier> ::= <unqualified source code identifier>
+  Out << II->getLength() << II->getName();
+}
+
+void CXXNameMangler::mangleNestedName(const NamedDecl *ND) {
+  // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
+  //               ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+  // FIXME: no template support
+  Out << 'N';
+  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND))
+    mangleCVQualifiers(Method->getTypeQualifiers());
+  manglePrefix(ND->getDeclContext());
+  mangleUnqualifiedName(ND);
+  Out << 'E';
+}
+
+void CXXNameMangler::manglePrefix(const DeclContext *DC) {
+  //  <prefix> ::= <prefix> <unqualified-name>
+  //           ::= <template-prefix> <template-args>
+  //           ::= <template-param>
+  //           ::= # empty
+  //           ::= <substitution>
+  // FIXME: We only handle mangling of namespaces and classes at the moment.
+  if (DC->getParent() != DC)
+    manglePrefix(DC);
+
+  if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(DC))
+    mangleSourceName(Namespace->getIdentifier());
+  else if (const RecordDecl *Record = dyn_cast<RecordDecl>(DC))
+    mangleSourceName(Record->getIdentifier());
+}
+
+void 
+CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
+  switch (OO) {
+  // <operator-name> ::= nw     # new           
+  case OO_New: Out << "nw"; break;
+  //              ::= na        # new[]
+  case OO_Array_New: Out << "na"; break;
+  //              ::= dl        # delete     
+  case OO_Delete: Out << "dl"; break;
+  //              ::= da        # delete[]      
+  case OO_Array_Delete: Out << "da"; break;
+  //              ::= ps        # + (unary)
+  //              ::= pl        # +
+  case OO_Plus: Out << (Arity == 1? "ps" : "pl"); break;
+  //              ::= ng        # - (unary)     
+  //              ::= mi        # -             
+  case OO_Minus: Out << (Arity == 1? "ng" : "mi"); break;
+  //              ::= ad        # & (unary)     
+  //              ::= an        # &             
+  case OO_Amp: Out << (Arity == 1? "ad" : "an"); break;
+  //              ::= de        # * (unary)     
+  //              ::= ml        # *             
+  case OO_Star: Out << (Arity == 1? "de" : "ml"); break;
+  //              ::= co        # ~             
+  case OO_Tilde: Out << "co"; break;
+  //              ::= dv        # /             
+  case OO_Slash: Out << "dv"; break;
+  //              ::= rm        # %             
+  case OO_Percent: Out << "rm"; break;
+  //              ::= or        # |   
+  case OO_Pipe: Out << "or"; break;          
+  //              ::= eo        # ^             
+  case OO_Caret: Out << "eo"; break;
+  //              ::= aS        # = 
+  case OO_Equal: Out << "aS"; break;
+  //              ::= pL        # +=            
+  case OO_PlusEqual: Out << "pL"; break;
+  //              ::= mI        # -=   
+  case OO_MinusEqual: Out << "mI"; break;
+  //              ::= mL        # *=     
+  case OO_StarEqual: Out << "mL"; break;
+  //              ::= dV        # /=    
+  case OO_SlashEqual: Out << "dV"; break;
+  //              ::= rM        # %=     
+  case OO_PercentEqual: Out << "rM"; break;       
+  //              ::= aN        # &=       
+  case OO_AmpEqual: Out << "aN"; break;     
+  //              ::= oR        # |=   
+  case OO_PipeEqual: Out << "oR"; break;         
+  //              ::= eO        # ^=      
+  case OO_CaretEqual: Out << "eO"; break;      
+  //              ::= ls        # <<     
+  case OO_LessLess: Out << "ls"; break;
+  //              ::= rs        # >>   
+  case OO_GreaterGreater: Out << "rs"; break;         
+  //              ::= lS        # <<=        
+  case OO_LessLessEqual: Out << "lS"; break;   
+  //              ::= rS        # >>=       
+  case OO_GreaterGreaterEqual: Out << "rS"; break;    
+  //              ::= eq        # ==
+  case OO_EqualEqual: Out << "eq"; break;
+  //              ::= ne        # !=     
+  case OO_ExclaimEqual: Out << "ne"; break;       
+  //              ::= lt        # <        
+  case OO_Less: Out << "lt"; break;
+  //              ::= gt        # >             
+  case OO_Greater: Out << "gt"; break;
+  //              ::= le        # <=  
+  case OO_LessEqual: Out << "le"; break;
+  //              ::= ge        # >=    
+  case OO_GreaterEqual: Out << "ge"; break;
+  //              ::= nt        # !        
+  case OO_Exclaim: Out << "nt"; break;
+  //              ::= aa        # &&  
+  case OO_AmpAmp: Out << "aa"; break;
+  //              ::= oo        # || 
+  case OO_PipePipe: Out << "oo"; break;           
+  //              ::= pp        # ++   
+  case OO_PlusPlus: Out << "pp"; break;         
+  //              ::= mm        # --   
+  case OO_MinusMinus: Out << "mm"; break;
+  //              ::= cm        # ,      
+  case OO_Comma: Out << "cm"; break;       
+  //              ::= pm        # ->*      
+  case OO_ArrowStar: Out << "pm"; break;
+  //              ::= pt        # ->    
+  case OO_Arrow: Out << "pt"; break;
+  //              ::= cl        # ()            
+  case OO_Call: Out << "cl"; break;
+  //              ::= ix        # []            
+  case OO_Subscript: Out << "ix"; break;
+  // UNSUPPORTED: ::= qu        # ?
+
+  case OO_None: 
+  case NUM_OVERLOADED_OPERATORS:
+    assert(false && "Not an ovelroaded operator"); 
+    break;
+  }
+}
+
+void CXXNameMangler::mangleCVQualifiers(unsigned Quals) {
+  // <CV-qualifiers> ::= [r] [V] [K]   # restrict (C99), volatile, const
+  if (Quals & QualType::Restrict)
+    Out << 'r';
+  if (Quals & QualType::Volatile)
+    Out << 'V';
+  if (Quals & QualType::Const)
+    Out << 'K';
+}
+
+void CXXNameMangler::mangleType(QualType T) {
+  // Only operate on the canonical type!
+  T = Context.getCanonicalType(T);
+
+  // FIXME: Should we have a TypeNodes.def to make this easier? (YES!)
+
+  //  <type> ::= <CV-qualifiers> <type>
+  mangleCVQualifiers(T.getCVRQualifiers());
+
+  //         ::= <builtin-type>
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
+    mangleType(BT);
+  //         ::= <function-type>
+  else if (const FunctionType *FT = dyn_cast<FunctionType>(T.getTypePtr()))
+    mangleType(FT);
+  //         ::= <class-enum-type>
+  else if (const TagType *TT = dyn_cast<TagType>(T.getTypePtr()))
+    mangleType(TT);
+  //         ::= <array-type>
+  else if (const ArrayType *AT = dyn_cast<ArrayType>(T.getTypePtr()))
+    mangleType(AT);
+  //         ::= <pointer-to-member-type>
+  else if (const MemberPointerType *MPT 
+             = dyn_cast<MemberPointerType>(T.getTypePtr()))
+    mangleType(MPT);
+  //         ::= <template-param>
+  else if (const TemplateTypeParmType *TypeParm 
+             = dyn_cast<TemplateTypeParmType>(T.getTypePtr()))
+    mangleType(TypeParm);
+  //  FIXME: ::= <template-template-param> <template-args>
+  //  FIXME: ::= <substitution> # See Compression below
+  //         ::= P <type>   # pointer-to
+  else if (const PointerType *PT = dyn_cast<PointerType>(T.getTypePtr())) {
+    Out << 'P';
+    mangleType(PT->getPointeeType());
+  }
+  //         ::= R <type>   # reference-to
+  //         ::= O <type>   # rvalue reference-to (C++0x)
+  else if (const ReferenceType *RT = dyn_cast<ReferenceType>(T.getTypePtr())) {
+    // FIXME: rvalue references
+    Out << 'R';
+    mangleType(RT->getPointeeType());
+  }
+  //         ::= C <type>   # complex pair (C 2000)
+  else if (const ComplexType *CT = dyn_cast<ComplexType>(T.getTypePtr())) {
+    Out << 'C';
+    mangleType(CT->getElementType());
+  } else if (const VectorType *VT = dyn_cast<VectorType>(T.getTypePtr())) {
+    // GNU extension: vector types
+    Out << "U8__vector";
+    mangleType(VT->getElementType());
+  }
+  // FIXME:  ::= G <type>   # imaginary (C 2000)
+  // FIXME:  ::= U <source-name> <type>     # vendor extended type qualifier
+  else
+    assert(false && "Cannot mangle unknown type");
+}
+
+void CXXNameMangler::mangleType(const BuiltinType *T) {
+  //  <builtin-type> ::= v  # void
+  //                 ::= w  # wchar_t
+  //                 ::= b  # bool
+  //                 ::= c  # char
+  //                 ::= a  # signed char
+  //                 ::= h  # unsigned char
+  //                 ::= s  # short
+  //                 ::= t  # unsigned short
+  //                 ::= i  # int
+  //                 ::= j  # unsigned int
+  //                 ::= l  # long
+  //                 ::= m  # unsigned long
+  //                 ::= x  # long long, __int64
+  //                 ::= y  # unsigned long long, __int64
+  //                 ::= n  # __int128
+  // UNSUPPORTED:    ::= o  # unsigned __int128
+  //                 ::= f  # float
+  //                 ::= d  # double
+  //                 ::= e  # long double, __float80
+  // UNSUPPORTED:    ::= g  # __float128
+  // NOT HERE:       ::= z  # ellipsis
+  // UNSUPPORTED:    ::= Dd # IEEE 754r decimal floating point (64 bits)
+  // UNSUPPORTED:    ::= De # IEEE 754r decimal floating point (128 bits)
+  // UNSUPPORTED:    ::= Df # IEEE 754r decimal floating point (32 bits)
+  // UNSUPPORTED:    ::= Dh # IEEE 754r half-precision floating point (16 bits)
+  // UNSUPPORTED:    ::= Di # char32_t
+  // UNSUPPORTED:    ::= Ds # char16_t
+  //                 ::= u <source-name>    # vendor extended type
+  switch (T->getKind()) {
+  case BuiltinType::Void: Out << 'v'; break;
+  case BuiltinType::Bool: Out << 'b'; break;
+  case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;
+  case BuiltinType::UChar: Out << 'h'; break;
+  case BuiltinType::UShort: Out << 't'; break;
+  case BuiltinType::UInt: Out << 'j'; break;
+  case BuiltinType::ULong: Out << 'm'; break;
+  case BuiltinType::ULongLong: Out << 'y'; break;
+  case BuiltinType::SChar: Out << 'a'; break;
+  case BuiltinType::WChar: Out << 'w'; break;
+  case BuiltinType::Short: Out << 's'; break;
+  case BuiltinType::Int: Out << 'i'; break;
+  case BuiltinType::Long: Out << 'l'; break;
+  case BuiltinType::LongLong: Out << 'x'; break;
+  case BuiltinType::Float: Out << 'f'; break;
+  case BuiltinType::Double: Out << 'd'; break;
+  case BuiltinType::LongDouble: Out << 'e'; break;
+
+  case BuiltinType::Overload:
+  case BuiltinType::Dependent:
+    assert(false && 
+           "Overloaded and dependent types shouldn't get to name mangling");
+    break;
+  }
+}
+
+void CXXNameMangler::mangleType(const FunctionType *T) {
+  // <function-type> ::= F [Y] <bare-function-type> E
+  Out << 'F';
+  // FIXME: We don't have enough information in the AST to produce the
+  // 'Y' encoding for extern "C" function types.
+  mangleBareFunctionType(T, /*MangleReturnType=*/true);
+  Out << 'E';
+}
+
+void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
+                                            bool MangleReturnType) {
+  // <bare-function-type> ::= <signature type>+
+  if (MangleReturnType)
+    mangleType(T->getResultType());
+
+  const FunctionTypeProto *Proto = dyn_cast<FunctionTypeProto>(T);
+  assert(Proto && "Can't mangle K&R function prototypes");
+
+  for (FunctionTypeProto::arg_type_iterator Arg = Proto->arg_type_begin(),
+                                         ArgEnd = Proto->arg_type_end(); 
+       Arg != ArgEnd; ++Arg)
+    mangleType(*Arg);
+}
+
+void CXXNameMangler::mangleType(const TagType *T) {
+  //  <class-enum-type> ::= <name>
+  mangleName(T->getDecl());
+}
+
+void CXXNameMangler::mangleType(const ArrayType *T) {
+  // <array-type> ::= A <positive dimension number> _ <element type>
+  //              ::= A [<dimension expression>] _ <element type>
+  Out << 'A';
+  if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
+    Out << CAT->getSize();
+  else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(T))
+    mangleExpression(VAT->getSizeExpr());
+  else if (const DependentSizedArrayType *DSAT 
+             = dyn_cast<DependentSizedArrayType>(T))
+    mangleExpression(DSAT->getSizeExpr());
+
+  Out << '_';
+  mangleType(T->getElementType());
+}
+
+void CXXNameMangler::mangleType(const MemberPointerType *T) {
+  //  <pointer-to-member-type> ::= M <class type> <member type>
+  Out << 'M';
+  mangleType(QualType(T->getClass(), 0));
+  mangleType(T->getPointeeType());
+}
+
+void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
+  // <template-param> ::= T_    # first template parameter
+  //                  ::= T <parameter-2 non-negative number> _
+  if (T->getIndex() == 0)
+    Out << "T_";
+  else
+    Out << 'T' << (T->getIndex() - 1) << '_';
+}
+
+void CXXNameMangler::mangleExpression(Expr *E) {
+  assert(false && "Cannot mangle expressions yet");
+}
+
+namespace clang {
+  /// \brief Mangles the name of the declaration D and emits that name
+  /// to the given output stream.
+  ///
+  /// If the declaration D requires a mangled name, this routine will
+  /// emit that mangled name to \p os and return true. Otherwise, \p
+  /// os will be unchanged and this routine will return false. In this
+  /// case, the caller should just emit the identifier of the declaration
+  /// (\c D->getIdentifier()) as its name.
+  bool mangleName(const NamedDecl *D, ASTContext &Context, 
+                  llvm::raw_ostream &os) {
+    CXXNameMangler Mangler(Context, os);
+    return Mangler.mangle(D);
+  }
+}
+
diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h
new file mode 100644 (file)
index 0000000..404f8bd
--- /dev/null
@@ -0,0 +1,32 @@
+//===---------------------- Mangle.h - Mangle C++ Names -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements C++ name mangling according to the Itanium C++ ABI,
+// which is used in GCC 3.2 and newer (and many compilers that are
+// ABI-compatible with GCC):
+//
+//   http://www.codesourcery.com/public/cxx-abi/abi.html
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_CODEGEN_MANGLE_H
+#define LLVM_CLANG_CODEGEN_MANGLE_H
+
+namespace llvm {
+  class raw_ostream;
+}
+
+namespace clang {
+  class ASTContext;
+  class NamedDecl;
+
+  bool mangleName(const NamedDecl *D, ASTContext &Context, 
+                  llvm::raw_ostream &os);
+}
+
+#endif 
diff --git a/test/CodeGen/overloadable.c b/test/CodeGen/overloadable.c
new file mode 100644 (file)
index 0000000..6b1cb35
--- /dev/null
@@ -0,0 +1,24 @@
+// RUN: clang -emit-llvm %s -o - | grep _Z1fPA10_1X
+int __attribute__((overloadable)) f(int x) { return x; }
+float __attribute__((overloadable)) f(float x) { return x; }
+double __attribute__((overloadable)) f(double x) { return x; }
+double _Complex __attribute__((overloadable)) f(double _Complex x) { return x; }
+typedef short v4hi __attribute__ ((__vector_size__ (8)));
+v4hi __attribute__((overloadable)) f(v4hi x) { return x; }
+
+struct X { };
+void  __attribute__((overloadable)) f(struct X (*ptr)[10]) { }
+
+int main() {
+  int iv = 17;
+  float fv = 3.0f;
+  double dv = 4.0;
+  double _Complex cdv;
+  v4hi vv;
+
+  iv = f(iv);
+  fv = f(fv);
+  dv = f(dv);
+  cdv = f(cdv);
+  vv = f(vv);
+}
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
new file mode 100644 (file)
index 0000000..7b92c85
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: clang -emit-llvm %s -o - | grep _ZplRK1YRA100_P1X
+
+// FIXME: This test is intentionally trivial, because we can't yet
+// CodeGen anything real in C++.
+struct X { };
+struct Y { };
+  
+bool operator+(const Y&, X* (&xs)[100]) { return false; }
+