Mangle.cpp revision 4904bf4e84cfb48080270ebaa9005327f18ab0e5
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// The LLVM Compiler Infrastructure 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// License. See LICENSE.TXT for details. 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===// 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Implements generic name mangling support for blocks and Objective-C. 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===// 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/AST/Mangle.h" 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/AST/ASTContext.h" 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/AST/Decl.h" 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/AST/DeclCXX.h" 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/AST/DeclObjC.h" 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/AST/DeclTemplate.h" 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/AST/ExprCXX.h" 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/Basic/ABI.h" 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "clang/Basic/SourceManager.h" 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "llvm/ADT/StringExtras.h" 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "llvm/Support/raw_ostream.h" 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "llvm/Support/ErrorHandling.h" 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MANGLE_CHECKER 0 27bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if MANGLE_CHECKER 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <cxxabi.h> 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)using namespace clang; 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 34bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// much to be desired. Come up with a better mangling scheme. 36bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace { 3802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 39bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static void mangleFunctionBlock(MangleContext &Context, 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StringRef Outer, 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BlockDecl *BD, 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raw_ostream &Out) { 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned discriminator = Context.getBlockId(BD, true); 44bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) if (discriminator == 0) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Out << "__" << Outer << "_block_invoke"; 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch Out << "__" << Outer << "_block_invoke_" << discriminator+1; 48bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)} 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) { 5102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch#ifndef NDEBUG 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const DeclContext *ExpectedDC = BD->getDeclContext(); 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC)) 5402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch ExpectedDC = ExpectedDC->getParent(); 55a372c30a9dc26aa32e51fa7b85e0c47b55479f89Ben Murdoch // In-class initializers for non-static data members are lexically defined 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // within the class, but are mangled as if they were specified as constructor 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // member initializers. 58bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) if (isa<CXXRecordDecl>(ExpectedDC) && DC != ExpectedDC) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) DC = DC->getParent(); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) assert(DC == ExpectedDC && "Given decl context did not match expected!"); 6102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch#endif 62197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MangleContext::anchor() { } 67197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MangleContext::mangleGlobalBlock(const BlockDecl *BD, 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const NamedDecl *ID, 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raw_ostream &Out) { 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned discriminator = getBlockId(BD, false); 7202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch if (ID) { 73bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) if (shouldMangleDeclName(ID)) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mangleName(ID, Out); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Out << ID->getIdentifier()->getName(); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch } 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (discriminator == 0) 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Out << "_block_invoke"; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 82bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) Out << "_block_invoke_" << discriminator+1; 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 84bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CXXCtorType CT, const BlockDecl *BD, 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raw_ostream &ResStream) { 8802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch checkMangleDC(CD, BD); 89bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) SmallString<64> Buffer; 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) llvm::raw_svector_ostream Out(Buffer); 91bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) mangleCXXCtor(CD, CT, Out); 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Out.flush(); 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mangleFunctionBlock(*this, Buffer, BD, ResStream); 94bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)} 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CXXDtorType DT, const BlockDecl *BD, 9802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch raw_ostream &ResStream) { 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) checkMangleDC(DD, BD); 100bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) SmallString<64> Buffer; 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) llvm::raw_svector_ostream Out(Buffer); 102bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) mangleCXXDtor(DD, DT, Out); 10302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch Out.flush(); 10402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch mangleFunctionBlock(*this, Buffer, BD, ResStream); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 10602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) raw_ostream &Out) { 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); 110bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) checkMangleDC(DC, BD); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SmallString<64> Buffer; 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) llvm::raw_svector_ostream Stream(Buffer); 11402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { 115bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) mangleObjCMethodName(Method, Stream); 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const NamedDecl *ND = cast<NamedDecl>(DC); 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!shouldMangleDeclName(ND) && ND->getIdentifier()) 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Stream << ND->getIdentifier()->getName(); 12002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch else { 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We were doing a mangleUnqualifiedName() before, but that's 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // a private member of a class that will soon itself be private to the 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Itanium C++ ABI object. What should we do now? Right now, I'm just 124c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // calling the mangleName() method on the MangleContext; is there a 125 // better way? 126 mangleName(ND, Stream); 127 } 128 } 129 Stream.flush(); 130 mangleFunctionBlock(*this, Buffer, BD, Out); 131} 132 133void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, 134 raw_ostream &Out) { 135 SmallString<64> Name; 136 llvm::raw_svector_ostream OS(Name); 137 138 const ObjCContainerDecl *CD = 139 dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); 140 assert (CD && "Missing container decl in GetNameForMethod"); 141 OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); 142 if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) 143 OS << '(' << *CID << ')'; 144 OS << ' ' << MD->getSelector().getAsString() << ']'; 145 146 Out << OS.str().size() << OS.str(); 147} 148 149void MangleContext::mangleBlock(const BlockDecl *BD, 150 raw_ostream &Out, 151 const NamedDecl *ID) { 152 const DeclContext *DC = BD->getDeclContext(); 153 while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) 154 DC = DC->getParent(); 155 if (DC->isFunctionOrMethod()) 156 mangleBlock(DC, BD, Out); 157 else 158 mangleGlobalBlock(BD, ID, Out); 159} 160