xref: /freebsd/contrib/llvm-project/clang/lib/AST/Mangle.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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