[cfe-commits] r95273 - in /cfe/trunk: include/clang/AST/ExprCXX.h lib/CodeGen/Mangle.cpp test/CodeGenCXX/mangle.cpp

John McCall rjmccall at apple.com
Wed Feb 3 17:42:14 PST 2010


Author: rjmccall
Date: Wed Feb  3 19:42:13 2010
New Revision: 95273

URL: http://llvm.org/viewvc/llvm-project?rev=95273&view=rev
Log:
Add mangling support for calls, sizeof/alignof, constructor calls,
float literals, and unresolved lookups (which required hand-wavey extensions).


Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/lib/CodeGen/Mangle.cpp
    cfe/trunk/test/CodeGenCXX/mangle.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Feb  3 19:42:13 2010
@@ -1602,11 +1602,24 @@
   arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
   arg_iterator arg_end() { return arg_begin() + NumArgs; }
 
+  typedef const Expr* const * const_arg_iterator;
+  const_arg_iterator arg_begin() const {
+    return reinterpret_cast<const Expr* const *>(this + 1);
+  }
+  const_arg_iterator arg_end() const {
+    return arg_begin() + NumArgs;
+  }
+
   Expr *getArg(unsigned I) {
     assert(I < NumArgs && "Argument index out-of-range");
     return *(arg_begin() + I);
   }
 
+  const Expr *getArg(unsigned I) const {
+    assert(I < NumArgs && "Argument index out-of-range");
+    return *(arg_begin() + I);
+  }
+
   virtual SourceRange getSourceRange() const {
     return SourceRange(TyBeginLoc, RParenLoc);
   }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Wed Feb  3 19:42:13 2010
@@ -44,6 +44,8 @@
     
   return MD;
 }
+
+static const unsigned UnknownArity = ~0U;
   
 /// CXXNameMangler - Manage the mangling of a single name.
 class CXXNameMangler {
@@ -55,6 +57,8 @@
 
   llvm::DenseMap<uintptr_t, unsigned> Substitutions;
 
+  ASTContext &getASTContext() const { return Context.getASTContext(); }
+
 public:
   CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res)
     : Context(C), Out(Res), Structor(0), StructorType(0) { }
@@ -89,10 +93,19 @@
   void addSubstitution(QualType T);
   void addSubstitution(uintptr_t Ptr);
 
+  void mangleUnresolvedScope(NestedNameSpecifier *Qualifier);
+  void mangleUnresolvedName(NestedNameSpecifier *Qualifier,
+                            DeclarationName Name,
+                            unsigned KnownArity = UnknownArity);
+
   void mangleName(const TemplateDecl *TD,
                   const TemplateArgument *TemplateArgs,
                   unsigned NumTemplateArgs);
-  void mangleUnqualifiedName(const NamedDecl *ND);
+  void mangleUnqualifiedName(const NamedDecl *ND) {
+    mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity);
+  }
+  void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,
+                             unsigned KnownArity);
   void mangleUnscopedName(const NamedDecl *ND);
   void mangleUnscopedTemplateName(const TemplateDecl *ND);
   void mangleSourceName(const IdentifierInfo *II);
@@ -119,6 +132,7 @@
                               bool MangleReturnType);
 
   void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
+  void mangleCalledExpression(const Expr *E, unsigned KnownArity);
   void mangleExpression(const Expr *E);
   void mangleCXXCtorType(CXXCtorType T);
   void mangleCXXDtorType(CXXDtorType T);
@@ -398,28 +412,50 @@
   Out << '_';
 }
 
