diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 54 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/Mangle.cpp | 516 | ||||
-rw-r--r-- | clang/lib/CodeGen/Mangle.h | 32 |
8 files changed, 597 insertions, 18 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index a32b78dedb9..3b912ce3d65 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -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()); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 7ef6fdf2af9..83fbd72f909 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -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(); diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index c59853a1b7c..1820c0b9f03 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -18,5 +18,6 @@ add_clang_library(clangCodeGen CodeGenFunction.cpp CodeGenModule.cpp CodeGenTypes.cpp + Mangle.cpp ModuleBuilder.cpp ) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index b46d24a2fcb..322f8bf565a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -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. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index a3b79562d14..df4a3d07636 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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 { diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 0c3964fd5f9..d8719efabfd 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -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/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp new file mode 100644 index 00000000000..a97ac58dd78 --- /dev/null +++ b/clang/lib/CodeGen/Mangle.cpp @@ -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/clang/lib/CodeGen/Mangle.h b/clang/lib/CodeGen/Mangle.h new file mode 100644 index 00000000000..404f8bddb75 --- /dev/null +++ b/clang/lib/CodeGen/Mangle.h @@ -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 |