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"
285ffd83dbSDimitry Andric #include "llvm/Support/Format.h"
290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric using namespace clang;
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
340b57cec5SDimitry Andric // much to be desired. Come up with a better mangling scheme.
350b57cec5SDimitry Andric
mangleFunctionBlock(MangleContext & Context,StringRef Outer,const BlockDecl * BD,raw_ostream & Out)360b57cec5SDimitry Andric static void mangleFunctionBlock(MangleContext &Context,
370b57cec5SDimitry Andric StringRef Outer,
380b57cec5SDimitry Andric const BlockDecl *BD,
390b57cec5SDimitry Andric raw_ostream &Out) {
400b57cec5SDimitry Andric unsigned discriminator = Context.getBlockId(BD, true);
410b57cec5SDimitry Andric if (discriminator == 0)
420b57cec5SDimitry Andric Out << "__" << Outer << "_block_invoke";
430b57cec5SDimitry Andric else
440b57cec5SDimitry Andric Out << "__" << Outer << "_block_invoke_" << discriminator+1;
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric
anchor()470b57cec5SDimitry Andric void MangleContext::anchor() { }
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric enum CCMangling {
500b57cec5SDimitry Andric CCM_Other,
510b57cec5SDimitry Andric CCM_Fast,
520b57cec5SDimitry Andric CCM_RegCall,
530b57cec5SDimitry Andric CCM_Vector,
545ffd83dbSDimitry Andric CCM_Std,
555ffd83dbSDimitry Andric CCM_WasmMainArgcArgv
560b57cec5SDimitry Andric };
570b57cec5SDimitry Andric
isExternC(const NamedDecl * ND)580b57cec5SDimitry Andric static bool isExternC(const NamedDecl *ND) {
590b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
600b57cec5SDimitry Andric return FD->isExternC();
615ffd83dbSDimitry Andric if (const VarDecl *VD = dyn_cast<VarDecl>(ND))
625ffd83dbSDimitry Andric return VD->isExternC();
635ffd83dbSDimitry Andric return false;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric
getCallingConvMangling(const ASTContext & Context,const NamedDecl * ND)660b57cec5SDimitry Andric static CCMangling getCallingConvMangling(const ASTContext &Context,
670b57cec5SDimitry Andric const NamedDecl *ND) {
680b57cec5SDimitry Andric const TargetInfo &TI = Context.getTargetInfo();
690b57cec5SDimitry Andric const llvm::Triple &Triple = TI.getTriple();
705ffd83dbSDimitry Andric
715ffd83dbSDimitry Andric // On wasm, the argc/argv form of "main" is renamed so that the startup code
725ffd83dbSDimitry Andric // can call it with the correct function signature.
7381ad6265SDimitry Andric if (Triple.isWasm())
745ffd83dbSDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
7581ad6265SDimitry Andric if (FD->isMain() && FD->getNumParams() == 2)
765ffd83dbSDimitry Andric return CCM_WasmMainArgcArgv;
775ffd83dbSDimitry Andric
78480093f4SDimitry Andric if (!Triple.isOSWindows() || !Triple.isX86())
790b57cec5SDimitry Andric return CCM_Other;
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric if (Context.getLangOpts().CPlusPlus && !isExternC(ND) &&
820b57cec5SDimitry Andric TI.getCXXABI() == TargetCXXABI::Microsoft)
830b57cec5SDimitry Andric return CCM_Other;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
860b57cec5SDimitry Andric if (!FD)
870b57cec5SDimitry Andric return CCM_Other;
880b57cec5SDimitry Andric QualType T = FD->getType();
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric const FunctionType *FT = T->castAs<FunctionType>();
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric CallingConv CC = FT->getCallConv();
930b57cec5SDimitry Andric switch (CC) {
940b57cec5SDimitry Andric default:
950b57cec5SDimitry Andric return CCM_Other;
960b57cec5SDimitry Andric case CC_X86FastCall:
970b57cec5SDimitry Andric return CCM_Fast;
980b57cec5SDimitry Andric case CC_X86StdCall:
990b57cec5SDimitry Andric return CCM_Std;
1000b57cec5SDimitry Andric case CC_X86VectorCall:
1010b57cec5SDimitry Andric return CCM_Vector;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric
shouldMangleDeclName(const NamedDecl * D)1050b57cec5SDimitry Andric bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
1060b57cec5SDimitry Andric const ASTContext &ASTContext = getASTContext();
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric CCMangling CC = getCallingConvMangling(ASTContext, D);
1090b57cec5SDimitry Andric if (CC != CCM_Other)
1100b57cec5SDimitry Andric return true;
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric // If the declaration has an owning module for linkage purposes that needs to
1130b57cec5SDimitry Andric // be mangled, we must mangle its name.
1140b57cec5SDimitry Andric if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage())
1150b57cec5SDimitry Andric return true;
1160b57cec5SDimitry Andric
117fe6060f1SDimitry Andric // C functions with internal linkage have to be mangled with option
118fe6060f1SDimitry Andric // -funique-internal-linkage-names.
119fe6060f1SDimitry Andric if (!getASTContext().getLangOpts().CPlusPlus &&
120fe6060f1SDimitry Andric isUniqueInternalLinkageDecl(D))
121fe6060f1SDimitry Andric return true;
122fe6060f1SDimitry Andric
1230b57cec5SDimitry Andric // In C, functions with no attributes never need to be mangled. Fastpath them.
1240b57cec5SDimitry Andric if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
1250b57cec5SDimitry Andric return false;
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric // Any decl can be declared with __asm("foo") on it, and this takes precedence
1280b57cec5SDimitry Andric // over all other naming in the .o file.
1290b57cec5SDimitry Andric if (D->hasAttr<AsmLabelAttr>())
1300b57cec5SDimitry Andric return true;
1310b57cec5SDimitry Andric
1325ffd83dbSDimitry Andric // Declarations that don't have identifier names always need to be mangled.
1335ffd83dbSDimitry Andric if (isa<MSGuidDecl>(D))
1345ffd83dbSDimitry Andric return true;
1355ffd83dbSDimitry Andric
1360b57cec5SDimitry Andric return shouldMangleCXXName(D);
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
mangleName(GlobalDecl GD,raw_ostream & Out)1395ffd83dbSDimitry Andric void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
140fe6060f1SDimitry Andric const ASTContext &ASTContext = getASTContext();
1415ffd83dbSDimitry Andric const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
142fe6060f1SDimitry Andric
1430b57cec5SDimitry Andric // Any decl can be declared with __asm("foo") on it, and this takes precedence
1440b57cec5SDimitry Andric // over all other naming in the .o file.
1450b57cec5SDimitry Andric if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
1460b57cec5SDimitry Andric // If we have an asm name, then we use it as the mangling.
1470b57cec5SDimitry Andric
148a7dea167SDimitry Andric // If the label isn't literal, or if this is an alias for an LLVM intrinsic,
149a7dea167SDimitry Andric // do not add a "\01" prefix.
1505f757f3fSDimitry Andric if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
151a7dea167SDimitry Andric Out << ALA->getLabel();
152a7dea167SDimitry Andric return;
153a7dea167SDimitry Andric }
154a7dea167SDimitry Andric
1550b57cec5SDimitry Andric // Adding the prefix can cause problems when one file has a "foo" and
1560b57cec5SDimitry Andric // another has a "\01foo". That is known to happen on ELF with the
1570b57cec5SDimitry Andric // tricks normally used for producing aliases (PR9177). Fortunately the
1580b57cec5SDimitry Andric // llvm mangler on ELF is a nop, so we can just avoid adding the \01
159a7dea167SDimitry Andric // marker.
160fe6060f1SDimitry Andric StringRef UserLabelPrefix =
161fe6060f1SDimitry Andric getASTContext().getTargetInfo().getUserLabelPrefix();
162fe6060f1SDimitry Andric #ifndef NDEBUG
1630b57cec5SDimitry Andric char GlobalPrefix =
164fe6060f1SDimitry Andric llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString())
165fe6060f1SDimitry Andric .getGlobalPrefix();
166fe6060f1SDimitry Andric assert((UserLabelPrefix.empty() && !GlobalPrefix) ||
167fe6060f1SDimitry Andric (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix));
168fe6060f1SDimitry Andric #endif
169fe6060f1SDimitry Andric if (!UserLabelPrefix.empty())
1700b57cec5SDimitry Andric Out << '\01'; // LLVM IR Marker for __asm("foo")
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric Out << ALA->getLabel();
1730b57cec5SDimitry Andric return;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric
1765ffd83dbSDimitry Andric if (auto *GD = dyn_cast<MSGuidDecl>(D))
1775ffd83dbSDimitry Andric return mangleMSGuidDecl(GD, Out);
1785ffd83dbSDimitry Andric
1790b57cec5SDimitry Andric CCMangling CC = getCallingConvMangling(ASTContext, D);
1805ffd83dbSDimitry Andric
1815ffd83dbSDimitry Andric if (CC == CCM_WasmMainArgcArgv) {
1825ffd83dbSDimitry Andric Out << "__main_argc_argv";
1835ffd83dbSDimitry Andric return;
1845ffd83dbSDimitry Andric }
1855ffd83dbSDimitry Andric
1860b57cec5SDimitry Andric bool MCXX = shouldMangleCXXName(D);
1870b57cec5SDimitry Andric const TargetInfo &TI = Context.getTargetInfo();
1880b57cec5SDimitry Andric if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
1890b57cec5SDimitry Andric if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
190e8d8bef9SDimitry Andric mangleObjCMethodNameAsSourceName(OMD, Out);
1910b57cec5SDimitry Andric else
1925ffd83dbSDimitry Andric mangleCXXName(GD, Out);
1930b57cec5SDimitry Andric return;
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric Out << '\01';
1970b57cec5SDimitry Andric if (CC == CCM_Std)
1980b57cec5SDimitry Andric Out << '_';
1990b57cec5SDimitry Andric else if (CC == CCM_Fast)
2000b57cec5SDimitry Andric Out << '@';
2015f757f3fSDimitry Andric else if (CC == CCM_RegCall) {
2025f757f3fSDimitry Andric if (getASTContext().getLangOpts().RegCall4)
2035f757f3fSDimitry Andric Out << "__regcall4__";
2045f757f3fSDimitry Andric else
2050b57cec5SDimitry Andric Out << "__regcall3__";
2065f757f3fSDimitry Andric }
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric if (!MCXX)
2090b57cec5SDimitry Andric Out << D->getIdentifier()->getName();
2100b57cec5SDimitry Andric else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
211e8d8bef9SDimitry Andric mangleObjCMethodNameAsSourceName(OMD, Out);
2120b57cec5SDimitry Andric else
2135ffd83dbSDimitry Andric mangleCXXName(GD, Out);
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andric const FunctionDecl *FD = cast<FunctionDecl>(D);
2160b57cec5SDimitry Andric const FunctionType *FT = FD->getType()->castAs<FunctionType>();
2170b57cec5SDimitry Andric const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);
2180b57cec5SDimitry Andric if (CC == CCM_Vector)
2190b57cec5SDimitry Andric Out << '@';
2200b57cec5SDimitry Andric Out << '@';
2210b57cec5SDimitry Andric if (!Proto) {
2220b57cec5SDimitry Andric Out << '0';
2230b57cec5SDimitry Andric return;
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric assert(!Proto->isVariadic());
2260b57cec5SDimitry Andric unsigned ArgWords = 0;
2270b57cec5SDimitry Andric if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
2285f757f3fSDimitry Andric if (MD->isImplicitObjectMemberFunction())
2290b57cec5SDimitry Andric ++ArgWords;
230bdd1243dSDimitry Andric uint64_t DefaultPtrWidth = TI.getPointerWidth(LangAS::Default);
23104eeddc0SDimitry Andric for (const auto &AT : Proto->param_types()) {
23204eeddc0SDimitry Andric // If an argument type is incomplete there is no way to get its size to
23304eeddc0SDimitry Andric // correctly encode into the mangling scheme.
23404eeddc0SDimitry Andric // Follow GCCs behaviour by simply breaking out of the loop.
23504eeddc0SDimitry Andric if (AT->isIncompleteType())
23604eeddc0SDimitry Andric break;
2370b57cec5SDimitry Andric // Size should be aligned to pointer size.
238bdd1243dSDimitry Andric ArgWords += llvm::alignTo(ASTContext.getTypeSize(AT), DefaultPtrWidth) /
239bdd1243dSDimitry Andric DefaultPtrWidth;
24004eeddc0SDimitry Andric }
241bdd1243dSDimitry Andric Out << ((DefaultPtrWidth / 8) * ArgWords);
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric
mangleMSGuidDecl(const MSGuidDecl * GD,raw_ostream & Out)2445ffd83dbSDimitry Andric void MangleContext::mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream &Out) {
2455ffd83dbSDimitry Andric // For now, follow the MSVC naming convention for GUID objects on all
2465ffd83dbSDimitry Andric // targets.
2475ffd83dbSDimitry Andric MSGuidDecl::Parts P = GD->getParts();
2485ffd83dbSDimitry Andric Out << llvm::format("_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_",
2495ffd83dbSDimitry Andric P.Part1, P.Part2, P.Part3);
2505ffd83dbSDimitry Andric unsigned I = 0;
2515ffd83dbSDimitry Andric for (uint8_t C : P.Part4And5) {
2525ffd83dbSDimitry Andric Out << llvm::format("%02" PRIx8, C);
2535ffd83dbSDimitry Andric if (++I == 2)
2545ffd83dbSDimitry Andric Out << "_";
2555ffd83dbSDimitry Andric }
2565ffd83dbSDimitry Andric }
2575ffd83dbSDimitry Andric
mangleGlobalBlock(const BlockDecl * BD,const NamedDecl * ID,raw_ostream & Out)2580b57cec5SDimitry Andric void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
2590b57cec5SDimitry Andric const NamedDecl *ID,
2600b57cec5SDimitry Andric raw_ostream &Out) {
2610b57cec5SDimitry Andric unsigned discriminator = getBlockId(BD, false);
2620b57cec5SDimitry Andric if (ID) {
2630b57cec5SDimitry Andric if (shouldMangleDeclName(ID))
2640b57cec5SDimitry Andric mangleName(ID, Out);
2650b57cec5SDimitry Andric else {
2660b57cec5SDimitry Andric Out << ID->getIdentifier()->getName();
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric if (discriminator == 0)
2700b57cec5SDimitry Andric Out << "_block_invoke";
2710b57cec5SDimitry Andric else
2720b57cec5SDimitry Andric Out << "_block_invoke_" << discriminator+1;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
mangleCtorBlock(const CXXConstructorDecl * CD,CXXCtorType CT,const BlockDecl * BD,raw_ostream & ResStream)2750b57cec5SDimitry Andric void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
2760b57cec5SDimitry Andric CXXCtorType CT, const BlockDecl *BD,
2770b57cec5SDimitry Andric raw_ostream &ResStream) {
2780b57cec5SDimitry Andric SmallString<64> Buffer;
2790b57cec5SDimitry Andric llvm::raw_svector_ostream Out(Buffer);
2805ffd83dbSDimitry Andric mangleName(GlobalDecl(CD, CT), Out);
2810b57cec5SDimitry Andric mangleFunctionBlock(*this, Buffer, BD, ResStream);
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric
mangleDtorBlock(const CXXDestructorDecl * DD,CXXDtorType DT,const BlockDecl * BD,raw_ostream & ResStream)2840b57cec5SDimitry Andric void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
2850b57cec5SDimitry Andric CXXDtorType DT, const BlockDecl *BD,
2860b57cec5SDimitry Andric raw_ostream &ResStream) {
2870b57cec5SDimitry Andric SmallString<64> Buffer;
2880b57cec5SDimitry Andric llvm::raw_svector_ostream Out(Buffer);
2895ffd83dbSDimitry Andric mangleName(GlobalDecl(DD, DT), Out);
2900b57cec5SDimitry Andric mangleFunctionBlock(*this, Buffer, BD, ResStream);
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
mangleBlock(const DeclContext * DC,const BlockDecl * BD,raw_ostream & Out)2930b57cec5SDimitry Andric void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
2940b57cec5SDimitry Andric raw_ostream &Out) {
2950b57cec5SDimitry Andric assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric SmallString<64> Buffer;
2980b57cec5SDimitry Andric llvm::raw_svector_ostream Stream(Buffer);
2990b57cec5SDimitry Andric if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
300e8d8bef9SDimitry Andric mangleObjCMethodNameAsSourceName(Method, Stream);
3010b57cec5SDimitry Andric } else {
3020b57cec5SDimitry Andric assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
3030b57cec5SDimitry Andric "expected a NamedDecl or BlockDecl");
304*0fca6ea1SDimitry Andric for (; isa_and_nonnull<BlockDecl>(DC); DC = DC->getParent())
3050b57cec5SDimitry Andric (void)getBlockId(cast<BlockDecl>(DC), true);
3060b57cec5SDimitry Andric assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
3070b57cec5SDimitry Andric "expected a TranslationUnitDecl or a NamedDecl");
3080b57cec5SDimitry Andric if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
3090b57cec5SDimitry Andric mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
3100b57cec5SDimitry Andric else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
3110b57cec5SDimitry Andric mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
3120b57cec5SDimitry Andric else if (auto ND = dyn_cast<NamedDecl>(DC)) {
3130b57cec5SDimitry Andric if (!shouldMangleDeclName(ND) && ND->getIdentifier())
3140b57cec5SDimitry Andric Stream << ND->getIdentifier()->getName();
3150b57cec5SDimitry Andric else {
3160b57cec5SDimitry Andric // FIXME: We were doing a mangleUnqualifiedName() before, but that's
3170b57cec5SDimitry Andric // a private member of a class that will soon itself be private to the
3180b57cec5SDimitry Andric // Itanium C++ ABI object. What should we do now? Right now, I'm just
3190b57cec5SDimitry Andric // calling the mangleName() method on the MangleContext; is there a
3200b57cec5SDimitry Andric // better way?
3210b57cec5SDimitry Andric mangleName(ND, Stream);
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric mangleFunctionBlock(*this, Buffer, BD, Out);
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric
mangleObjCMethodName(const ObjCMethodDecl * MD,raw_ostream & OS,bool includePrefixByte,bool includeCategoryNamespace)328e8d8bef9SDimitry Andric void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
329e8d8bef9SDimitry Andric raw_ostream &OS,
330e8d8bef9SDimitry Andric bool includePrefixByte,
331e8d8bef9SDimitry Andric bool includeCategoryNamespace) {
332e8d8bef9SDimitry Andric if (getASTContext().getLangOpts().ObjCRuntime.isGNUFamily()) {
333e8d8bef9SDimitry Andric // This is the mangling we've always used on the GNU runtimes, but it
334e8d8bef9SDimitry Andric // has obvious collisions in the face of underscores within class
335e8d8bef9SDimitry Andric // names, category names, and selectors; maybe we should improve it.
336e8d8bef9SDimitry Andric
337e8d8bef9SDimitry Andric OS << (MD->isClassMethod() ? "_c_" : "_i_")
338e8d8bef9SDimitry Andric << MD->getClassInterface()->getName() << '_';
339e8d8bef9SDimitry Andric
340e8d8bef9SDimitry Andric if (includeCategoryNamespace) {
341e8d8bef9SDimitry Andric if (auto category = MD->getCategory())
342e8d8bef9SDimitry Andric OS << category->getName();
343e8d8bef9SDimitry Andric }
344e8d8bef9SDimitry Andric OS << '_';
345e8d8bef9SDimitry Andric
346e8d8bef9SDimitry Andric auto selector = MD->getSelector();
347e8d8bef9SDimitry Andric for (unsigned slotIndex = 0,
348e8d8bef9SDimitry Andric numArgs = selector.getNumArgs(),
349e8d8bef9SDimitry Andric slotEnd = std::max(numArgs, 1U);
350e8d8bef9SDimitry Andric slotIndex != slotEnd; ++slotIndex) {
351e8d8bef9SDimitry Andric if (auto name = selector.getIdentifierInfoForSlot(slotIndex))
352e8d8bef9SDimitry Andric OS << name->getName();
353e8d8bef9SDimitry Andric
354e8d8bef9SDimitry Andric // Replace all the positions that would've been ':' with '_'.
355e8d8bef9SDimitry Andric // That's after each slot except that a unary selector doesn't
356e8d8bef9SDimitry Andric // end in ':'.
357e8d8bef9SDimitry Andric if (numArgs)
358e8d8bef9SDimitry Andric OS << '_';
359e8d8bef9SDimitry Andric }
360e8d8bef9SDimitry Andric
361e8d8bef9SDimitry Andric return;
362e8d8bef9SDimitry Andric }
363e8d8bef9SDimitry Andric
364e8d8bef9SDimitry Andric // \01+[ContainerName(CategoryName) SelectorName]
365e8d8bef9SDimitry Andric if (includePrefixByte) {
366e8d8bef9SDimitry Andric OS << '\01';
367e8d8bef9SDimitry Andric }
3680b57cec5SDimitry Andric OS << (MD->isInstanceMethod() ? '-' : '+') << '[';
369e8d8bef9SDimitry Andric if (const auto *CID = MD->getCategory()) {
3700b57cec5SDimitry Andric OS << CID->getClassInterface()->getName();
371e8d8bef9SDimitry Andric if (includeCategoryNamespace) {
3720b57cec5SDimitry Andric OS << '(' << *CID << ')';
373e8d8bef9SDimitry Andric }
374e8d8bef9SDimitry Andric } else if (const auto *CD =
375e8d8bef9SDimitry Andric dyn_cast<ObjCContainerDecl>(MD->getDeclContext())) {
3760b57cec5SDimitry Andric OS << CD->getName();
377e8d8bef9SDimitry Andric } else {
378e8d8bef9SDimitry Andric llvm_unreachable("Unexpected ObjC method decl context");
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric OS << ' ';
3810b57cec5SDimitry Andric MD->getSelector().print(OS);
3820b57cec5SDimitry Andric OS << ']';
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric
mangleObjCMethodNameAsSourceName(const ObjCMethodDecl * MD,raw_ostream & Out)385e8d8bef9SDimitry Andric void MangleContext::mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,
3860b57cec5SDimitry Andric raw_ostream &Out) {
3870b57cec5SDimitry Andric SmallString<64> Name;
3880b57cec5SDimitry Andric llvm::raw_svector_ostream OS(Name);
3890b57cec5SDimitry Andric
390e8d8bef9SDimitry Andric mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,
391e8d8bef9SDimitry Andric /*includeCategoryNamespace=*/true);
3920b57cec5SDimitry Andric Out << OS.str().size() << OS.str();
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric class ASTNameGenerator::Implementation {
3960b57cec5SDimitry Andric std::unique_ptr<MangleContext> MC;
3970b57cec5SDimitry Andric llvm::DataLayout DL;
3980b57cec5SDimitry Andric
3990b57cec5SDimitry Andric public:
Implementation(ASTContext & Ctx)4000b57cec5SDimitry Andric explicit Implementation(ASTContext &Ctx)
401fe6060f1SDimitry Andric : MC(Ctx.createMangleContext()),
402fe6060f1SDimitry Andric DL(Ctx.getTargetInfo().getDataLayoutString()) {}
4030b57cec5SDimitry Andric
writeName(const Decl * D,raw_ostream & OS)4040b57cec5SDimitry Andric bool writeName(const Decl *D, raw_ostream &OS) {
4050b57cec5SDimitry Andric // First apply frontend mangling.
4060b57cec5SDimitry Andric SmallString<128> FrontendBuf;
4070b57cec5SDimitry Andric llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
4080b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(D)) {
4090b57cec5SDimitry Andric if (FD->isDependentContext())
4100b57cec5SDimitry Andric return true;
4110b57cec5SDimitry Andric if (writeFuncOrVarName(FD, FrontendBufOS))
4120b57cec5SDimitry Andric return true;
4130b57cec5SDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) {
4140b57cec5SDimitry Andric if (writeFuncOrVarName(VD, FrontendBufOS))
4150b57cec5SDimitry Andric return true;
4160b57cec5SDimitry Andric } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
417e8d8bef9SDimitry Andric MC->mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,
418e8d8bef9SDimitry Andric /*includeCategoryNamespace=*/true);
4190b57cec5SDimitry Andric return false;
4200b57cec5SDimitry Andric } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
4210b57cec5SDimitry Andric writeObjCClassName(ID, FrontendBufOS);
4220b57cec5SDimitry Andric } else {
4230b57cec5SDimitry Andric return true;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric // Now apply backend mangling.
4270b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
4280b57cec5SDimitry Andric return false;
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric
getName(const Decl * D)4310b57cec5SDimitry Andric std::string getName(const Decl *D) {
4320b57cec5SDimitry Andric std::string Name;
4330b57cec5SDimitry Andric {
4340b57cec5SDimitry Andric llvm::raw_string_ostream OS(Name);
4350b57cec5SDimitry Andric writeName(D, OS);
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric return Name;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric
4400b57cec5SDimitry Andric enum ObjCKind {
4410b57cec5SDimitry Andric ObjCClass,
4420b57cec5SDimitry Andric ObjCMetaclass,
4430b57cec5SDimitry Andric };
4440b57cec5SDimitry Andric
getClassSymbolPrefix(ObjCKind Kind,const ASTContext & Context)4450b57cec5SDimitry Andric static StringRef getClassSymbolPrefix(ObjCKind Kind,
4460b57cec5SDimitry Andric const ASTContext &Context) {
4470b57cec5SDimitry Andric if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
4480b57cec5SDimitry Andric return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
4490b57cec5SDimitry Andric return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric
getAllManglings(const ObjCContainerDecl * OCD)4520b57cec5SDimitry Andric std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
4530b57cec5SDimitry Andric StringRef ClassName;
4540b57cec5SDimitry Andric if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
4550b57cec5SDimitry Andric ClassName = OID->getObjCRuntimeNameAsString();
4560b57cec5SDimitry Andric else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))
4570b57cec5SDimitry Andric ClassName = OID->getObjCRuntimeNameAsString();
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andric if (ClassName.empty())
4600b57cec5SDimitry Andric return {};
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andric auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
4630b57cec5SDimitry Andric SmallString<40> Mangled;
4640b57cec5SDimitry Andric auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
4650b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
4667a6dacacSDimitry Andric return std::string(Mangled);
4670b57cec5SDimitry Andric };
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andric return {
4700b57cec5SDimitry Andric Mangle(ObjCClass, ClassName),
4710b57cec5SDimitry Andric Mangle(ObjCMetaclass, ClassName),
4720b57cec5SDimitry Andric };
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric
getAllManglings(const Decl * D)4750b57cec5SDimitry Andric std::vector<std::string> getAllManglings(const Decl *D) {
4760b57cec5SDimitry Andric if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
4770b57cec5SDimitry Andric return getAllManglings(OCD);
4780b57cec5SDimitry Andric
4790b57cec5SDimitry Andric if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
4800b57cec5SDimitry Andric return {};
4810b57cec5SDimitry Andric
4820b57cec5SDimitry Andric const NamedDecl *ND = cast<NamedDecl>(D);
4830b57cec5SDimitry Andric
4840b57cec5SDimitry Andric ASTContext &Ctx = ND->getASTContext();
4850b57cec5SDimitry Andric std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric std::vector<std::string> Manglings;
4880b57cec5SDimitry Andric
4890b57cec5SDimitry Andric auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
4900b57cec5SDimitry Andric auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
4910b57cec5SDimitry Andric /*IsCXXMethod=*/true);
492a7dea167SDimitry Andric auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv();
4930b57cec5SDimitry Andric return CC == DefaultCC;
4940b57cec5SDimitry Andric };
4950b57cec5SDimitry Andric
4960b57cec5SDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
4970b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
5000b57cec5SDimitry Andric if (!CD->getParent()->isAbstract())
5010b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
5040b57cec5SDimitry Andric if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
5050b57cec5SDimitry Andric if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
5060b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
5070b57cec5SDimitry Andric } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
5080b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
5090b57cec5SDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
5100b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
5110b57cec5SDimitry Andric if (DD->isVirtual())
5120b57cec5SDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
5150b57cec5SDimitry Andric Manglings.emplace_back(getName(ND));
516*0fca6ea1SDimitry Andric if (MD->isVirtual()) {
517*0fca6ea1SDimitry Andric if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) {
518*0fca6ea1SDimitry Andric for (const auto &T : *TIV) {
519*0fca6ea1SDimitry Andric std::string ThunkName;
520*0fca6ea1SDimitry Andric std::string ContextualizedName =
521*0fca6ea1SDimitry Andric getMangledThunk(MD, T, /* ElideOverrideInfo */ false);
522*0fca6ea1SDimitry Andric if (Ctx.useAbbreviatedThunkName(MD, ContextualizedName))
523*0fca6ea1SDimitry Andric ThunkName = getMangledThunk(MD, T, /* ElideOverrideInfo */ true);
524*0fca6ea1SDimitry Andric else
525*0fca6ea1SDimitry Andric ThunkName = ContextualizedName;
526*0fca6ea1SDimitry Andric Manglings.emplace_back(ThunkName);
527*0fca6ea1SDimitry Andric }
528*0fca6ea1SDimitry Andric }
529*0fca6ea1SDimitry Andric }
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andric return Manglings;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric
5350b57cec5SDimitry Andric private:
writeFuncOrVarName(const NamedDecl * D,raw_ostream & OS)5360b57cec5SDimitry Andric bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
5370b57cec5SDimitry Andric if (MC->shouldMangleDeclName(D)) {
5385ffd83dbSDimitry Andric GlobalDecl GD;
5390b57cec5SDimitry Andric if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
5405ffd83dbSDimitry Andric GD = GlobalDecl(CtorD, Ctor_Complete);
5410b57cec5SDimitry Andric else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
5425ffd83dbSDimitry Andric GD = GlobalDecl(DtorD, Dtor_Complete);
5435ffd83dbSDimitry Andric else if (D->hasAttr<CUDAGlobalAttr>())
5445ffd83dbSDimitry Andric GD = GlobalDecl(cast<FunctionDecl>(D));
5450b57cec5SDimitry Andric else
5465ffd83dbSDimitry Andric GD = GlobalDecl(D);
5475ffd83dbSDimitry Andric MC->mangleName(GD, OS);
5480b57cec5SDimitry Andric return false;
5490b57cec5SDimitry Andric } else {
5500b57cec5SDimitry Andric IdentifierInfo *II = D->getIdentifier();
5510b57cec5SDimitry Andric if (!II)
5520b57cec5SDimitry Andric return true;
5530b57cec5SDimitry Andric OS << II->getName();
5540b57cec5SDimitry Andric return false;
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric
writeObjCClassName(const ObjCInterfaceDecl * D,raw_ostream & OS)5580b57cec5SDimitry Andric void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
5590b57cec5SDimitry Andric OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
5600b57cec5SDimitry Andric OS << D->getObjCRuntimeNameAsString();
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric
getMangledStructor(const NamedDecl * ND,unsigned StructorType)5630b57cec5SDimitry Andric std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
5640b57cec5SDimitry Andric std::string FrontendBuf;
5650b57cec5SDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf);
5660b57cec5SDimitry Andric
5675ffd83dbSDimitry Andric GlobalDecl GD;
5680b57cec5SDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
5695ffd83dbSDimitry Andric GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));
5700b57cec5SDimitry Andric else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
5715ffd83dbSDimitry Andric GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));
5725ffd83dbSDimitry Andric MC->mangleName(GD, FOS);
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric std::string BackendBuf;
5750b57cec5SDimitry Andric llvm::raw_string_ostream BOS(BackendBuf);
5760b57cec5SDimitry Andric
5770b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andric return BOS.str();
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric
getMangledThunk(const CXXMethodDecl * MD,const ThunkInfo & T,bool ElideOverrideInfo)582*0fca6ea1SDimitry Andric std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T,
583*0fca6ea1SDimitry Andric bool ElideOverrideInfo) {
5840b57cec5SDimitry Andric std::string FrontendBuf;
5850b57cec5SDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf);
5860b57cec5SDimitry Andric
587*0fca6ea1SDimitry Andric MC->mangleThunk(MD, T, ElideOverrideInfo, FOS);
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andric std::string BackendBuf;
5900b57cec5SDimitry Andric llvm::raw_string_ostream BOS(BackendBuf);
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
5930b57cec5SDimitry Andric
5940b57cec5SDimitry Andric return BOS.str();
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric };
5970b57cec5SDimitry Andric
ASTNameGenerator(ASTContext & Ctx)5980b57cec5SDimitry Andric ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx)
599a7dea167SDimitry Andric : Impl(std::make_unique<Implementation>(Ctx)) {}
6000b57cec5SDimitry Andric
~ASTNameGenerator()6010b57cec5SDimitry Andric ASTNameGenerator::~ASTNameGenerator() {}
6020b57cec5SDimitry Andric
writeName(const Decl * D,raw_ostream & OS)6030b57cec5SDimitry Andric bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
6040b57cec5SDimitry Andric return Impl->writeName(D, OS);
6050b57cec5SDimitry Andric }
6060b57cec5SDimitry Andric
getName(const Decl * D)6070b57cec5SDimitry Andric std::string ASTNameGenerator::getName(const Decl *D) {
6080b57cec5SDimitry Andric return Impl->getName(D);
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric
getAllManglings(const Decl * D)6110b57cec5SDimitry Andric std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) {
6120b57cec5SDimitry Andric return Impl->getAllManglings(D);
6130b57cec5SDimitry Andric }
614