-void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
+void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
+  Qualifier = getASTContext().getCanonicalNestedNameSpecifier(Qualifier);
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+    // nothing
+    break;
+  case NestedNameSpecifier::Namespace:
+    mangleName(Qualifier->getAsNamespace());
+    break;
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+    mangleType(QualType(Qualifier->getAsType(), 0));
+    break;
+  case NestedNameSpecifier::Identifier:
+    mangleUnresolvedScope(Qualifier->getPrefix());
+    mangleSourceName(Qualifier->getAsIdentifier());
+    break;
+  }
+}
+
+/// Mangles a name which was not resolved to a specific entity.
+void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *Qualifier,
+                                          DeclarationName Name,
+                                          unsigned KnownArity) {
+  if (Qualifier)
+    mangleUnresolvedScope(Qualifier);
+  // FIXME: ambiguity of unqualified lookup with ::
+
+  mangleUnqualifiedName(0, Name, KnownArity);
+}
+
+void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+                                           DeclarationName Name,
+                                           unsigned KnownArity) {
   //  <unqualified-name> ::= <operator-name>
   //                     ::= <ctor-dtor-name>
   //                     ::= <source-name>
-  DeclarationName Name = ND->getDeclName();
   switch (Name.getNameKind()) {
   case DeclarationName::Identifier: {
-    if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
-      if (NS->isAnonymousNamespace()) {
-        // This is how gcc mangles these names.  It's apparently
-        // always '1', no matter how many different anonymous
-        // namespaces appear in a context.
-        Out << "12_GLOBAL__N_1";
-        break;
-      }
-    }
-
     if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
       // We must avoid conflicts between internally- and externally-
       // linked names in the same TU. This naming convention is the
       // same as that followed by GCC, though it shouldn't actually matter.
-      if (ND->getLinkage() == InternalLinkage &&
+      if (ND && ND->getLinkage() == InternalLinkage &&
           ND->getDeclContext()->isFileContext())
         Out << 'L';
 
@@ -427,6 +463,17 @@
       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()) {
+        // This is how gcc mangles these names.
+        Out << "12_GLOBAL__N_1";
+        break;
+      }
+    }
+
     // We must have an anonymous struct.
     const TagDecl *TD = cast<TagDecl>(ND);
     if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
@@ -488,13 +535,18 @@
     break;
 
   case DeclarationName::CXXOperatorName: {
-    unsigned Arity = cast<FunctionDecl>(ND)->getNumParams();
+    unsigned Arity;
+    if (ND) {
+      Arity = cast<FunctionDecl>(ND)->getNumParams();
     
-    // If we have a C++ member function, we need to include the 'this' pointer.
-    // FIXME: This does not make sense for operators that are static, but their
-    // names stay the same regardless of the arity (operator new for instance).
-    if (isa<CXXMethodDecl>(ND))
-      Arity++;
+      // If we have a C++ member function, we need to include the 'this' pointer.
+      // FIXME: This does not make sense for operators that are static, but their
+      // names stay the same regardless of the arity (operator new for instance).
+      if (isa<CXXMethodDecl>(ND))
+        Arity++;
+    } else
+      Arity = KnownArity;
+
     mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
     break;
   }
@@ -1053,6 +1105,19 @@
   
 }
 
+void CXXNameMangler::mangleCalledExpression(const Expr *E, unsigned Arity) {
+  if (E->getType() != getASTContext().OverloadTy)
+    mangleExpression(E);
+
+  llvm::PointerIntPair<OverloadExpr*,1> R
+    = OverloadExpr::find(const_cast<Expr*>(E));
+  if (R.getInt())
+    Out << "an"; // &
+  const OverloadExpr *Ovl = R.getPointer();
+
+  mangleUnresolvedName(Ovl->getQualifier(), Ovl->getName(), Arity);
+}
+
 void CXXNameMangler::mangleExpression(const Expr *E) {
   // <expression> ::= <unary operator-name> <expression>
   //              ::= <binary operator-name> <expression> <expression>
@@ -1068,25 +1133,68 @@
   //              ::= sr <type> <unqualified-name> <template-args>   # dependent template-id
   //              ::= sZ <template-param>                            # size of a parameter pack
   //              ::= <expr-primary>
+  // <expr-primary> ::= L <type> <value number> E    # integer literal
+  //                ::= L <type <value float> E      # floating literal
+  //                ::= L <mangled-name> E           # external name
   switch (E->getStmtClass()) {
   default:
     llvm_unreachable("unexpected statement kind");
     break;
 
-  case Expr::CallExprClass:
-    // FIXME: implement
-    llvm_unreachable("mangling not implemented for calls");
+  case Expr::CallExprClass: {
+    const CallExpr *CE = cast<CallExpr>(E);
+    Out << "cl";
+    mangleCalledExpression(CE->getCallee(), CE->getNumArgs());
+    for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
+      mangleExpression(CE->getArg(I));
+    Out << "E";
     break;
+  }
+
+  case Expr::UnresolvedLookupExprClass: {
+    const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
+    mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), UnknownArity);
+    break;
+  }
+
+  case Expr::CXXUnresolvedConstructExprClass: { 
+    const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
+    unsigned N = CE->arg_size();
 
-  case Expr::CXXConstructExprClass:
-    // FIXME: implement
-    llvm_unreachable("mangling not implemented for construct exprs");
+    Out << "cv";
+    mangleType(CE->getType());
+    if (N != 1) Out << "_";
+    for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
+    if (N != 1) Out << "E";
     break;    
+  }
+
+  case Expr::CXXTemporaryObjectExprClass:
+  case Expr::CXXConstructExprClass: {
+    const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
+    unsigned N = CE->getNumArgs();
+
+    Out << "cv";
+    mangleType(CE->getType());
+    if (N != 1) Out << "_";
+    for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
+    if (N != 1) Out << "E";
+    break;
+  }
 
