Home | History | Annotate | Line # | Download | only in AST
      1      1.1  joerg //===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
      2      1.1  joerg //
      3      1.1  joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4      1.1  joerg // See https://llvm.org/LICENSE.txt for license information.
      5      1.1  joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6      1.1  joerg //
      7      1.1  joerg //===----------------------------------------------------------------------===//
      8      1.1  joerg //
      9      1.1  joerg // Implements generic name mangling support for blocks and Objective-C.
     10      1.1  joerg //
     11      1.1  joerg //===----------------------------------------------------------------------===//
     12      1.1  joerg #include "clang/AST/Attr.h"
     13      1.1  joerg #include "clang/AST/ASTContext.h"
     14      1.1  joerg #include "clang/AST/Decl.h"
     15      1.1  joerg #include "clang/AST/DeclCXX.h"
     16      1.1  joerg #include "clang/AST/DeclObjC.h"
     17      1.1  joerg #include "clang/AST/DeclTemplate.h"
     18      1.1  joerg #include "clang/AST/ExprCXX.h"
     19      1.1  joerg #include "clang/AST/Mangle.h"
     20      1.1  joerg #include "clang/AST/VTableBuilder.h"
     21      1.1  joerg #include "clang/Basic/ABI.h"
     22      1.1  joerg #include "clang/Basic/SourceManager.h"
     23      1.1  joerg #include "clang/Basic/TargetInfo.h"
     24      1.1  joerg #include "llvm/ADT/StringExtras.h"
     25      1.1  joerg #include "llvm/IR/DataLayout.h"
     26      1.1  joerg #include "llvm/IR/Mangler.h"
     27      1.1  joerg #include "llvm/Support/ErrorHandling.h"
     28  1.1.1.2  joerg #include "llvm/Support/Format.h"
     29      1.1  joerg #include "llvm/Support/raw_ostream.h"
     30      1.1  joerg 
     31      1.1  joerg using namespace clang;
     32      1.1  joerg 
     33      1.1  joerg // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
     34      1.1  joerg // much to be desired. Come up with a better mangling scheme.
     35      1.1  joerg 
     36      1.1  joerg static void mangleFunctionBlock(MangleContext &Context,
     37      1.1  joerg                                 StringRef Outer,
     38      1.1  joerg                                 const BlockDecl *BD,
     39      1.1  joerg                                 raw_ostream &Out) {
     40      1.1  joerg   unsigned discriminator = Context.getBlockId(BD, true);
     41      1.1  joerg   if (discriminator == 0)
     42      1.1  joerg     Out << "__" << Outer << "_block_invoke";
     43      1.1  joerg   else
     44      1.1  joerg     Out << "__" << Outer << "_block_invoke_" << discriminator+1;
     45      1.1  joerg }
     46      1.1  joerg 
     47      1.1  joerg void MangleContext::anchor() { }
     48      1.1  joerg 
     49      1.1  joerg enum CCMangling {
     50      1.1  joerg   CCM_Other,
     51      1.1  joerg   CCM_Fast,
     52      1.1  joerg   CCM_RegCall,
     53      1.1  joerg   CCM_Vector,
     54  1.1.1.2  joerg   CCM_Std,
     55  1.1.1.2  joerg   CCM_WasmMainArgcArgv
     56      1.1  joerg };
     57      1.1  joerg 
     58      1.1  joerg static bool isExternC(const NamedDecl *ND) {
     59      1.1  joerg   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
     60      1.1  joerg     return FD->isExternC();
     61  1.1.1.2  joerg   if (const VarDecl *VD = dyn_cast<VarDecl>(ND))
     62  1.1.1.2  joerg     return VD->isExternC();
     63  1.1.1.2  joerg   return false;
     64      1.1  joerg }
     65      1.1  joerg 
     66      1.1  joerg static CCMangling getCallingConvMangling(const ASTContext &Context,
     67      1.1  joerg                                          const NamedDecl *ND) {
     68      1.1  joerg   const TargetInfo &TI = Context.getTargetInfo();
     69      1.1  joerg   const llvm::Triple &Triple = TI.getTriple();
     70  1.1.1.2  joerg 
     71  1.1.1.2  joerg   // On wasm, the argc/argv form of "main" is renamed so that the startup code
     72  1.1.1.2  joerg   // can call it with the correct function signature.
     73  1.1.1.2  joerg   // On Emscripten, users may be exporting "main" and expecting to call it
     74  1.1.1.2  joerg   // themselves, so we can't mangle it.
     75  1.1.1.2  joerg   if (Triple.isWasm() && !Triple.isOSEmscripten())
     76  1.1.1.2  joerg     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
     77  1.1.1.2  joerg       if (FD->isMain() && FD->hasPrototype() && FD->param_size() == 2)
     78  1.1.1.2  joerg         return CCM_WasmMainArgcArgv;
     79  1.1.1.2  joerg 
     80  1.1.1.2  joerg   if (!Triple.isOSWindows() || !Triple.isX86())
     81      1.1  joerg     return CCM_Other;
     82      1.1  joerg 
     83      1.1  joerg   if (Context.getLangOpts().CPlusPlus && !isExternC(ND) &&
     84      1.1  joerg       TI.getCXXABI() == TargetCXXABI::Microsoft)
     85      1.1  joerg     return CCM_Other;
     86      1.1  joerg 
     87      1.1  joerg   const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
     88      1.1  joerg   if (!FD)
     89      1.1  joerg     return CCM_Other;
     90      1.1  joerg   QualType T = FD->getType();
     91      1.1  joerg 
     92      1.1  joerg   const FunctionType *FT = T->castAs<FunctionType>();
     93      1.1  joerg 
     94      1.1  joerg   CallingConv CC = FT->getCallConv();
     95      1.1  joerg   switch (CC) {
     96      1.1  joerg   default:
     97      1.1  joerg     return CCM_Other;
     98      1.1  joerg   case CC_X86FastCall:
     99      1.1  joerg     return CCM_Fast;
    100      1.1  joerg   case CC_X86StdCall:
    101      1.1  joerg     return CCM_Std;
    102      1.1  joerg   case CC_X86VectorCall:
    103      1.1  joerg     return CCM_Vector;
    104      1.1  joerg   }
    105      1.1  joerg }
    106      1.1  joerg 
    107      1.1  joerg bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
    108      1.1  joerg   const ASTContext &ASTContext = getASTContext();
    109      1.1  joerg 
    110      1.1  joerg   CCMangling CC = getCallingConvMangling(ASTContext, D);
    111      1.1  joerg   if (CC != CCM_Other)
    112      1.1  joerg     return true;
    113      1.1  joerg 
    114      1.1  joerg   // If the declaration has an owning module for linkage purposes that needs to
    115      1.1  joerg   // be mangled, we must mangle its name.
    116      1.1  joerg   if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage())
    117      1.1  joerg     return true;
    118      1.1  joerg 
    119  1.1.1.2  joerg   // C functions with internal linkage have to be mangled with option
    120  1.1.1.2  joerg   // -funique-internal-linkage-names.
    121  1.1.1.2  joerg   if (!getASTContext().getLangOpts().CPlusPlus &&
    122  1.1.1.2  joerg       isUniqueInternalLinkageDecl(D))
    123  1.1.1.2  joerg     return true;
    124  1.1.1.2  joerg 
    125      1.1  joerg   // In C, functions with no attributes never need to be mangled. Fastpath them.
    126      1.1  joerg   if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
    127      1.1  joerg     return false;
    128      1.1  joerg 
    129      1.1  joerg   // Any decl can be declared with __asm("foo") on it, and this takes precedence
    130      1.1  joerg   // over all other naming in the .o file.
    131      1.1  joerg   if (D->hasAttr<AsmLabelAttr>())
    132      1.1  joerg     return true;
    133      1.1  joerg 
    134  1.1.1.2  joerg   // Declarations that don't have identifier names always need to be mangled.
    135  1.1.1.2  joerg   if (isa<MSGuidDecl>(D))
    136  1.1.1.2  joerg     return true;
    137  1.1.1.2  joerg 
    138      1.1  joerg   return shouldMangleCXXName(D);
    139      1.1  joerg }
    140      1.1  joerg 
    141  1.1.1.2  joerg void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
    142  1.1.1.2  joerg   const ASTContext &ASTContext = getASTContext();
    143  1.1.1.2  joerg   const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
    144  1.1.1.2  joerg 
    145      1.1  joerg   // Any decl can be declared with __asm("foo") on it, and this takes precedence
    146      1.1  joerg   // over all other naming in the .o file.
    147      1.1  joerg   if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
    148      1.1  joerg     // If we have an asm name, then we use it as the mangling.
    149      1.1  joerg 
    150      1.1  joerg     // If the label isn't literal, or if this is an alias for an LLVM intrinsic,
    151      1.1  joerg     // do not add a "\01" prefix.
    152      1.1  joerg     if (!ALA->getIsLiteralLabel() || ALA->getLabel().startswith("llvm.")) {
    153      1.1  joerg       Out << ALA->getLabel();
    154      1.1  joerg       return;
    155      1.1  joerg     }
    156      1.1  joerg 
    157      1.1  joerg     // Adding the prefix can cause problems when one file has a "foo" and
    158      1.1  joerg     // another has a "\01foo". That is known to happen on ELF with the
    159      1.1  joerg     // tricks normally used for producing aliases (PR9177). Fortunately the
    160      1.1  joerg     // llvm mangler on ELF is a nop, so we can just avoid adding the \01
    161      1.1  joerg     // marker.
    162  1.1.1.2  joerg     StringRef UserLabelPrefix =
    163  1.1.1.2  joerg         getASTContext().getTargetInfo().getUserLabelPrefix();
    164  1.1.1.2  joerg #ifndef NDEBUG
    165      1.1  joerg     char GlobalPrefix =
    166  1.1.1.2  joerg         llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString())
    167  1.1.1.2  joerg             .getGlobalPrefix();
    168  1.1.1.2  joerg     assert((UserLabelPrefix.empty() && !GlobalPrefix) ||
    169  1.1.1.2  joerg            (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix));
    170  1.1.1.2  joerg #endif
    171  1.1.1.2  joerg     if (!UserLabelPrefix.empty())
    172      1.1  joerg       Out << '\01'; // LLVM IR Marker for __asm("foo")
    173      1.1  joerg 
    174      1.1  joerg     Out << ALA->getLabel();
    175      1.1  joerg     return;
    176      1.1  joerg   }
    177      1.1  joerg 
    178  1.1.1.2  joerg   if (auto *GD = dyn_cast<MSGuidDecl>(D))
    179  1.1.1.2  joerg     return mangleMSGuidDecl(GD, Out);
    180  1.1.1.2  joerg 
    181      1.1  joerg   CCMangling CC = getCallingConvMangling(ASTContext, D);
    182  1.1.1.2  joerg 
    183  1.1.1.2  joerg   if (CC == CCM_WasmMainArgcArgv) {
    184  1.1.1.2  joerg     Out << "__main_argc_argv";
    185  1.1.1.2  joerg     return;
    186  1.1.1.2  joerg   }
    187  1.1.1.2  joerg 
    188      1.1  joerg   bool MCXX = shouldMangleCXXName(D);
    189      1.1  joerg   const TargetInfo &TI = Context.getTargetInfo();
    190      1.1  joerg   if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
    191      1.1  joerg     if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
    192  1.1.1.2  joerg       mangleObjCMethodNameAsSourceName(OMD, Out);
    193      1.1  joerg     else
    194  1.1.1.2  joerg       mangleCXXName(GD, Out);
    195      1.1  joerg     return;
    196      1.1  joerg   }
    197      1.1  joerg 
    198      1.1  joerg   Out << '\01';
    199      1.1  joerg   if (CC == CCM_Std)
    200      1.1  joerg     Out << '_';
    201      1.1  joerg   else if (CC == CCM_Fast)
    202      1.1  joerg     Out << '@';
    203      1.1  joerg   else if (CC == CCM_RegCall)
    204      1.1  joerg     Out << "__regcall3__";
    205      1.1  joerg 
    206      1.1  joerg   if (!MCXX)
    207      1.1  joerg     Out << D->getIdentifier()->getName();
    208      1.1  joerg   else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
    209  1.1.1.2  joerg     mangleObjCMethodNameAsSourceName(OMD, Out);
    210      1.1  joerg   else
    211  1.1.1.2  joerg     mangleCXXName(GD, Out);
    212      1.1  joerg 
    213      1.1  joerg   const FunctionDecl *FD = cast<FunctionDecl>(D);
    214      1.1  joerg   const FunctionType *FT = FD->getType()->castAs<FunctionType>();
    215      1.1  joerg   const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);
    216      1.1  joerg   if (CC == CCM_Vector)
    217      1.1  joerg     Out << '@';
    218      1.1  joerg   Out << '@';
    219      1.1  joerg   if (!Proto) {
    220      1.1  joerg     Out << '0';
    221      1.1  joerg     return;
    222      1.1  joerg   }
    223      1.1  joerg   assert(!Proto->isVariadic());
    224      1.1  joerg   unsigned ArgWords = 0;
    225      1.1  joerg   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
    226      1.1  joerg     if (!MD->isStatic())
    227      1.1  joerg       ++ArgWords;
    228      1.1  joerg   for (const auto &AT : Proto->param_types())
    229      1.1  joerg     // Size should be aligned to pointer size.
    230      1.1  joerg     ArgWords +=
    231      1.1  joerg         llvm::alignTo(ASTContext.getTypeSize(AT), TI.getPointerWidth(0)) /
    232      1.1  joerg         TI.getPointerWidth(0);
    233      1.1  joerg   Out << ((TI.getPointerWidth(0) / 8) * ArgWords);
    234      1.1  joerg }
    235      1.1  joerg 
    236  1.1.1.2  joerg void MangleContext::mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream &Out) {
    237  1.1.1.2  joerg   // For now, follow the MSVC naming convention for GUID objects on all
    238  1.1.1.2  joerg   // targets.
    239  1.1.1.2  joerg   MSGuidDecl::Parts P = GD->getParts();
    240  1.1.1.2  joerg   Out << llvm::format("_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_",
    241  1.1.1.2  joerg                       P.Part1, P.Part2, P.Part3);
    242  1.1.1.2  joerg   unsigned I = 0;
    243  1.1.1.2  joerg   for (uint8_t C : P.Part4And5) {
    244  1.1.1.2  joerg     Out << llvm::format("%02" PRIx8, C);
    245  1.1.1.2  joerg     if (++I == 2)
    246  1.1.1.2  joerg       Out << "_";
    247  1.1.1.2  joerg   }
    248  1.1.1.2  joerg }
    249  1.1.1.2  joerg 
    250      1.1  joerg void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
    251      1.1  joerg                                       const NamedDecl *ID,
    252      1.1  joerg                                       raw_ostream &Out) {
    253      1.1  joerg   unsigned discriminator = getBlockId(BD, false);
    254      1.1  joerg   if (ID) {
    255      1.1  joerg     if (shouldMangleDeclName(ID))
    256      1.1  joerg       mangleName(ID, Out);
    257      1.1  joerg     else {
    258      1.1  joerg       Out << ID->getIdentifier()->getName();
    259      1.1  joerg     }
    260      1.1  joerg   }
    261      1.1  joerg   if (discriminator == 0)
    262      1.1  joerg     Out << "_block_invoke";
    263      1.1  joerg   else
    264      1.1  joerg     Out << "_block_invoke_" << discriminator+1;
    265      1.1  joerg }
    266      1.1  joerg 
    267      1.1  joerg void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
    268      1.1  joerg                                     CXXCtorType CT, const BlockDecl *BD,
    269      1.1  joerg                                     raw_ostream &ResStream) {
    270      1.1  joerg   SmallString<64> Buffer;
    271      1.1  joerg   llvm::raw_svector_ostream Out(Buffer);
    272  1.1.1.2  joerg   mangleName(GlobalDecl(CD, CT), Out);
    273      1.1  joerg   mangleFunctionBlock(*this, Buffer, BD, ResStream);
    274      1.1  joerg }
    275      1.1  joerg 
    276      1.1  joerg void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
    277      1.1  joerg                                     CXXDtorType DT, const BlockDecl *BD,
    278      1.1  joerg                                     raw_ostream &ResStream) {
    279      1.1  joerg   SmallString<64> Buffer;
    280      1.1  joerg   llvm::raw_svector_ostream Out(Buffer);
    281  1.1.1.2  joerg   mangleName(GlobalDecl(DD, DT), Out);
    282      1.1  joerg   mangleFunctionBlock(*this, Buffer, BD, ResStream);
    283      1.1  joerg }
    284      1.1  joerg 
    285      1.1  joerg void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
    286      1.1  joerg                                 raw_ostream &Out) {
    287      1.1  joerg   assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
    288      1.1  joerg 
    289      1.1  joerg   SmallString<64> Buffer;
    290      1.1  joerg   llvm::raw_svector_ostream Stream(Buffer);
    291      1.1  joerg   if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
    292  1.1.1.2  joerg     mangleObjCMethodNameAsSourceName(Method, Stream);
    293      1.1  joerg   } else {
    294      1.1  joerg     assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
    295      1.1  joerg            "expected a NamedDecl or BlockDecl");
    296      1.1  joerg     if (isa<BlockDecl>(DC))
    297      1.1  joerg       for (; DC && isa<BlockDecl>(DC); DC = DC->getParent())
    298      1.1  joerg         (void) getBlockId(cast<BlockDecl>(DC), true);
    299      1.1  joerg     assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
    300      1.1  joerg            "expected a TranslationUnitDecl or a NamedDecl");
    301      1.1  joerg     if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
    302      1.1  joerg       mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
    303      1.1  joerg     else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
    304      1.1  joerg       mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
    305      1.1  joerg     else if (auto ND = dyn_cast<NamedDecl>(DC)) {
    306      1.1  joerg       if (!shouldMangleDeclName(ND) && ND->getIdentifier())
    307      1.1  joerg         Stream << ND->getIdentifier()->getName();
    308      1.1  joerg       else {
    309      1.1  joerg         // FIXME: We were doing a mangleUnqualifiedName() before, but that's
    310      1.1  joerg         // a private member of a class that will soon itself be private to the
    311      1.1  joerg         // Itanium C++ ABI object. What should we do now? Right now, I'm just
    312      1.1  joerg         // calling the mangleName() method on the MangleContext; is there a
    313      1.1  joerg         // better way?
    314      1.1  joerg         mangleName(ND, Stream);
    315      1.1  joerg       }
    316      1.1  joerg     }
    317      1.1  joerg   }
    318      1.1  joerg   mangleFunctionBlock(*this, Buffer, BD, Out);
    319      1.1  joerg }
    320      1.1  joerg 
    321  1.1.1.2  joerg void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
    322  1.1.1.2  joerg                                          raw_ostream &OS,
    323  1.1.1.2  joerg                                          bool includePrefixByte,
    324  1.1.1.2  joerg                                          bool includeCategoryNamespace) {
    325  1.1.1.2  joerg   if (getASTContext().getLangOpts().ObjCRuntime.isGNUFamily()) {
    326  1.1.1.2  joerg     // This is the mangling we've always used on the GNU runtimes, but it
    327  1.1.1.2  joerg     // has obvious collisions in the face of underscores within class
    328  1.1.1.2  joerg     // names, category names, and selectors; maybe we should improve it.
    329  1.1.1.2  joerg 
    330  1.1.1.2  joerg     OS << (MD->isClassMethod() ? "_c_" : "_i_")
    331  1.1.1.2  joerg        << MD->getClassInterface()->getName() << '_';
    332  1.1.1.2  joerg 
    333  1.1.1.2  joerg     if (includeCategoryNamespace) {
    334  1.1.1.2  joerg       if (auto category = MD->getCategory())
    335  1.1.1.2  joerg         OS << category->getName();
    336  1.1.1.2  joerg     }
    337  1.1.1.2  joerg     OS << '_';
    338  1.1.1.2  joerg 
    339  1.1.1.2  joerg     auto selector = MD->getSelector();
    340  1.1.1.2  joerg     for (unsigned slotIndex = 0,
    341  1.1.1.2  joerg                   numArgs = selector.getNumArgs(),
    342  1.1.1.2  joerg                   slotEnd = std::max(numArgs, 1U);
    343  1.1.1.2  joerg            slotIndex != slotEnd; ++slotIndex) {
    344  1.1.1.2  joerg       if (auto name = selector.getIdentifierInfoForSlot(slotIndex))
    345  1.1.1.2  joerg         OS << name->getName();
    346  1.1.1.2  joerg 
    347  1.1.1.2  joerg       // Replace all the positions that would've been ':' with '_'.
    348  1.1.1.2  joerg       // That's after each slot except that a unary selector doesn't
    349  1.1.1.2  joerg       // end in ':'.
    350  1.1.1.2  joerg       if (numArgs)
    351  1.1.1.2  joerg         OS << '_';
    352  1.1.1.2  joerg     }
    353  1.1.1.2  joerg 
    354  1.1.1.2  joerg     return;
    355  1.1.1.2  joerg   }
    356  1.1.1.2  joerg 
    357  1.1.1.2  joerg   // \01+[ContainerName(CategoryName) SelectorName]
    358  1.1.1.2  joerg   if (includePrefixByte) {
    359  1.1.1.2  joerg     OS << '\01';
    360  1.1.1.2  joerg   }
    361      1.1  joerg   OS << (MD->isInstanceMethod() ? '-' : '+') << '[';
    362  1.1.1.2  joerg   if (const auto *CID = MD->getCategory()) {
    363      1.1  joerg     OS << CID->getClassInterface()->getName();
    364  1.1.1.2  joerg     if (includeCategoryNamespace) {
    365  1.1.1.2  joerg       OS << '(' << *CID << ')';
    366  1.1.1.2  joerg     }
    367  1.1.1.2  joerg   } else if (const auto *CD =
    368  1.1.1.2  joerg                  dyn_cast<ObjCContainerDecl>(MD->getDeclContext())) {
    369      1.1  joerg     OS << CD->getName();
    370  1.1.1.2  joerg   } else {
    371  1.1.1.2  joerg     llvm_unreachable("Unexpected ObjC method decl context");
    372      1.1  joerg   }
    373      1.1  joerg   OS << ' ';
    374      1.1  joerg   MD->getSelector().print(OS);
    375      1.1  joerg   OS << ']';
    376      1.1  joerg }
    377      1.1  joerg 
    378  1.1.1.2  joerg void MangleContext::mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,
    379  1.1.1.2  joerg                                                      raw_ostream &Out) {
    380      1.1  joerg   SmallString<64> Name;
    381      1.1  joerg   llvm::raw_svector_ostream OS(Name);
    382      1.1  joerg 
    383  1.1.1.2  joerg   mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,
    384  1.1.1.2  joerg                        /*includeCategoryNamespace=*/true);
    385      1.1  joerg   Out << OS.str().size() << OS.str();
    386      1.1  joerg }
    387      1.1  joerg 
    388      1.1  joerg class ASTNameGenerator::Implementation {
    389      1.1  joerg   std::unique_ptr<MangleContext> MC;
    390      1.1  joerg   llvm::DataLayout DL;
    391      1.1  joerg 
    392      1.1  joerg public:
    393      1.1  joerg   explicit Implementation(ASTContext &Ctx)
    394  1.1.1.2  joerg       : MC(Ctx.createMangleContext()),
    395  1.1.1.2  joerg         DL(Ctx.getTargetInfo().getDataLayoutString()) {}
    396      1.1  joerg 
    397      1.1  joerg   bool writeName(const Decl *D, raw_ostream &OS) {
    398      1.1  joerg     // First apply frontend mangling.
    399      1.1  joerg     SmallString<128> FrontendBuf;
    400      1.1  joerg     llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
    401      1.1  joerg     if (auto *FD = dyn_cast<FunctionDecl>(D)) {
    402      1.1  joerg       if (FD->isDependentContext())
    403      1.1  joerg         return true;
    404      1.1  joerg       if (writeFuncOrVarName(FD, FrontendBufOS))
    405      1.1  joerg         return true;
    406      1.1  joerg     } else if (auto *VD = dyn_cast<VarDecl>(D)) {
    407      1.1  joerg       if (writeFuncOrVarName(VD, FrontendBufOS))
    408      1.1  joerg         return true;
    409      1.1  joerg     } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
    410  1.1.1.2  joerg       MC->mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,
    411  1.1.1.2  joerg                                /*includeCategoryNamespace=*/true);
    412      1.1  joerg       return false;
    413      1.1  joerg     } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
    414      1.1  joerg       writeObjCClassName(ID, FrontendBufOS);
    415      1.1  joerg     } else {
    416      1.1  joerg       return true;
    417      1.1  joerg     }
    418      1.1  joerg 
    419      1.1  joerg     // Now apply backend mangling.
    420      1.1  joerg     llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
    421      1.1  joerg     return false;
    422      1.1  joerg   }
    423      1.1  joerg 
    424      1.1  joerg   std::string getName(const Decl *D) {
    425      1.1  joerg     std::string Name;
    426      1.1  joerg     {
    427      1.1  joerg       llvm::raw_string_ostream OS(Name);
    428      1.1  joerg       writeName(D, OS);
    429      1.1  joerg     }
    430      1.1  joerg     return Name;
    431      1.1  joerg   }
    432      1.1  joerg 
    433      1.1  joerg   enum ObjCKind {
    434      1.1  joerg     ObjCClass,
    435      1.1  joerg     ObjCMetaclass,
    436      1.1  joerg   };
    437      1.1  joerg 
    438      1.1  joerg   static StringRef getClassSymbolPrefix(ObjCKind Kind,
    439      1.1  joerg                                         const ASTContext &Context) {
    440      1.1  joerg     if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
    441      1.1  joerg       return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
    442      1.1  joerg     return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
    443      1.1  joerg   }
    444      1.1  joerg 
    445      1.1  joerg   std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
    446      1.1  joerg     StringRef ClassName;
    447      1.1  joerg     if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
    448      1.1  joerg       ClassName = OID->getObjCRuntimeNameAsString();
    449      1.1  joerg     else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))
    450      1.1  joerg       ClassName = OID->getObjCRuntimeNameAsString();
    451      1.1  joerg 
    452      1.1  joerg     if (ClassName.empty())
    453      1.1  joerg       return {};
    454      1.1  joerg 
    455      1.1  joerg     auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
    456      1.1  joerg       SmallString<40> Mangled;
    457      1.1  joerg       auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
    458      1.1  joerg       llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
    459  1.1.1.2  joerg       return std::string(Mangled.str());
    460      1.1  joerg     };
    461      1.1  joerg 
    462      1.1  joerg     return {
    463      1.1  joerg         Mangle(ObjCClass, ClassName),
    464      1.1  joerg         Mangle(ObjCMetaclass, ClassName),
    465      1.1  joerg     };
    466      1.1  joerg   }
    467      1.1  joerg 
    468      1.1  joerg   std::vector<std::string> getAllManglings(const Decl *D) {
    469      1.1  joerg     if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
    470      1.1  joerg       return getAllManglings(OCD);
    471      1.1  joerg 
    472      1.1  joerg     if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
    473      1.1  joerg       return {};
    474      1.1  joerg 
    475      1.1  joerg     const NamedDecl *ND = cast<NamedDecl>(D);
    476      1.1  joerg 
    477      1.1  joerg     ASTContext &Ctx = ND->getASTContext();
    478      1.1  joerg     std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
    479      1.1  joerg 
    480      1.1  joerg     std::vector<std::string> Manglings;
    481      1.1  joerg 
    482      1.1  joerg     auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
    483      1.1  joerg       auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
    484      1.1  joerg                                                      /*IsCXXMethod=*/true);
    485      1.1  joerg       auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv();
    486      1.1  joerg       return CC == DefaultCC;
    487      1.1  joerg     };
    488      1.1  joerg 
    489      1.1  joerg     if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
    490      1.1  joerg       Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
    491      1.1  joerg 
    492      1.1  joerg       if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
    493      1.1  joerg         if (!CD->getParent()->isAbstract())
    494      1.1  joerg           Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
    495      1.1  joerg 
    496      1.1  joerg       if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
    497      1.1  joerg         if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
    498      1.1  joerg           if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
    499      1.1  joerg             Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
    500      1.1  joerg     } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
    501      1.1  joerg       Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
    502      1.1  joerg       if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
    503      1.1  joerg         Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
    504      1.1  joerg         if (DD->isVirtual())
    505      1.1  joerg           Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
    506      1.1  joerg       }
    507      1.1  joerg     } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
    508      1.1  joerg       Manglings.emplace_back(getName(ND));
    509      1.1  joerg       if (MD->isVirtual())
    510      1.1  joerg         if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
    511      1.1  joerg           for (const auto &T : *TIV)
    512      1.1  joerg             Manglings.emplace_back(getMangledThunk(MD, T));
    513      1.1  joerg     }
    514      1.1  joerg 
    515      1.1  joerg     return Manglings;
    516      1.1  joerg   }
    517      1.1  joerg 
    518      1.1  joerg private:
    519      1.1  joerg   bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
    520      1.1  joerg     if (MC->shouldMangleDeclName(D)) {
    521  1.1.1.2  joerg       GlobalDecl GD;
    522      1.1  joerg       if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
    523  1.1.1.2  joerg         GD = GlobalDecl(CtorD, Ctor_Complete);
    524      1.1  joerg       else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
    525  1.1.1.2  joerg         GD = GlobalDecl(DtorD, Dtor_Complete);
    526  1.1.1.2  joerg       else if (D->hasAttr<CUDAGlobalAttr>())
    527  1.1.1.2  joerg         GD = GlobalDecl(cast<FunctionDecl>(D));
    528      1.1  joerg       else
    529  1.1.1.2  joerg         GD = GlobalDecl(D);
    530  1.1.1.2  joerg       MC->mangleName(GD, OS);
    531      1.1  joerg       return false;
    532      1.1  joerg     } else {
    533      1.1  joerg       IdentifierInfo *II = D->getIdentifier();
    534      1.1  joerg       if (!II)
    535      1.1  joerg         return true;
    536      1.1  joerg       OS << II->getName();
    537      1.1  joerg       return false;
    538      1.1  joerg     }
    539      1.1  joerg   }
    540      1.1  joerg 
    541      1.1  joerg   void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
    542      1.1  joerg     OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
    543      1.1  joerg     OS << D->getObjCRuntimeNameAsString();
    544      1.1  joerg   }
    545      1.1  joerg 
    546      1.1  joerg   std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
    547      1.1  joerg     std::string FrontendBuf;
    548      1.1  joerg     llvm::raw_string_ostream FOS(FrontendBuf);
    549      1.1  joerg 
    550  1.1.1.2  joerg     GlobalDecl GD;
    551      1.1  joerg     if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
    552  1.1.1.2  joerg       GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));
    553      1.1  joerg     else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
    554  1.1.1.2  joerg       GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));
    555  1.1.1.2  joerg     MC->mangleName(GD, FOS);
    556      1.1  joerg 
    557      1.1  joerg     std::string BackendBuf;
    558      1.1  joerg     llvm::raw_string_ostream BOS(BackendBuf);
    559      1.1  joerg 
    560      1.1  joerg     llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
    561      1.1  joerg 
    562      1.1  joerg     return BOS.str();
    563      1.1  joerg   }
    564      1.1  joerg 
    565      1.1  joerg   std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
    566      1.1  joerg     std::string FrontendBuf;
    567      1.1  joerg     llvm::raw_string_ostream FOS(FrontendBuf);
    568      1.1  joerg 
    569      1.1  joerg     MC->mangleThunk(MD, T, FOS);
    570      1.1  joerg 
    571      1.1  joerg     std::string BackendBuf;
    572      1.1  joerg     llvm::raw_string_ostream BOS(BackendBuf);
    573      1.1  joerg 
    574      1.1  joerg     llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
    575      1.1  joerg 
    576      1.1  joerg     return BOS.str();
    577      1.1  joerg   }
    578      1.1  joerg };
    579      1.1  joerg 
    580      1.1  joerg ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx)
    581      1.1  joerg     : Impl(std::make_unique<Implementation>(Ctx)) {}
    582      1.1  joerg 
    583      1.1  joerg ASTNameGenerator::~ASTNameGenerator() {}
    584      1.1  joerg 
    585      1.1  joerg bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
    586      1.1  joerg   return Impl->writeName(D, OS);
    587      1.1  joerg }
    588      1.1  joerg 
    589      1.1  joerg std::string ASTNameGenerator::getName(const Decl *D) {
    590      1.1  joerg   return Impl->getName(D);
    591      1.1  joerg }
    592      1.1  joerg 
    593      1.1  joerg std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) {
    594      1.1  joerg   return Impl->getAllManglings(D);
    595      1.1  joerg }
    596