diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 13 | ||||
-rw-r--r-- | lib/AST/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp (renamed from lib/CodeGen/Mangle.cpp) | 218 | ||||
-rw-r--r-- | lib/AST/Mangle.cpp | 132 | ||||
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 1184 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.h | 36 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGVTables.h | 89 | ||||
-rw-r--r-- | lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 20 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 9 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTBAA.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTBAA.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/GlobalDecl.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.h | 179 | ||||
-rw-r--r-- | lib/CodeGen/MicrosoftCXXABI.cpp | 1158 |
22 files changed, 1485 insertions, 1593 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 05e1973e61..3abfe22caa 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -22,6 +22,7 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/Mangle.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -5835,4 +5836,16 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { return ABI->isNearlyEmpty(RD); } +MangleContext *ASTContext::createMangleContext() { + switch (Target.getCXXABI()) { + case CXXABI_ARM: + case CXXABI_Itanium: + return createItaniumMangleContext(*this, getDiagnostics()); + case CXXABI_Microsoft: + return createMicrosoftMangleContext(*this, getDiagnostics()); + } + assert(0 && "Unsupported ABI"); + return 0; +} + CXXABI::~CXXABI() {} diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index e98a89646c..b49b89ed88 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -26,7 +26,10 @@ add_clang_library(clangAST ExprCXX.cpp InheritViz.cpp ItaniumCXXABI.cpp + ItaniumMangle.cpp + Mangle.cpp MicrosoftCXXABI.cpp + MicrosoftMangle.cpp NestedNameSpecifier.cpp ParentMap.cpp RecordLayout.cpp diff --git a/lib/CodeGen/Mangle.cpp b/lib/AST/ItaniumMangle.cpp index b8ae1e7e41..8daba88ea8 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1,4 +1,4 @@ -//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// +//===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,18 +14,18 @@ // http://www.codesourcery.com/public/cxx-abi/abi.html // //===----------------------------------------------------------------------===// -#include "Mangle.h" +#include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/ABI.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" -#include "CGVTables.h" #define MANGLE_CHECKER 0 @@ -34,68 +34,6 @@ #endif using namespace clang; -using namespace CodeGen; - -MiscNameMangler::MiscNameMangler(MangleContext &C, - llvm::SmallVectorImpl<char> &Res) - : Context(C), Out(Res) { } - -void MiscNameMangler::mangleBlock(GlobalDecl GD, const BlockDecl *BD) { - // Mangle the context of the block. - // FIXME: We currently mimic GCC's mangling scheme, which leaves much to be - // desired. Come up with a better mangling scheme. - const DeclContext *DC = BD->getDeclContext(); - while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) - DC = DC->getParent(); - if (DC->isFunctionOrMethod()) { - Out << "__"; - if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) - mangleObjCMethodName(Method); - else { - const NamedDecl *ND = cast<NamedDecl>(DC); - if (IdentifierInfo *II = ND->getIdentifier()) - Out << II->getName(); - else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND)) { - llvm::SmallString<64> Buffer; - Context.mangleCXXDtor(D, GD.getDtorType(), Buffer); - Out << Buffer; - } - else if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND)) { - llvm::SmallString<64> Buffer; - Context.mangleCXXCtor(D, GD.getCtorType(), Buffer); - Out << Buffer; - } - else { - // FIXME: We were doing a mangleUnqualifiedName() before, but that's - // a private member of a class that will soon itself be private to the - // Itanium C++ ABI object. What should we do now? Right now, I'm just - // calling the mangleName() method on the MangleContext; is there a - // better way? - llvm::SmallString<64> Buffer; - Context.mangleName(ND, Buffer); - Out << Buffer; - } - } - Out << "_block_invoke_" << Context.getBlockId(BD, true); - } else { - Out << "__block_global_" << Context.getBlockId(BD, false); - } -} - -void MiscNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { - llvm::SmallString<64> Name; - llvm::raw_svector_ostream OS(Name); - - const ObjCContainerDecl *CD = - dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); - assert (CD && "Missing container decl in GetNameForMethod"); - OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); - if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) - OS << '(' << CID << ')'; - OS << ' ' << MD->getSelector().getAsString() << ']'; - - Out << OS.str().size() << OS.str(); -} namespace { @@ -127,9 +65,77 @@ static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { static const unsigned UnknownArity = ~0U; +class ItaniumMangleContext : public MangleContext { + llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; + unsigned Discriminator; + llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; + +public: + explicit ItaniumMangleContext(ASTContext &Context, + Diagnostic &Diags) + : MangleContext(Context, Diags) { } + + uint64_t getAnonymousStructId(const TagDecl *TD) { + std::pair<llvm::DenseMap<const TagDecl *, + uint64_t>::iterator, bool> Result = + AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); + return Result.first->second; + } + + void startNewFunction() { + MangleContext::startNewFunction(); + mangleInitDiscriminator(); + } + + /// @name Mangler Entry Points + /// @{ + + bool shouldMangleDeclName(const NamedDecl *D); + void mangleName(const NamedDecl *D, llvm::SmallVectorImpl<char> &); + void mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, + llvm::SmallVectorImpl<char> &); + void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + llvm::SmallVectorImpl<char> &); + void mangleReferenceTemporary(const VarDecl *D, + llvm::SmallVectorImpl<char> &); + void mangleCXXVTable(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &); + void mangleCXXVTT(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &); + void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, + const CXXRecordDecl *Type, + llvm::SmallVectorImpl<char> &); + void mangleCXXRTTI(QualType T, llvm::SmallVectorImpl<char> &); + void mangleCXXRTTIName(QualType T, llvm::SmallVectorImpl<char> &); + void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + llvm::SmallVectorImpl<char> &); + void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + llvm::SmallVectorImpl<char> &); + + void mangleItaniumGuardVariable(const VarDecl *D, + llvm::SmallVectorImpl<char> &); + + void mangleInitDiscriminator() { + Discriminator = 0; + } + + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator; + if (discriminator == 1) + return false; + disc = discriminator-2; + return true; + } + /// @} +}; + /// CXXNameMangler - Manage the mangling of a single name. class CXXNameMangler { - MangleContext &Context; + ItaniumMangleContext &Context; llvm::raw_svector_ostream Out; const CXXMethodDecl *Structor; @@ -143,13 +149,13 @@ class CXXNameMangler { ASTContext &getASTContext() const { return Context.getASTContext(); } public: - CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res) + CXXNameMangler(ItaniumMangleContext &C, llvm::SmallVectorImpl<char> &Res) : Context(C), Out(Res), Structor(0), StructorType(0), SeqID(0) { } - CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res, + CXXNameMangler(ItaniumMangleContext &C, llvm::SmallVectorImpl<char> &Res, const CXXConstructorDecl *D, CXXCtorType Type) : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } - CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res, + CXXNameMangler(ItaniumMangleContext &C, llvm::SmallVectorImpl<char> &Res, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Res), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } @@ -259,6 +265,7 @@ private: void mangleTemplateParameter(unsigned Index); }; + } static bool isInCLinkageSpecification(const Decl *D) { @@ -272,7 +279,7 @@ static bool isInCLinkageSpecification(const Decl *D) { return false; } -bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { +bool ItaniumMangleContext::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; @@ -896,7 +903,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) { manglePrefix(DC->getParent(), NoFunction); llvm::SmallString<64> Name; - Context.mangleBlock(GlobalDecl(), Block, Name); + Context.mangleBlock(Block, Name); Out << Name.size() << Name; return; } @@ -1150,7 +1157,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { llvm::SmallString<64> Buffer; - MiscNameMangler(Context, Buffer).mangleObjCMethodName(MD); + Context.mangleObjCMethodName(MD, Buffer); Out << Buffer; } @@ -2470,8 +2477,8 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { /// 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) { +void ItaniumMangleContext::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) && @@ -2485,27 +2492,23 @@ void MangleContext::mangleName(const NamedDecl *D, return Mangler.mangle(D); } -void MangleContext::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::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) { +void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, + CXXDtorType Type, + llvm::SmallVectorImpl<char> &Res) { CXXNameMangler Mangler(*this, Res, D, Type); Mangler.mangle(D); } -void MangleContext::mangleBlock(GlobalDecl GD, const BlockDecl *BD, - llvm::SmallVectorImpl<char> &Res) { - MiscNameMangler Mangler(*this, Res); - Mangler.mangleBlock(GD, BD); -} - -void MangleContext::mangleThunk(const CXXMethodDecl *MD, - const ThunkInfo &Thunk, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, + llvm::SmallVectorImpl<char> &Res) { // <special-name> ::= T <call-offset> <base encoding> // # base is the nominal target function of thunk // <special-name> ::= Tc <call-offset> <call-offset> <base encoding> @@ -2533,9 +2536,10 @@ void MangleContext::mangleThunk(const CXXMethodDecl *MD, } void -MangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, - const ThisAdjustment &ThisAdjustment, - llvm::SmallVectorImpl<char> &Res) { +ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, + CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + llvm::SmallVectorImpl<char> &Res) { // <special-name> ::= T <call-offset> <base encoding> // # base is the nominal target function of thunk @@ -2551,8 +2555,8 @@ MangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, /// mangleGuardVariable - Returns the mangled name for a guard variable /// for the passed in VarDecl. -void MangleContext::mangleItaniumGuardVariable(const VarDecl *D, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D, + llvm::SmallVectorImpl<char> &Res) { // <special-name> ::= GV <object name> # Guard variable for one-time // # initialization CXXNameMangler Mangler(*this, Res); @@ -2560,7 +2564,7 @@ void MangleContext::mangleItaniumGuardVariable(const VarDecl *D, Mangler.mangleName(D); } -void MangleContext::mangleReferenceTemporary(const VarDecl *D, +void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D, llvm::SmallVectorImpl<char> &Res) { // We match the GCC mangling here. // <special-name> ::= GR <object name> @@ -2569,25 +2573,26 @@ void MangleContext::mangleReferenceTemporary(const VarDecl *D, Mangler.mangleName(D); } -void MangleContext::mangleCXXVTable(const CXXRecordDecl *RD, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &Res) { // <special-name> ::= TV <type> # virtual table CXXNameMangler Mangler(*this, Res); Mangler.getStream() << "_ZTV"; Mangler.mangleNameOrStandardSubstitution(RD); } -void MangleContext::mangleCXXVTT(const CXXRecordDecl *RD, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &Res) { // <special-name> ::= TT <type> # VTT structure CXXNameMangler Mangler(*this, Res); Mangler.getStream() << "_ZTT"; Mangler.mangleNameOrStandardSubstitution(RD); } -void MangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, - const CXXRecordDecl *Type, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::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"; @@ -2597,8 +2602,8 @@ void MangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, Mangler.mangleNameOrStandardSubstitution(Type); } -void MangleContext::mangleCXXRTTI(QualType Ty, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::mangleCXXRTTI(QualType Ty, + llvm::SmallVectorImpl<char> &Res) { // <special-name> ::= TI <type> # typeinfo structure assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers"); CXXNameMangler Mangler(*this, Res); @@ -2606,10 +2611,15 @@ void MangleContext::mangleCXXRTTI(QualType Ty, Mangler.mangleType(Ty); } -void MangleContext::mangleCXXRTTIName(QualType Ty, - llvm::SmallVectorImpl<char> &Res) { +void ItaniumMangleContext::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); } + +MangleContext *clang::createItaniumMangleContext(ASTContext &Context, + Diagnostic &Diags) { + return new ItaniumMangleContext(Context, Diags); +} diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp new file mode 100644 index 0000000000..83d9ed6678 --- /dev/null +++ b/lib/AST/Mangle.cpp @@ -0,0 +1,132 @@ +//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements generic name mangling support for blocks and Objective-C. +// +//===----------------------------------------------------------------------===// +#include "clang/AST/Mangle.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Basic/ABI.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" + +#define MANGLE_CHECKER 0 + +#if MANGLE_CHECKER +#include <cxxabi.h> +#endif + +using namespace clang; + +// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves +// much to be desired. Come up with a better mangling scheme. + +namespace { + +static void mangleFunctionBlock(MangleContext &Context, + llvm::StringRef Outer, + const BlockDecl *BD, + llvm::SmallVectorImpl<char> &Res) { + llvm::raw_svector_ostream Out(Res); + Out << "__" << Outer << "_block_invoke_" << Context.getBlockId(BD, true); +} + +static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) { +#ifndef NDEBUG + const DeclContext *ExpectedDC = BD->getDeclContext(); + while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC)) + ExpectedDC = ExpectedDC->getParent(); + assert(DC == ExpectedDC && "Given decl context did not match expected!"); +#endif +} + +} + +void MangleContext::mangleGlobalBlock(const BlockDecl *BD, + llvm::SmallVectorImpl<char> &Res) { + llvm::raw_svector_ostream Out(Res); + Out << "__block_global_" << getBlockId(BD, false); +} + +void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, + CXXCtorType CT, const BlockDecl *BD, + llvm::SmallVectorImpl<char> &Res) { + checkMangleDC(CD, BD); + llvm::SmallString<64> Buffer; + mangleCXXCtor(CD, CT, Buffer); + mangleFunctionBlock(*this, Buffer, BD, Res); +} + +void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, + CXXDtorType DT, const BlockDecl *BD, + llvm::SmallVectorImpl<char> &Res) { + checkMangleDC(DD, BD); + llvm::SmallString<64> Buffer; + mangleCXXDtor(DD, DT, Buffer); + mangleFunctionBlock(*this, Buffer, BD, Res); +} + +void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, + llvm::SmallVectorImpl<char> &Res) { + assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); + checkMangleDC(DC, BD); + + llvm::SmallString<64> Buffer; + if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { + mangleObjCMethodName(Method, Buffer); + } else { + const NamedDecl *ND = cast<NamedDecl>(DC); + if (IdentifierInfo *II = ND->getIdentifier()) + Buffer = II->getName(); + else { + // FIXME: We were doing a mangleUnqualifiedName() before, but that's + // a private member of a class that will soon itself be private to the + // Itanium C++ ABI object. What should we do now? Right now, I'm just + // calling the mangleName() method on the MangleContext; is there a + // better way? + mangleName(ND, Buffer); + } + } + + mangleFunctionBlock(*this, Buffer, BD, Res); +} + +void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, + llvm::SmallVectorImpl<char> &Res) { + llvm::SmallString<64> Name; + llvm::raw_svector_ostream OS(Name), Out(Res); + + const ObjCContainerDecl *CD = + dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); + assert (CD && "Missing container decl in GetNameForMethod"); + OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); + if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) + OS << '(' << CID << ')'; + OS << ' ' << MD->getSelector().getAsString() << ']'; + + Out << OS.str().size() << OS.str(); +} + +void MangleContext::mangleBlock(const BlockDecl *BD, + llvm::SmallVectorImpl<char> &Res) { + const DeclContext *DC = BD->getDeclContext(); + while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) + DC = DC->getParent(); + if (DC->isFunctionOrMethod()) + mangleBlock(DC, BD, Res); + else + mangleGlobalBlock(BD, Res); +} diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp new file mode 100644 index 0000000000..ef50899e43 --- /dev/null +++ b/lib/AST/MicrosoftMangle.cpp @@ -0,0 +1,1184 @@ +//===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides C++ name mangling targetting the Microsoft Visual C++ ABI. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Mangle.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Basic/ABI.h" + +using namespace clang; + +namespace { + +/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the +/// Microsoft Visual C++ ABI. +class MicrosoftCXXNameMangler { + MangleContext &Context; + llvm::raw_svector_ostream Out; + + ASTContext &getASTContext() const { return Context.getASTContext(); } + +public: + MicrosoftCXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res) + : Context(C), Out(Res) { } + + void mangle(const NamedDecl *D, llvm::StringRef Prefix = "?"); + void mangleName(const NamedDecl *ND); + void mangleFunctionEncoding(const FunctionDecl *FD); + void mangleVariableEncoding(const VarDecl *VD); + void mangleNumber(int64_t Number); + void mangleType(QualType T); + +private: + void mangleUnqualifiedName(const NamedDecl *ND) { + mangleUnqualifiedName(ND, ND->getDeclName()); + } + void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name); + void mangleSourceName(const IdentifierInfo *II); + void manglePostfix(const DeclContext *DC, bool NoFunction=false); + void mangleOperatorName(OverloadedOperatorKind OO); + void mangleQualifiers(Qualifiers Quals, bool IsMember); + + void mangleObjCMethodName(const ObjCMethodDecl *MD); + + // 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 mangleType(const FunctionType *T, const FunctionDecl *D, + bool IsStructor, bool IsInstMethod); + void mangleType(const ArrayType *T, bool IsGlobal); + void mangleExtraDimensions(QualType T); + void mangleFunctionClass(const FunctionDecl *FD); + void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false); + void mangleThrowSpecification(const FunctionProtoType *T); + +}; + +/// MicrosoftMangleContext - Overrides the default MangleContext for the +/// Microsoft Visual C++ ABI. +class MicrosoftMangleContext : public MangleContext { +public: + MicrosoftMangleContext(ASTContext &Context, + Diagnostic &Diags) : MangleContext(Context, Diags) { } + virtual bool shouldMangleDeclName(const NamedDecl *D); + virtual void mangleName(const NamedDecl *D, llvm::SmallVectorImpl<char> &); + virtual void mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXVTable(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXVTT(const CXXRecordDecl *RD, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, + const CXXRecordDecl *Type, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXRTTI(QualType T, llvm::SmallVectorImpl<char> &); + virtual void mangleCXXRTTIName(QualType T, llvm::SmallVectorImpl<char> &); + virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + llvm::SmallVectorImpl<char> &); + virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + llvm::SmallVectorImpl<char> &); + virtual void mangleReferenceTemporary(const clang::VarDecl *, + llvm::SmallVectorImpl<char> &); +}; + +} + +static bool isInCLinkageSpecification(const Decl *D) { + D = D->getCanonicalDecl(); + for (const DeclContext *DC = D->getDeclContext(); + !DC->isTranslationUnit(); DC = DC->getParent()) { + if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) + return Linkage->getLanguage() == LinkageSpecDecl::lang_c; + } + + return false; +} + +bool MicrosoftMangleContext::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. + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) || + !FD->getDeclName().isIdentifier())) + return true; + + // Otherwise, no mangling is done outside C++ mode. + if (!getASTContext().getLangOptions().CPlusPlus) + return false; + + // Variables at global scope with internal linkage are not mangled. + if (!FD) { + const DeclContext *DC = D->getDeclContext(); + if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage) + return false; + } + + // C functions and "main" are not mangled. + if ((FD && FD->isMain()) || isInCLinkageSpecification(D)) + return false; + + return true; +} + +void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, + llvm::StringRef Prefix) { + // MSVC doesn't mangle C++ names the same way it mangles extern "C" names. + // Therefore it's really important that we don't decorate the + // name with leading underscores or leading/trailing at signs. So, emit a + // asm marker at the start so we get the name right. + Out << '\01'; // LLVM IR Marker for __asm("foo") + + // Any decl can be declared with __asm("foo") on it, and this takes precedence + // over all other naming in the .o file. + if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { + // If we have an asm name, then we use it as the mangling. + Out << ALA->getLabel(); + return; + } + + // <mangled-name> ::= ? <name> <type-encoding> + Out << Prefix; + mangleName(D); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + mangleFunctionEncoding(FD); + else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) + mangleVariableEncoding(VD); + // TODO: Fields? Can MSVC even mangle them? +} + +void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { + // <type-encoding> ::= <function-class> <function-type> + + // Don't mangle in the type if this isn't a decl we should typically mangle. + if (!Context.shouldMangleDeclName(FD)) + return; + + // We should never ever see a FunctionNoProtoType at this point. + // We don't even know how to mangle their types anyway :). + const FunctionProtoType *FT = cast<FunctionProtoType>(FD->getType()); + + bool InStructor = false, InInstMethod = false; + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + if (MD) { + if (MD->isInstance()) + InInstMethod = true; + if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) + InStructor = true; + } + + // First, the function class. + mangleFunctionClass(FD); + + mangleType(FT, FD, InStructor, InInstMethod); +} + +void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { + // <type-encoding> ::= <storage-class> <variable-type> + // <storage-class> ::= 0 # private static member + // ::= 1 # protected static member + // ::= 2 # public static member + // ::= 3 # global + // ::= 4 # static local + + // The first character in the encoding (after the name) is the storage class. + if (VD->isStaticDataMember()) { + // If it's a static member, it also encodes the access level. + switch (VD->getAccess()) { + defau |