-  case Expr::SizeOfAlignOfExprClass:
-    // FIXME: implement
-    llvm_unreachable("mangling not implemented for sizeof/alignof");
+  case Expr::SizeOfAlignOfExprClass: {
+    const SizeOfAlignOfExpr *SAE = cast<SizeOfAlignOfExpr>(E);
+    if (SAE->isSizeOf()) Out << "s";
+    else Out << "a";
+    if (SAE->isArgumentType()) {
+      Out << "t";
+      mangleType(SAE->getArgumentType());
+    } else {
+      Out << "z";
+      mangleExpression(SAE->getArgumentExpr());
+    }
     break;
+  }
 
   case Expr::UnaryOperatorClass: {
     const UnaryOperator *UO = cast<UnaryOperator>(E);
@@ -1178,6 +1286,20 @@
     break;
   }
 
+  case Expr::FloatingLiteralClass: {
+    const FloatingLiteral *FL = cast<FloatingLiteral>(E);
+    Out << "L";
+    mangleType(FL->getType());
+
+    // TODO: avoid this copy with careful stream management.
+    llvm::SmallVector<char,20> Buffer;
+    FL->getValue().bitcastToAPInt().toString(Buffer, 16, false);
+    Out.write(Buffer.data(), Buffer.size());
+
+    Out << "E";
+    break;
+  }
+
   case Expr::IntegerLiteralClass:
     mangleIntegerLiteral(E->getType(), 
                          llvm::APSInt(cast<IntegerLiteral>(E)->getValue()));

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=95273&r1=95272&r2=95273&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Wed Feb  3 19:42:13 2010
@@ -322,3 +322,38 @@
 void pr5966_bar() {
   pr5966_i = 0;
 }
+
+namespace test0 {
+  int ovl(int x);
+  char ovl(double x);
+
+  template <class T> void f(T, char (&buffer)[sizeof(ovl(T()))]) {}
+
+  void test0() {
+    char buffer[1];
+    f(0.0, buffer);
+  }
+  // CHECK: define void @_ZN5test05test0Ev()
+  // CHECK: define linkonce_odr void @_ZN5test01fIdEEvT_RAszcl3ovlcvS1__EE_c(
+
+  void test1() {
+    char buffer[sizeof(int)];
+    f(1, buffer);
+  }
+  // CHECK: define void @_ZN5test05test1Ev()
+  // CHECK: define linkonce_odr void @_ZN5test01fIiEEvT_RAszcl3ovlcvS1__EE_c(
+
+  template <class T> void g(char (&buffer)[sizeof(T() + 5.0f)]) {}
+  void test2() {
+    char buffer[sizeof(float)];
+    g<float>(buffer);
+  }
+  // CHECK: define linkonce_odr void @_ZN5test01gIfEEvRAszplcvT__ELf40A00000E_c(
+
+  template <class T> void h(char (&buffer)[sizeof(T() + 5.0)]) {}
+  void test3() {
+    char buffer[sizeof(double)];
+    h<float>(buffer);
+  }
+  // CHECK: define linkonce_odr void @_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c(
+}





More information about the cfe-commits mailing list