10b57cec5SDimitry Andric //===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implements generic name mangling support for blocks and Objective-C. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric #include "clang/AST/Attr.h" 130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 140b57cec5SDimitry Andric #include "clang/AST/Decl.h" 150b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 160b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 180b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 190b57cec5SDimitry Andric #include "clang/AST/Mangle.h" 200b57cec5SDimitry Andric #include "clang/AST/VTableBuilder.h" 210b57cec5SDimitry Andric #include "clang/Basic/ABI.h" 220b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 230b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 240b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 250b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 260b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using namespace clang; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves 330b57cec5SDimitry Andric // much to be desired. Come up with a better mangling scheme. 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric static void mangleFunctionBlock(MangleContext &Context, 360b57cec5SDimitry Andric StringRef Outer, 370b57cec5SDimitry Andric const BlockDecl *BD, 380b57cec5SDimitry Andric raw_ostream &Out) { 390b57cec5SDimitry Andric unsigned discriminator = Context.getBlockId(BD, true); 400b57cec5SDimitry Andric if (discriminator == 0) 410b57cec5SDimitry Andric Out << "__" << Outer << "_block_invoke"; 420b57cec5SDimitry Andric else 430b57cec5SDimitry Andric Out << "__" << Outer << "_block_invoke_" << discriminator+1; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric void MangleContext::anchor() { } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric enum CCMangling { 490b57cec5SDimitry Andric CCM_Other, 500b57cec5SDimitry Andric CCM_Fast, 510b57cec5SDimitry Andric CCM_RegCall, 520b57cec5SDimitry Andric CCM_Vector, 530b57cec5SDimitry Andric CCM_Std 540b57cec5SDimitry Andric }; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric static bool isExternC(const NamedDecl *ND) { 570b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) 580b57cec5SDimitry Andric return FD->isExternC(); 590b57cec5SDimitry Andric return cast<VarDecl>(ND)->isExternC(); 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric static CCMangling getCallingConvMangling(const ASTContext &Context, 630b57cec5SDimitry Andric const NamedDecl *ND) { 640b57cec5SDimitry Andric const TargetInfo &TI = Context.getTargetInfo(); 650b57cec5SDimitry Andric const llvm::Triple &Triple = TI.getTriple(); 66*480093f4SDimitry Andric if (!Triple.isOSWindows() || !Triple.isX86()) 670b57cec5SDimitry Andric return CCM_Other; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric if (Context.getLangOpts().CPlusPlus && !isExternC(ND) && 700b57cec5SDimitry Andric TI.getCXXABI() == TargetCXXABI::Microsoft) 710b57cec5SDimitry Andric return CCM_Other; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND); 740b57cec5SDimitry Andric if (!FD) 750b57cec5SDimitry Andric return CCM_Other; 760b57cec5SDimitry Andric QualType T = FD->getType(); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric const FunctionType *FT = T->castAs<FunctionType>(); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric CallingConv CC = FT->getCallConv(); 810b57cec5SDimitry Andric switch (CC) { 820b57cec5SDimitry Andric default: 830b57cec5SDimitry Andric return CCM_Other; 840b57cec5SDimitry Andric case CC_X86FastCall: 850b57cec5SDimitry Andric return CCM_Fast; 860b57cec5SDimitry Andric case CC_X86StdCall: 870b57cec5SDimitry Andric return CCM_Std; 880b57cec5SDimitry Andric case CC_X86VectorCall: 890b57cec5SDimitry Andric return CCM_Vector; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { 940b57cec5SDimitry Andric const ASTContext &ASTContext = getASTContext(); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric CCMangling CC = getCallingConvMangling(ASTContext, D); 970b57cec5SDimitry Andric if (CC != CCM_Other) 980b57cec5SDimitry Andric return true; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric // If the declaration has an owning module for linkage purposes that needs to 1010b57cec5SDimitry Andric // be mangled, we must mangle its name. 1020b57cec5SDimitry Andric if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage()) 1030b57cec5SDimitry Andric return true; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // In C, functions with no attributes never need to be mangled. Fastpath them. 1060b57cec5SDimitry Andric if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) 1070b57cec5SDimitry Andric return false; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // Any decl can be declared with __asm("foo") on it, and this takes precedence 1100b57cec5SDimitry Andric // over all other naming in the .o file. 1110b57cec5SDimitry Andric if (D->hasAttr<AsmLabelAttr>()) 1120b57cec5SDimitry Andric return true; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric return shouldMangleCXXName(D); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { 1180b57cec5SDimitry Andric // Any decl can be declared with __asm("foo") on it, and this takes precedence 1190b57cec5SDimitry Andric // over all other naming in the .o file. 1200b57cec5SDimitry Andric if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { 1210b57cec5SDimitry Andric // If we have an asm name, then we use it as the mangling. 1220b57cec5SDimitry Andric 123a7dea167SDimitry Andric // If the label isn't literal, or if this is an alias for an LLVM intrinsic, 124a7dea167SDimitry Andric // do not add a "\01" prefix. 125a7dea167SDimitry Andric if (!ALA->getIsLiteralLabel() || ALA->getLabel().startswith("llvm.")) { 126a7dea167SDimitry Andric Out << ALA->getLabel(); 127a7dea167SDimitry Andric return; 128a7dea167SDimitry Andric } 129a7dea167SDimitry Andric 1300b57cec5SDimitry Andric // Adding the prefix can cause problems when one file has a "foo" and 1310b57cec5SDimitry Andric // another has a "\01foo". That is known to happen on ELF with the 1320b57cec5SDimitry Andric // tricks normally used for producing aliases (PR9177). Fortunately the 1330b57cec5SDimitry Andric // llvm mangler on ELF is a nop, so we can just avoid adding the \01 134a7dea167SDimitry Andric // marker. 1350b57cec5SDimitry Andric char GlobalPrefix = 1360b57cec5SDimitry Andric getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix(); 137a7dea167SDimitry Andric if (GlobalPrefix) 1380b57cec5SDimitry Andric Out << '\01'; // LLVM IR Marker for __asm("foo") 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric Out << ALA->getLabel(); 1410b57cec5SDimitry Andric return; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric const ASTContext &ASTContext = getASTContext(); 1450b57cec5SDimitry Andric CCMangling CC = getCallingConvMangling(ASTContext, D); 1460b57cec5SDimitry Andric bool MCXX = shouldMangleCXXName(D); 1470b57cec5SDimitry Andric const TargetInfo &TI = Context.getTargetInfo(); 1480b57cec5SDimitry Andric if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { 1490b57cec5SDimitry Andric if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 1500b57cec5SDimitry Andric mangleObjCMethodName(OMD, Out); 1510b57cec5SDimitry Andric else 1520b57cec5SDimitry Andric mangleCXXName(D, Out); 1530b57cec5SDimitry Andric return; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric Out << '\01'; 1570b57cec5SDimitry Andric if (CC == CCM_Std) 1580b57cec5SDimitry Andric Out << '_'; 1590b57cec5SDimitry Andric else if (CC == CCM_Fast) 1600b57cec5SDimitry Andric Out << '@'; 1610b57cec5SDimitry Andric else if (CC == CCM_RegCall) 1620b57cec5SDimitry Andric Out << "__regcall3__"; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric if (!MCXX) 1650b57cec5SDimitry Andric Out << D->getIdentifier()->getName(); 1660b57cec5SDimitry Andric else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 1670b57cec5SDimitry Andric mangleObjCMethodName(OMD, Out); 1680b57cec5SDimitry Andric else 1690b57cec5SDimitry Andric mangleCXXName(D, Out); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric const FunctionDecl *FD = cast<FunctionDecl>(D); 1720b57cec5SDimitry Andric const FunctionType *FT = FD->getType()->castAs<FunctionType>(); 1730b57cec5SDimitry Andric const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT); 1740b57cec5SDimitry Andric if (CC == CCM_Vector) 1750b57cec5SDimitry Andric Out << '@'; 1760b57cec5SDimitry Andric Out << '@'; 1770b57cec5SDimitry Andric if (!Proto) { 1780b57cec5SDimitry Andric Out << '0'; 1790b57cec5SDimitry Andric return; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric assert(!Proto->isVariadic()); 1820b57cec5SDimitry Andric unsigned ArgWords = 0; 1830b57cec5SDimitry Andric if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) 1840b57cec5SDimitry Andric if (!MD->isStatic()) 1850b57cec5SDimitry Andric ++ArgWords; 1860b57cec5SDimitry Andric for (const auto &AT : Proto->param_types()) 1870b57cec5SDimitry Andric // Size should be aligned to pointer size. 1880b57cec5SDimitry Andric ArgWords += 1890b57cec5SDimitry Andric llvm::alignTo(ASTContext.getTypeSize(AT), TI.getPointerWidth(0)) / 1900b57cec5SDimitry Andric TI.getPointerWidth(0); 1910b57cec5SDimitry Andric Out << ((TI.getPointerWidth(0) / 8) * ArgWords); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void MangleContext::mangleGlobalBlock(const BlockDecl *BD, 1950b57cec5SDimitry Andric const NamedDecl *ID, 1960b57cec5SDimitry Andric raw_ostream &Out) { 1970b57cec5SDimitry Andric unsigned discriminator = getBlockId(BD, false); 1980b57cec5SDimitry Andric if (ID) { 1990b57cec5SDimitry Andric if (shouldMangleDeclName(ID)) 2000b57cec5SDimitry Andric mangleName(ID, Out); 2010b57cec5SDimitry Andric else { 2020b57cec5SDimitry Andric Out << ID->getIdentifier()->getName(); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric if (discriminator == 0) 2060b57cec5SDimitry Andric Out << "_block_invoke"; 2070b57cec5SDimitry Andric else 2080b57cec5SDimitry Andric Out << "_block_invoke_" << discriminator+1; 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, 2120b57cec5SDimitry Andric CXXCtorType CT, const BlockDecl *BD, 2130b57cec5SDimitry Andric raw_ostream &ResStream) { 2140b57cec5SDimitry Andric SmallString<64> Buffer; 2150b57cec5SDimitry Andric llvm::raw_svector_ostream Out(Buffer); 2160b57cec5SDimitry Andric mangleCXXCtor(CD, CT, Out); 2170b57cec5SDimitry Andric mangleFunctionBlock(*this, Buffer, BD, ResStream); 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, 2210b57cec5SDimitry Andric CXXDtorType DT, const BlockDecl *BD, 2220b57cec5SDimitry Andric raw_ostream &ResStream) { 2230b57cec5SDimitry Andric SmallString<64> Buffer; 2240b57cec5SDimitry Andric llvm::raw_svector_ostream Out(Buffer); 2250b57cec5SDimitry Andric mangleCXXDtor(DD, DT, Out); 2260b57cec5SDimitry Andric mangleFunctionBlock(*this, Buffer, BD, ResStream); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, 2300b57cec5SDimitry Andric raw_ostream &Out) { 2310b57cec5SDimitry Andric assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric SmallString<64> Buffer; 2340b57cec5SDimitry Andric llvm::raw_svector_ostream Stream(Buffer); 2350b57cec5SDimitry Andric if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { 2360b57cec5SDimitry Andric mangleObjCMethodName(Method, Stream); 2370b57cec5SDimitry Andric } else { 2380b57cec5SDimitry Andric assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) && 2390b57cec5SDimitry Andric "expected a NamedDecl or BlockDecl"); 2400b57cec5SDimitry Andric if (isa<BlockDecl>(DC)) 2410b57cec5SDimitry Andric for (; DC && isa<BlockDecl>(DC); DC = DC->getParent()) 2420b57cec5SDimitry Andric (void) getBlockId(cast<BlockDecl>(DC), true); 2430b57cec5SDimitry Andric assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) && 2440b57cec5SDimitry Andric "expected a TranslationUnitDecl or a NamedDecl"); 2450b57cec5SDimitry Andric if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) 2460b57cec5SDimitry Andric mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); 2470b57cec5SDimitry Andric else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) 2480b57cec5SDimitry Andric mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); 2490b57cec5SDimitry Andric else if (auto ND = dyn_cast<NamedDecl>(DC)) { 2500b57cec5SDimitry Andric if (!shouldMangleDeclName(ND) && ND->getIdentifier()) 2510b57cec5SDimitry Andric Stream << ND->getIdentifier()->getName(); 2520b57cec5SDimitry Andric else { 2530b57cec5SDimitry Andric // FIXME: We were doing a mangleUnqualifiedName() before, but that's 2540b57cec5SDimitry Andric // a private member of a class that will soon itself be private to the 2550b57cec5SDimitry Andric // Itanium C++ ABI object. What should we do now? Right now, I'm just 2560b57cec5SDimitry Andric // calling the mangleName() method on the MangleContext; is there a 2570b57cec5SDimitry Andric // better way? 2580b57cec5SDimitry Andric mangleName(ND, Stream); 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric mangleFunctionBlock(*this, Buffer, BD, Out); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, 2660b57cec5SDimitry Andric raw_ostream &OS) { 2670b57cec5SDimitry Andric const ObjCContainerDecl *CD = 2680b57cec5SDimitry Andric dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); 2690b57cec5SDimitry Andric assert (CD && "Missing container decl in GetNameForMethod"); 2700b57cec5SDimitry Andric OS << (MD->isInstanceMethod() ? '-' : '+') << '['; 2710b57cec5SDimitry Andric if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) { 2720b57cec5SDimitry Andric OS << CID->getClassInterface()->getName(); 2730b57cec5SDimitry Andric OS << '(' << *CID << ')'; 2740b57cec5SDimitry Andric } else { 2750b57cec5SDimitry Andric OS << CD->getName(); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric OS << ' '; 2780b57cec5SDimitry Andric MD->getSelector().print(OS); 2790b57cec5SDimitry Andric OS << ']'; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, 2830b57cec5SDimitry Andric raw_ostream &Out) { 2840b57cec5SDimitry Andric SmallString<64> Name; 2850b57cec5SDimitry Andric llvm::raw_svector_ostream OS(Name); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric mangleObjCMethodNameWithoutSize(MD, OS); 2880b57cec5SDimitry Andric Out << OS.str().size() << OS.str(); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric class ASTNameGenerator::Implementation { 2920b57cec5SDimitry Andric std::unique_ptr<MangleContext> MC; 2930b57cec5SDimitry Andric llvm::DataLayout DL; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric public: 2960b57cec5SDimitry Andric explicit Implementation(ASTContext &Ctx) 2970b57cec5SDimitry Andric : MC(Ctx.createMangleContext()), DL(Ctx.getTargetInfo().getDataLayout()) { 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric bool writeName(const Decl *D, raw_ostream &OS) { 3010b57cec5SDimitry Andric // First apply frontend mangling. 3020b57cec5SDimitry Andric SmallString<128> FrontendBuf; 3030b57cec5SDimitry Andric llvm::raw_svector_ostream FrontendBufOS(FrontendBuf); 3040b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(D)) { 3050b57cec5SDimitry Andric if (FD->isDependentContext()) 3060b57cec5SDimitry Andric return true; 3070b57cec5SDimitry Andric if (writeFuncOrVarName(FD, FrontendBufOS)) 3080b57cec5SDimitry Andric return true; 3090b57cec5SDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) { 3100b57cec5SDimitry Andric if (writeFuncOrVarName(VD, FrontendBufOS)) 3110b57cec5SDimitry Andric return true; 3120b57cec5SDimitry Andric } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) { 3130b57cec5SDimitry Andric MC->mangleObjCMethodNameWithoutSize(MD, OS); 3140b57cec5SDimitry Andric return false; 3150b57cec5SDimitry Andric } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { 3160b57cec5SDimitry Andric writeObjCClassName(ID, FrontendBufOS); 3170b57cec5SDimitry Andric } else { 3180b57cec5SDimitry Andric return true; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric // Now apply backend mangling. 3220b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL); 3230b57cec5SDimitry Andric return false; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric std::string getName(const Decl *D) { 3270b57cec5SDimitry Andric std::string Name; 3280b57cec5SDimitry Andric { 3290b57cec5SDimitry Andric llvm::raw_string_ostream OS(Name); 3300b57cec5SDimitry Andric writeName(D, OS); 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric return Name; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric enum ObjCKind { 3360b57cec5SDimitry Andric ObjCClass, 3370b57cec5SDimitry Andric ObjCMetaclass, 3380b57cec5SDimitry Andric }; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric static StringRef getClassSymbolPrefix(ObjCKind Kind, 3410b57cec5SDimitry Andric const ASTContext &Context) { 3420b57cec5SDimitry Andric if (Context.getLangOpts().ObjCRuntime.isGNUFamily()) 3430b57cec5SDimitry Andric return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_"; 3440b57cec5SDimitry Andric return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_"; 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) { 3480b57cec5SDimitry Andric StringRef ClassName; 3490b57cec5SDimitry Andric if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) 3500b57cec5SDimitry Andric ClassName = OID->getObjCRuntimeNameAsString(); 3510b57cec5SDimitry Andric else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD)) 3520b57cec5SDimitry Andric ClassName = OID->getObjCRuntimeNameAsString(); 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric if (ClassName.empty()) 3550b57cec5SDimitry Andric return {}; 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string { 3580b57cec5SDimitry Andric SmallString<40> Mangled; 3590b57cec5SDimitry Andric auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext()); 3600b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL); 3610b57cec5SDimitry Andric return Mangled.str(); 3620b57cec5SDimitry Andric }; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric return { 3650b57cec5SDimitry Andric Mangle(ObjCClass, ClassName), 3660b57cec5SDimitry Andric Mangle(ObjCMetaclass, ClassName), 3670b57cec5SDimitry Andric }; 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric std::vector<std::string> getAllManglings(const Decl *D) { 3710b57cec5SDimitry Andric if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D)) 3720b57cec5SDimitry Andric return getAllManglings(OCD); 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D))) 3750b57cec5SDimitry Andric return {}; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric const NamedDecl *ND = cast<NamedDecl>(D); 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric ASTContext &Ctx = ND->getASTContext(); 3800b57cec5SDimitry Andric std::unique_ptr<MangleContext> M(Ctx.createMangleContext()); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric std::vector<std::string> Manglings; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { 3850b57cec5SDimitry Andric auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, 3860b57cec5SDimitry Andric /*IsCXXMethod=*/true); 387a7dea167SDimitry Andric auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv(); 3880b57cec5SDimitry Andric return CC == DefaultCC; 3890b57cec5SDimitry Andric }; 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) { 3920b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Base)); 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) 3950b57cec5SDimitry Andric if (!CD->getParent()->isAbstract()) 3960b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete)); 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isMicrosoft()) 3990b57cec5SDimitry Andric if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor()) 4000b57cec5SDimitry Andric if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0)) 4010b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure)); 4020b57cec5SDimitry Andric } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) { 4030b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Base)); 4040b57cec5SDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) { 4050b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete)); 4060b57cec5SDimitry Andric if (DD->isVirtual()) 4070b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting)); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) { 4100b57cec5SDimitry Andric Manglings.emplace_back(getName(ND)); 4110b57cec5SDimitry Andric if (MD->isVirtual()) 4120b57cec5SDimitry Andric if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) 4130b57cec5SDimitry Andric for (const auto &T : *TIV) 4140b57cec5SDimitry Andric Manglings.emplace_back(getMangledThunk(MD, T)); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric return Manglings; 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric private: 4210b57cec5SDimitry Andric bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) { 4220b57cec5SDimitry Andric if (MC->shouldMangleDeclName(D)) { 4230b57cec5SDimitry Andric if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D)) 4240b57cec5SDimitry Andric MC->mangleCXXCtor(CtorD, Ctor_Complete, OS); 4250b57cec5SDimitry Andric else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D)) 4260b57cec5SDimitry Andric MC->mangleCXXDtor(DtorD, Dtor_Complete, OS); 4270b57cec5SDimitry Andric else 4280b57cec5SDimitry Andric MC->mangleName(D, OS); 4290b57cec5SDimitry Andric return false; 4300b57cec5SDimitry Andric } else { 4310b57cec5SDimitry Andric IdentifierInfo *II = D->getIdentifier(); 4320b57cec5SDimitry Andric if (!II) 4330b57cec5SDimitry Andric return true; 4340b57cec5SDimitry Andric OS << II->getName(); 4350b57cec5SDimitry Andric return false; 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) { 4400b57cec5SDimitry Andric OS << getClassSymbolPrefix(ObjCClass, D->getASTContext()); 4410b57cec5SDimitry Andric OS << D->getObjCRuntimeNameAsString(); 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) { 4450b57cec5SDimitry Andric std::string FrontendBuf; 4460b57cec5SDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) 4490b57cec5SDimitry Andric MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS); 4500b57cec5SDimitry Andric else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) 4510b57cec5SDimitry Andric MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS); 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric std::string BackendBuf; 4540b57cec5SDimitry Andric llvm::raw_string_ostream BOS(BackendBuf); 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric return BOS.str(); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) { 4620b57cec5SDimitry Andric std::string FrontendBuf; 4630b57cec5SDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf); 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric MC->mangleThunk(MD, T, FOS); 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric std::string BackendBuf; 4680b57cec5SDimitry Andric llvm::raw_string_ostream BOS(BackendBuf); 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric return BOS.str(); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric }; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx) 477a7dea167SDimitry Andric : Impl(std::make_unique<Implementation>(Ctx)) {} 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric ASTNameGenerator::~ASTNameGenerator() {} 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) { 4820b57cec5SDimitry Andric return Impl->writeName(D, OS); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric std::string ASTNameGenerator::getName(const Decl *D) { 4860b57cec5SDimitry Andric return Impl->getName(D); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) { 4900b57cec5SDimitry Andric return Impl->getAllManglings(D); 4910b57cec5SDimitry Andric } 492