summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/Mangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/Mangle.cpp')
-rw-r--r--lib/CodeGen/Mangle.cpp816
1 files changed, 383 insertions, 433 deletions
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 0a7124d..d6f7808 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -23,100 +23,111 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
+#include "CGVtable.h"
using namespace clang;
+using namespace CodeGen;
namespace {
- class VISIBILITY_HIDDEN CXXNameMangler {
- MangleContext &Context;
- llvm::raw_ostream &Out;
-
- const CXXMethodDecl *Structor;
- unsigned StructorType;
- CXXCtorType CtorType;
-
- llvm::DenseMap<uintptr_t, unsigned> Substitutions;
-
- public:
- CXXNameMangler(MangleContext &C, llvm::raw_ostream &os)
- : Context(C), Out(os), Structor(0), StructorType(0) { }
-
- bool mangle(const NamedDecl *D);
- void mangleCalloffset(int64_t nv, int64_t v);
- void mangleThunk(const FunctionDecl *FD, int64_t nv, int64_t v);
- void mangleCovariantThunk(const FunctionDecl *FD,
- int64_t nv_t, int64_t v_t,
- int64_t nv_r, int64_t v_r);
- void mangleGuardVariable(const VarDecl *D);
-
- void mangleCXXVtable(const CXXRecordDecl *RD);
- void mangleCXXVTT(const CXXRecordDecl *RD);
- void mangleCXXCtorVtable(const CXXRecordDecl *RD, int64_t Offset,
- const CXXRecordDecl *Type);
- void mangleCXXRtti(QualType Ty);
- void mangleCXXRttiName(QualType Ty);
- void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
- void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type);
-
- private:
- bool mangleSubstitution(const NamedDecl *ND);
- bool mangleSubstitution(QualType T);
- bool mangleSubstitution(uintptr_t Ptr);
-
- bool mangleStandardSubstitution(const NamedDecl *ND);
-
- void addSubstitution(const NamedDecl *ND) {
- ND = cast<NamedDecl>(ND->getCanonicalDecl());
+
+static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
+ assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
+ "Passed in decl is not a ctor or dtor!");
+
+ if (const TemplateDecl *TD = MD->getPrimaryTemplate()) {
+ MD = cast<CXXMethodDecl>(TD->getTemplatedDecl());
- addSubstitution(reinterpret_cast<uintptr_t>(ND));
- }
- void addSubstitution(QualType T);
- void addSubstitution(uintptr_t Ptr);
+ assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
+ "Templated decl is not a ctor or dtor!");
+ }
- bool mangleFunctionDecl(const FunctionDecl *FD);
-
- void mangleFunctionEncoding(const FunctionDecl *FD);
- void mangleName(const NamedDecl *ND);
- void mangleName(const TemplateDecl *TD,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs);
- void mangleUnqualifiedName(const NamedDecl *ND);
- void mangleUnscopedName(const NamedDecl *ND);
- void mangleUnscopedTemplateName(const TemplateDecl *ND);
- void mangleSourceName(const IdentifierInfo *II);
- void mangleLocalName(const NamedDecl *ND);
- void mangleNestedName(const NamedDecl *ND);
- void mangleNestedName(const TemplateDecl *TD,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs);
- void manglePrefix(const DeclContext *DC);
- void mangleTemplatePrefix(const TemplateDecl *ND);
- void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
- void mangleQualifiers(Qualifiers Quals);
- void mangleType(QualType T);
-
- // Declare manglers for every type class.
+ return MD;
+}
+
+/// CXXNameMangler - Manage the mangling of a single name.
+class CXXNameMangler {
+ MangleContext &Context;
+ llvm::raw_svector_ostream Out;
+
+ const CXXMethodDecl *Structor;
+ unsigned StructorType;
+
+ llvm::DenseMap<uintptr_t, unsigned> Substitutions;
+
+public:
+ CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res)
+ : Context(C), Out(Res), Structor(0), StructorType(0) { }
+ CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res,
+ const CXXConstructorDecl *D, CXXCtorType Type)
+ : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type) { }
+ CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res,
+ const CXXDestructorDecl *D, CXXDtorType Type)
+ : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type) { }
+
+ llvm::raw_svector_ostream &getStream() { return Out; }
+
+ void mangle(const NamedDecl *D, llvm::StringRef Prefix = "_Z");
+ void mangleCallOffset(const ThunkAdjustment &Adjustment);
+ void mangleNumber(int64_t Number);
+ void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleName(const NamedDecl *ND);
+ void mangleType(QualType T);
+
+private:
+ bool mangleSubstitution(const NamedDecl *ND);
+ bool mangleSubstitution(QualType T);
+ bool mangleSubstitution(uintptr_t Ptr);
+
+ bool mangleStandardSubstitution(const NamedDecl *ND);
+
+ void addSubstitution(const NamedDecl *ND) {
+ ND = cast<NamedDecl>(ND->getCanonicalDecl());
+
+ addSubstitution(reinterpret_cast<uintptr_t>(ND));
+ }
+ void addSubstitution(QualType T);
+ void addSubstitution(uintptr_t Ptr);
+
+ bool mangleFunctionDecl(const FunctionDecl *FD);
+
+ void mangleName(const TemplateDecl *TD,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+ void mangleUnqualifiedName(const NamedDecl *ND);
+ void mangleUnscopedName(const NamedDecl *ND);
+ void mangleUnscopedTemplateName(const TemplateDecl *ND);
+ void mangleSourceName(const IdentifierInfo *II);
+ void mangleLocalName(const NamedDecl *ND);
+ void mangleNestedName(const NamedDecl *ND);
+ void mangleNestedName(const TemplateDecl *TD,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+ void manglePrefix(const DeclContext *DC);
+ void mangleTemplatePrefix(const TemplateDecl *ND);
+ void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
+ void mangleQualifiers(Qualifiers Quals);
+
+ // Declare manglers for every type class.
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);
#include "clang/AST/TypeNodes.def"
- void mangleType(const TagType*);
- void mangleBareFunctionType(const FunctionType *T,
- bool MangleReturnType);
- void mangleExpression(const Expr *E);
- void mangleCXXCtorType(CXXCtorType T);
- void mangleCXXDtorType(CXXDtorType T);
-
- void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs);
- void mangleTemplateArgumentList(const TemplateArgumentList &L);
- void mangleTemplateArgument(const TemplateArgument &A);
-
- void mangleTemplateParameter(unsigned Index);
- };
+ void mangleType(const TagType*);
+ void mangleBareFunctionType(const FunctionType *T,
+ bool MangleReturnType);
+ void mangleExpression(const Expr *E);
+ void mangleCXXCtorType(CXXCtorType T);
+ void mangleCXXDtorType(CXXDtorType T);
+
+ void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+ void mangleTemplateArgumentList(const TemplateArgumentList &L);
+ void mangleTemplateArgument(const TemplateArgument &A);
+
+ void mangleTemplateParameter(unsigned Index);
+};
}
static bool isInCLinkageSpecification(const Decl *D) {
@@ -130,132 +141,72 @@ static bool isInCLinkageSpecification(const Decl *D) {
return false;
}
-bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
+bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
+ // In C, functions with no attributes never need to be mangled. Fastpath them.
+ if (!getASTContext().getLangOptions().CPlusPlus && !D->hasAttrs())
+ return false;
+
+ // Any decl can be declared with __asm("foo") on it, and this takes precedence
+ // over all other naming in the .o file.
+ if (D->hasAttr<AsmLabelAttr>())
+ return true;
+
// Clang's "overloadable" attribute extension to C/C++ implies name mangling
// (always) as does passing a C++ member function and a function
// whose name is not a simple identifier.
- if (!FD->hasAttr<OverloadableAttr>() && !isa<CXXMethodDecl>(FD) &&
- FD->getDeclName().isIdentifier()) {
- // C functions are not mangled, and "main" is never mangled.
- if (!Context.getASTContext().getLangOptions().CPlusPlus || FD->isMain())
- return false;
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
+ !FD->getDeclName().isIdentifier()))
+ return true;
- // No mangling in an "implicit extern C" header.
- if (FD->getLocation().isValid() &&
- Context.getASTContext().getSourceManager().
- isInExternCSystemHeader(FD->getLocation()))
- return false;
+ // Otherwise, no mangling is done outside C++ mode.
+ if (!getASTContext().getLangOptions().CPlusPlus)
+ return false;
- // No name mangling in a C linkage specification.
- if (isInCLinkageSpecification(FD))
- return false;
- }
+ // No mangling in an "implicit extern C" header.
+ if (D->getLocation().isValid() &&
+ getASTContext().getSourceManager().
+ isInExternCSystemHeader(D->getLocation()))
+ return false;
+
+ // C functions, "main", and variables at global scope are not
+ // mangled.
+ if ((FD && FD->isMain()) ||
+ (!FD && D->getDeclContext()->isTranslationUnit()) ||
+ isInCLinkageSpecification(D))
+ return false;
- // If we get here, mangle the decl name!
- Out << "_Z";
- mangleFunctionEncoding(FD);
return true;
}
-bool CXXNameMangler::mangle(const NamedDecl *D) {
+void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) {
// 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 << '\01'; // LLVM IR Marker for __asm("foo")
Out << ALA->getLabel();
- return true;
+ return;
}
// <mangled-name> ::= _Z <encoding>
// ::= <data name>
// ::= <special-name>
-
- // FIXME: Actually use a visitor to decode these?
+ Out << Prefix;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return mangleFunctionDecl(FD);
-
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (!Context.getASTContext().getLangOptions().CPlusPlus ||
- isInCLinkageSpecification(D) ||
- D->getDeclContext()->isTranslationUnit())
- return false;
-
- Out << "_Z";
- mangleName(VD);
- return true;
- }
-
- return false;
-}
-
-void CXXNameMangler::mangleCXXCtor(const CXXConstructorDecl *D,
- CXXCtorType Type) {
- assert(!Structor && "Structor already set!");
- Structor = D;
- StructorType = Type;
-
- mangle(D);
-}
-
-void CXXNameMangler::mangleCXXDtor(const CXXDestructorDecl *D,
- CXXDtorType Type) {
- assert(!Structor && "Structor already set!");
- Structor = D;
- StructorType = Type;
-
- mangle(D);
-}
-
-void CXXNameMangler::mangleCXXVtable(const CXXRecordDecl *RD) {
- // <special-name> ::= TV <type> # virtual table
- Out << "_ZTV";
- mangleName(RD);
-}
-
-void CXXNameMangler::mangleCXXVTT(const CXXRecordDecl *RD) {
- // <special-name> ::= TT <type> # VTT structure
- Out << "_ZTT";
- mangleName(RD);
-}
-
-void CXXNameMangler::mangleCXXCtorVtable(const CXXRecordDecl *RD,
- int64_t Offset,
- const CXXRecordDecl *Type) {
- // <special-name> ::= TC <type> <offset number> _ <base type>
- Out << "_ZTC";
- mangleName(RD);
- Out << Offset;
- Out << "_";
- mangleName(Type);
-}
-
-void CXXNameMangler::mangleCXXRtti(QualType Ty) {
- // <special-name> ::= TI <type> # typeinfo structure
- Out << "_ZTI";
-
- mangleType(Ty);
-}
-
-void CXXNameMangler::mangleCXXRttiName(QualType Ty) {
- // <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
- Out << "_ZTS";
-
- mangleType(Ty);
-}
-
-void CXXNameMangler::mangleGuardVariable(const VarDecl *D) {
- // <special-name> ::= GV <object name> # Guard variable for one-time
- // # initialization
-
- Out << "_ZGV";
- mangleName(D);
+ mangleFunctionEncoding(FD);
+ else
+ mangleName(cast<VarDecl>(D));
}
void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
// <encoding> ::= <function name> <bare-function-type>
mangleName(FD);
+ // Don't mangle in the type if this isn't a decl we should typically mangle.
+ if (!Context.shouldMangleDeclName(FD))
+ return;
+
// Whether the mangling of a function type includes the return type depends on
// the context and the nature of the function. The rules for deciding whether
// the return type is included are:
@@ -277,7 +228,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||
isa<CXXConversionDecl>(FD)))
MangleReturnType = true;
-
+
// Mangle the type of the primary template.
FD = PrimaryTemplate->getTemplatedDecl();
}
@@ -290,15 +241,16 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
mangleBareFunctionType(FT, MangleReturnType);
}
-static bool isStdNamespace(const DeclContext *DC) {
- if (!DC->isNamespace() || !DC->getParent()->isTranslationUnit())
- return false;
-
- const NamespaceDecl *NS = cast<NamespaceDecl>(DC);
+static bool isStdNamespace(const NamespaceDecl *NS) {
const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
return II && II->isStr("std");
}
+static bool isStdNamespace(const DeclContext *DC) {
+ return DC->isNamespace() && DC->getParent()->isTranslationUnit() &&
+ isStdNamespace(cast<NamespaceDecl>(DC));
+}
+
static const TemplateDecl *
isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
// Check if we have a function template.
@@ -315,7 +267,7 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
TemplateArgs = &Spec->getTemplateArgs();
return Spec->getSpecializedTemplate();
}
-
+
return 0;
}
@@ -328,7 +280,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
const DeclContext *DC = ND->getDeclContext();
while (isa<LinkageSpecDecl>(DC))
DC = DC->getParent();
-
+
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = 0;
@@ -341,24 +293,24 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
mangleUnscopedName(ND);
return;
}
-
+
if (isa<FunctionDecl>(DC)) {
mangleLocalName(ND);
return;
}
-
+
mangleNestedName(ND);
}
-void CXXNameMangler::mangleName(const TemplateDecl *TD,
+void CXXNameMangler::mangleName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
const DeclContext *DC = TD->getDeclContext();
while (isa<LinkageSpecDecl>(DC)) {
- assert(cast<LinkageSpecDecl>(DC)->getLanguage() ==
+ assert(cast<LinkageSpecDecl>(DC)->getLanguage() ==
LinkageSpecDecl::lang_cxx && "Unexpected linkage decl!");
DC = DC->getParent();
}
-
+
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
mangleUnscopedTemplateName(TD);
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
@@ -372,7 +324,7 @@ void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) {
// ::= St <unqualified-name> # ::std::
if (isStdNamespace(ND->getDeclContext()))
Out << "St";
-
+
mangleUnqualifiedName(ND);
}
@@ -381,61 +333,39 @@ void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
// ::= <substitution>
if (mangleSubstitution(ND))
return;
-
+
mangleUnscopedName(ND->getTemplatedDecl());
addSubstitution(ND);
}
-void CXXNameMangler::mangleCalloffset(int64_t nv, int64_t v) {
+void CXXNameMangler::mangleNumber(int64_t Number) {
+ // <number> ::= [n] <non-negative decimal integer>
+ if (Number < 0) {
+ Out << 'n';
+ Number = -Number;
+ }
+
+ Out << Number;
+}
+
+void CXXNameMangler::mangleCallOffset(const ThunkAdjustment &Adjustment) {
// <call-offset> ::= h <nv-offset> _
// ::= v <v-offset> _
// <nv-offset> ::= <offset number> # non-virtual base override
- // <v-offset> ::= <offset nubmer> _ <virtual offset number>
+ // <v-offset> ::= <offset number> _ <virtual offset number>
// # virtual base override, with vcall offset
- if (v == 0) {
- Out << "h";
- if (nv < 0) {
- Out << "n";
- nv = -nv;
- }
- Out << nv;
- } else {
- Out << "v";
- if (nv < 0) {
- Out << "n";
- nv = -nv;
- }
- Out << nv;
- Out << "_";
- if (v < 0) {
- Out << "n";
- v = -v;
- }
- Out << v;
+ if (!Adjustment.Virtual) {
+ Out << 'h';
+ mangleNumber(Adjustment.NonVirtual);
+ Out << '_';
+ return;
}
- Out << "_";
-}
-
-void CXXNameMangler::mangleThunk(const FunctionDecl *FD, int64_t nv,
- int64_t v) {
- // <special-name> ::= T <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- Out << "_ZT";
- mangleCalloffset(nv, v);
- mangleFunctionEncoding(FD);
-}
-
- void CXXNameMangler::mangleCovariantThunk(const FunctionDecl *FD,
- int64_t nv_t, int64_t v_t,
- int64_t nv_r, int64_t v_r) {
- // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // # first call-offset is 'this' adjustment
- // # second call-offset is result adjustment
- Out << "_ZTc";
- mangleCalloffset(nv_t, v_t);
- mangleCalloffset(nv_r, v_r);
- mangleFunctionEncoding(FD);
+
+ Out << 'v';
+ mangleNumber(Adjustment.NonVirtual);
+ Out << '_';
+ mangleNumber(Adjustment.Virtual);
+ Out << '_';
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
@@ -453,13 +383,13 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
Out << "12_GLOBAL__N_1";
break;
}
- }
+ }
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
mangleSourceName(II);
break;
}
-
+
// We must have an anonymous struct.
const TagDecl *TD = cast<TagDecl>(ND);
if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
@@ -470,12 +400,12 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
mangleSourceName(D->getDeclName().getAsIdentifierInfo());
break;
}
-
+
// Get a unique id for the anonymous struct.
uint64_t AnonStructId = Context.getAnonymousStructId(TD);
// Mangle it as a source name in the form
- // [n] $_<id>
+ // [n] $_<id>
// where n is the length of the string.
llvm::SmallString<8> Str;
Str += "$_";
@@ -525,6 +455,12 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
cast<FunctionDecl>(ND)->getNumParams());
break;
+ case DeclarationName::CXXLiteralOperatorName:
+ // Guessing based on existing ABI.
+ Out << "ul";
+ mangleSourceName(Name.getCXXLiteralIdentifier());
+ break;
+
case DeclarationName::CXXUsingDirective:
assert(false && "Can't mangle a using directive name!");
break;
@@ -545,29 +481,29 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND) {
Out << 'N';
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND))
mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
-
+
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = 0;
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgumentList(*TemplateArgs);
} else {
manglePrefix(ND->getDeclContext());
mangleUnqualifiedName(ND);
}
-
+
Out << 'E';
}
-void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
+void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
// <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
Out << 'N';
-
+
mangleTemplatePrefix(TD);
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
-
+
Out << 'E';
}
@@ -591,23 +527,23 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) {
while (isa<LinkageSpecDecl>(DC))
DC = DC->getParent();
-
+
if (DC->isTranslationUnit())
return;
-
+
if (mangleSubstitution(cast<NamedDecl>(DC)))
return;
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = 0;
- if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) {
+ if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgumentList(*TemplateArgs);
} else {
manglePrefix(DC->getParent());
mangleUnqualifiedName(cast<NamedDecl>(DC));
}
-
+
addSubstitution(cast<NamedDecl>(DC));
}
@@ -618,12 +554,12 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
if (mangleSubstitution(ND))
return;
-
+
// FIXME: <template-param>
-
+
manglePrefix(ND->getDeclContext());
mangleUnqualifiedName(ND->getTemplatedDecl());
-
+
addSubstitution(ND);
}
@@ -838,6 +774,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
break;
case BuiltinType::ObjCId: Out << "11objc_object"; break;
case BuiltinType::ObjCClass: Out << "10objc_class"; break;
+ case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
}
}
@@ -992,7 +929,7 @@ void CXXNameMangler::mangleType(const FixedWidthIntType *T) {
void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl();
assert(TD && "FIXME: Support dependent template names!");
-
+
mangleName(TD, T->getArgs(), T->getNumArgs());
}
@@ -1001,7 +938,7 @@ void CXXNameMangler::mangleType(const TypenameType *T) {
Out << 'N';
const Type *QTy = T->getQualifier()->getAsType();
- if (const TemplateSpecializationType *TST =
+ if (const TemplateSpecializationType *TST =
dyn_cast<TemplateSpecializationType>(QTy)) {
if (!mangleSubstitution(QualType(TST, 0))) {
TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();
@@ -1010,7 +947,7 @@ void CXXNameMangler::mangleType(const TypenameType *T) {
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
- } else if (const TemplateTypeParmType *TTPT =
+ } else if (const TemplateTypeParmType *TTPT =
dyn_cast<TemplateTypeParmType>(QTy)) {
// We use the QualType mangle type variant here because it handles
// substitutions.
@@ -1019,7 +956,7 @@ void CXXNameMangler::mangleType(const TypenameType *T) {
assert(false && "Unhandled type!");
mangleSourceName(T->getIdentifier());
-
+
Out << 'E';
}
@@ -1047,7 +984,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
case Expr::DeclRefExprClass: {
const Decl *D = cast<DeclRefExpr>(E)->getDecl();
-
+
switch (D->getKind()) {
default: assert(false && "Unhandled decl kind!");
case Decl::NonTypeTemplateParm: {
@@ -1057,23 +994,23 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
}
}
-
+
break;
}
-
- case Expr::UnresolvedDeclRefExprClass: {
- const UnresolvedDeclRefExpr *DRE = cast<UnresolvedDeclRefExpr>(E);
+
+ case Expr::DependentScopeDeclRefExprClass: {
+ const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
const Type *QTy = DRE->getQualifier()->getAsType();
assert(QTy && "Qualifier was not type!");
// ::= sr <type> <unqualified-name> # dependent name
Out << "sr";
mangleType(QualType(QTy, 0));
-
+
assert(DRE->getDeclName().getNameKind() == DeclarationName::Identifier &&
"Unhandled decl name kind!");
mangleSourceName(DRE->getDeclName().getAsIdentifierInfo());
-
+
break;
}
@@ -1122,13 +1059,8 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
void CXXNameMangler::mangleTemplateArgumentList(const TemplateArgumentList &L) {
// <template-args> ::= I <template-arg>+ E
Out << "I";
-
- for (unsigned i = 0, e = L.size(); i != e; ++i) {
- const TemplateArgument &A = L[i];
-
- mangleTemplateArgument(A);
- }
-
+ for (unsigned i = 0, e = L.size(); i != e; ++i)
+ mangleTemplateArgument(L[i]);
Out << "E";
}
@@ -1136,11 +1068,8 @@ void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << "I";
-
- for (unsigned i = 0; i != NumTemplateArgs; ++i) {
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
mangleTemplateArgument(TemplateArgs[i]);
- }
-
Out << "E";
}
@@ -1161,14 +1090,12 @@ void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) {
mangleExpression(A.getAsExpr());
Out << 'E';
break;
- case TemplateArgument::Integral:
+ case TemplateArgument::Integral: {
// <expr-primary> ::= L <type> <value number> E # integer literal
+ const llvm::APSInt *Integral = A.getAsIntegral();
Out << 'L';
-
mangleType(A.getIntegralType());
-
- const llvm::APSInt *Integral = A.getAsIntegral();
if (A.getIntegralType()->isBooleanType()) {
// Boolean values are encoded as 0/1.
Out << (Integral->getBoolValue() ? '1' : '0');
@@ -1177,10 +1104,27 @@ void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) {
Out << 'n';
Integral->abs().print(Out, false);
}
+ Out << 'E';
+ break;
+ }
+ case TemplateArgument::Declaration: {
+ // <expr-primary> ::= L <mangled-name> E # external name
+ // FIXME: Clang produces AST's where pointer-to-member-function expressions
+ // and pointer-to-function expressions are represented as a declaration not
+ // an expression; this is not how gcc represents them and this changes the
+ // mangling.
+ Out << 'L';
+ // References to external entities use the mangled name; if the name would
+ // not normally be manged then mangle it as unqualified.
+ //
+ // FIXME: The ABI specifies that external names here should have _Z, but
+ // gcc leaves this off.
+ mangle(cast<NamedDecl>(A.getAsDecl()), "Z");
Out << 'E';
break;
}
+ }
}
void CXXNameMangler::mangleTemplateParameter(unsigned Index) {
@@ -1198,7 +1142,7 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
// Try one of the standard substitutions first.
if (mangleStandardSubstitution(ND))
return true;
-
+
ND = cast<NamedDecl>(ND->getCanonicalDecl());
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
}
@@ -1208,79 +1152,79 @@ bool CXXNameMangler::mangleSubstitution(QualType T) {
if (const RecordType *RT = T->getAs<RecordType>())
return mangleSubstitution(RT->getDecl());
}
-
+
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
return mangleSubstitution(TypePtr);
}
bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
- llvm::DenseMap<uintptr_t, unsigned>::iterator I =
+ llvm::DenseMap<uintptr_t, unsigned>::iterator I =
Substitutions.find(Ptr);
if (I == Substitutions.end())
return false;
-
+
unsigned SeqID = I->second;
if (SeqID == 0)
Out << "S_";
else {
SeqID--;
-
+
// <seq-id> is encoded in base-36, using digits and upper case letters.
char Buffer[10];
char *BufferPtr = Buffer + 9;
-
+
*BufferPtr = 0;
if (SeqID == 0) *--BufferPtr = '0';
-
+
while (SeqID) {
assert(BufferPtr > Buffer && "Buffer overflow!");
-
+
unsigned char c = static_cast<unsigned char>(SeqID) % 36;
-
+
*--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10);
SeqID /= 36;
}
-
+
Out << 'S' << BufferPtr << '_';
}
-
+
return true;
}
static bool isCharType(QualType T) {
if (T.isNull())
return false;
-
+
return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
T->isSpecificBuiltinType(BuiltinType::Char_U);
}
-/// isCharSpecialization - Returns whether a given type is a template
+/// isCharSpecialization - Returns whether a given type is a template
/// specialization of a given name with a single argument of type char.
static bool isCharSpecialization(QualType T, const char *Name) {
if (T.isNull())
return false;
-
+
const RecordType *RT = T->getAs<RecordType>();
if (!RT)
return false;
-
- const ClassTemplateSpecializationDecl *SD =
+
+ const ClassTemplateSpecializationDecl *SD =
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
if (!SD)
return false;
if (!isStdNamespace(SD->getDeclContext()))
return false;
-
+
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
if (TemplateArgs.size() != 1)
return false;
-
+
if (!isCharType(TemplateArgs[0].getAsType()))
return false;
-
+
return SD->getIdentifier()->getName() == Name;
}
@@ -1298,55 +1242,55 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
if (!isStdNamespace(TD->getDeclContext()))
return false;
-
+
// <substitution> ::= Sa # ::std::allocator
if (TD->getIdentifier()->isStr("allocator")) {
Out << "Sa";
return true;
}
-
+
// <<substitution> ::= Sb # ::std::basic_string
if (TD->getIdentifier()->isStr("basic_string")) {
Out << "Sb";
return true;
}
}
-
- if (const ClassTemplateSpecializationDecl *SD =
+
+ if (const ClassTemplateSpecializationDecl *SD =
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
// <substitution> ::= Ss # ::std::basic_string<char,
// ::std::char_traits<char>,
// ::std::allocator<char> >
if (SD->getIdentifier()->isStr("basic_string")) {
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
-
+
if (TemplateArgs.size() != 3)
return false;
-
+
if (!isCharType(TemplateArgs[0].getAsType()))
return false;
-
+
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
return false;
-
+
if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
return false;
Out << "Ss";
return true;
}
-
- // <substitution> ::= So # ::std::basic_ostream<char,
+
+ // <substitution> ::= So # ::std::basic_ostream<char,
// ::std::char_traits<char> >
if (SD->getIdentifier()->isStr("basic_ostream")) {
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
-
+
if (TemplateArgs.size() != 2)
return false;
-
+
if (!isCharType(TemplateArgs[0].getAsType()))
return false;
-
+
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
return false;
@@ -1364,138 +1308,144 @@ void CXXNameMangler::addSubstitution(QualType T) {
return;
}
}
-
+
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
addSubstitution(TypePtr);
}
void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
unsigned SeqID = Substitutions.size();
-
- assert(!Substitutions.count(Ptr) && "Substitution already exists!");
- Substitutions[Ptr] = SeqID;
-}
-
-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(MangleContext &Context, const NamedDecl *D,
- llvm::raw_ostream &os) {
- assert(!isa<CXXConstructorDecl>(D) &&
- "Use mangleCXXCtor for constructor decls!");
- assert(!isa<CXXDestructorDecl>(D) &&
- "Use mangleCXXDtor for destructor decls!");
-
- PrettyStackTraceDecl CrashInfo(const_cast<NamedDecl *>(D), SourceLocation(),
- Context.getASTContext().getSourceManager(),
- "Mangling declaration");
-
- CXXNameMangler Mangler(Context, os);
- if (!Mangler.mangle(D))
- return false;
-
- os.flush();
- return true;
- }
-
- /// \brief Mangles the a thunk with the offset n for the declaration D and
- /// emits that name to the given output stream.
- void mangleThunk(MangleContext &Context, const FunctionDecl *FD,
- int64_t nv, int64_t v, llvm::raw_ostream &os) {
- // FIXME: Hum, we might have to thunk these, fix.
- assert(!isa<CXXDestructorDecl>(FD) &&
- "Use mangleCXXDtor for destructor decls!");
-
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleThunk(FD, nv, v);
- os.flush();
- }
-
- /// \brief Mangles the a covariant thunk for the declaration D and emits that
- /// name to the given output stream.
- void mangleCovariantThunk(MangleContext &Context, const FunctionDecl *FD,
- int64_t nv_t, int64_t v_t,
- int64_t nv_r, int64_t v_r,
- llvm::raw_ostream &os) {
- // FIXME: Hum, we might have to thunk these, fix.
- assert(!isa<CXXDestructorDecl>(FD) &&
- "Use mangleCXXDtor for destructor decls!");
-
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCovariantThunk(FD, nv_t, v_t, nv_r, v_r);
- os.flush();
- }
-
- /// mangleGuardVariable - Returns the mangled name for a guard variable
- /// for the passed in VarDecl.
- void mangleGuardVariable(MangleContext &Context, const VarDecl *D,
- llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleGuardVariable(D);
-
- os.flush();
- }
-
- void mangleCXXCtor(MangleContext &Context, const CXXConstructorDecl *D,
- CXXCtorType Type, llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXCtor(D, Type);
- os.flush();
- }
-
- void mangleCXXDtor(MangleContext &Context, const CXXDestructorDecl *D,
- CXXDtorType Type, llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXDtor(D, Type);
+ assert(!Substitutions.count(Ptr) && "Substitution already exists!");
+ Substitutions[Ptr] = SeqID;
+}
- os.flush();
- }
+//
- void mangleCXXVtable(MangleContext &Context, const CXXRecordDecl *RD,
- llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXVtable(RD);
+/// \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.
+void MangleContext::mangleName(const NamedDecl *D,
+ llvm::SmallVectorImpl<char> &Res) {
+ 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");
+
+ CXXNameMangler Mangler(*this, Res);
+ return Mangler.mangle(D);
+}
+
+void MangleContext::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ llvm::SmallVectorImpl<char> &Res) {
+ CXXNameMangler Mangler(*this, Res, D, Type);
+ Mangler.mangle(D);
+}
+
+void MangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ llvm::SmallVectorImpl<char> &Res) {
+ CXXNameMangler Mangler(*this, Res, D, Type);
+ Mangler.mangle(D);
+}
+
+/// \brief Mangles the a thunk with the offset n for the declaration D and
+/// emits that name to the given output stream.
+void MangleContext::mangleThunk(const FunctionDecl *FD,
+ const ThunkAdjustment &ThisAdjustment,
+ llvm::SmallVectorImpl<char> &Res) {
+ // FIXME: Hum, we might have to thunk these, fix.
+ assert(!isa<CXXDestructorDecl>(FD) &&
+ "Use mangleCXXDtor for destructor decls!");
- os.flush();
- }
-
- void mangleCXXVTT(MangleContext &Context, const CXXRecordDecl *RD,
- llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXVTT(RD);
+ // <special-name> ::= T <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZT";
+ Mangler.mangleCallOffset(ThisAdjustment);
+ Mangler.mangleFunctionEncoding(FD);
+}
+
+/// \brief Mangles the a covariant thunk for the declaration D and emits that
+/// name to the given output stream.
+void
+MangleContext::mangleCovariantThunk(const FunctionDecl *FD,
+ const CovariantThunkAdjustment& Adjustment,
+ llvm::SmallVectorImpl<char> &Res) {
+ // FIXME: Hum, we might have to thunk these, fix.
+ assert(!isa<CXXDestructorDecl>(FD) &&
+ "Use mangleCXXDtor for destructor decls!");
- os.flush();
- }
+ // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // # first call-offset is 'this' adjustment
+ // # second call-offset is result adjustment
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZTc";
+ Mangler.mangleCallOffset(Adjustment.ThisAdjustment);
+ Mangler.mangleCallOffset(Adjustment.ReturnAdjustment);
+ Mangler.mangleFunctionEncoding(FD);
+}
- void mangleCXXCtorVtable(MangleContext &Context, const CXXRecordDecl *RD,
- int64_t Offset, const CXXRecordDecl *Type,
- llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXCtorVtable(RD, Offset, Type);
+/// mangleGuardVariable - Returns the mangled name for a guard variable
+/// for the passed in VarDecl.
+void MangleContext::mangleGuardVariable(const VarDecl *D,
+ llvm::SmallVectorImpl<char> &Res) {
+ // <special-name> ::= GV <object name> # Guard variable for one-time
+ // # initialization
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZGV";
+ Mangler.mangleName(D);
+}
- os.flush();
- }
+void MangleContext::mangleCXXVtable(const CXXRecordDecl *RD,
+ llvm::SmallVectorImpl<char> &Res) {
+ // <special-name> ::= TV <type> # virtual table
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZTV";
+ Mangler.mangleName(RD);
+}
- void mangleCXXRtti(MangleContext &Context, QualType Ty,
- llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXRtti(Ty);
+void MangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
+ llvm::SmallVectorImpl<char> &Res) {
+ // <special-name> ::= TT <type> # VTT structure
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZTT";
+ Mangler.mangleName(RD);
+}
- os.flush();
- }
+void MangleContext::mangleCXXCtorVtable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ llvm::SmallVectorImpl<char> &Res) {
+ // <special-name> ::= TC <type> <offset number> _ <base type>
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZTC";
+ Mangler.mangleName(RD);
+ Mangler.getStream() << Offset;
+ Mangler.getStream() << "_";
+ Mangler.mangleName(Type);
+}
- void mangleCXXRttiName(MangleContext &Context, QualType Ty,
- llvm::raw_ostream &os) {
- CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXRttiName(Ty);
+void MangleContext::mangleCXXRtti(QualType Ty,
+ llvm::SmallVectorImpl<char> &Res) {
+ // <special-name> ::= TI <type> # typeinfo structure
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZTI";
+ Mangler.mangleType(Ty);
+}
- os.flush();
- }
+void MangleContext::mangleCXXRttiName(QualType Ty,
+ llvm::SmallVectorImpl<char> &Res) {
+ // <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
+ CXXNameMangler Mangler(*this, Res);
+ Mangler.getStream() << "_ZTS";
+ Mangler.mangleType(Ty);
}
OpenPOWER on IntegriCloud