Clang Project

clang_source_code/lib/AST/Mangle.cpp
1//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implements generic name mangling support for blocks and Objective-C.
10//
11//===----------------------------------------------------------------------===//
12#include "clang/AST/Attr.h"
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclCXX.h"
16#include "clang/AST/DeclObjC.h"
17#include "clang/AST/DeclTemplate.h"
18#include "clang/AST/ExprCXX.h"
19#include "clang/AST/Mangle.h"
20#include "clang/Basic/ABI.h"
21#include "clang/Basic/SourceManager.h"
22#include "clang/Basic/TargetInfo.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/raw_ostream.h"
26
27using namespace clang;
28
29// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
30// much to be desired. Come up with a better mangling scheme.
31
32static void mangleFunctionBlock(MangleContext &Context,
33                                StringRef Outer,
34                                const BlockDecl *BD,
35                                raw_ostream &Out) {
36  unsigned discriminator = Context.getBlockId(BDtrue);
37  if (discriminator == 0)
38    Out << "__" << Outer << "_block_invoke";
39  else
40    Out << "__" << Outer << "_block_invoke_" << discriminator+1;
41}
42
43void MangleContext::anchor() { }
44
45enum CCMangling {
46  CCM_Other,
47  CCM_Fast,
48  CCM_RegCall,
49  CCM_Vector,
50  CCM_Std
51};
52
53static bool isExternC(const NamedDecl *ND) {
54  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
55    return FD->isExternC();
56  return cast<VarDecl>(ND)->isExternC();
57}
58
59static CCMangling getCallingConvMangling(const ASTContext &Context,
60                                         const NamedDecl *ND) {
61  const TargetInfo &TI = Context.getTargetInfo();
62  const llvm::Triple &Triple = TI.getTriple();
63  if (!Triple.isOSWindows() ||
64      !(Triple.getArch() == llvm::Triple::x86 ||
65        Triple.getArch() == llvm::Triple::x86_64))
66    return CCM_Other;
67
68  if (Context.getLangOpts().CPlusPlus && !isExternC(ND) &&
69      TI.getCXXABI() == TargetCXXABI::Microsoft)
70    return CCM_Other;
71
72  const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
73  if (!FD)
74    return CCM_Other;
75  QualType T = FD->getType();
76
77  const FunctionType *FT = T->castAs<FunctionType>();
78
79  CallingConv CC = FT->getCallConv();
80  switch (CC) {
81  default:
82    return CCM_Other;
83  case CC_X86FastCall:
84    return CCM_Fast;
85  case CC_X86StdCall:
86    return CCM_Std;
87  case CC_X86VectorCall:
88    return CCM_Vector;
89  }
90}
91
92bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
93  const ASTContext &ASTContext = getASTContext();
94
95  CCMangling CC = getCallingConvMangling(ASTContextD);
96  if (CC != CCM_Other)
97    return true;
98
99  // If the declaration has an owning module for linkage purposes that needs to
100  // be mangled, we must mangle its name.
101  if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage())
102    return true;
103
104  // In C, functions with no attributes never need to be mangled. Fastpath them.
105  if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
106    return false;
107
108  // Any decl can be declared with __asm("foo") on it, and this takes precedence
109  // over all other naming in the .o file.
110  if (D->hasAttr<AsmLabelAttr>())
111    return true;
112
113  return shouldMangleCXXName(D);
114}
115
116void MangleContext::mangleName(const NamedDecl *Draw_ostream &Out) {
117  // Any decl can be declared with __asm("foo") on it, and this takes precedence
118  // over all other naming in the .o file.
119  if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
120    // If we have an asm name, then we use it as the mangling.
121
122    // Adding the prefix can cause problems when one file has a "foo" and
123    // another has a "\01foo". That is known to happen on ELF with the
124    // tricks normally used for producing aliases (PR9177). Fortunately the
125    // llvm mangler on ELF is a nop, so we can just avoid adding the \01
126    // marker.  We also avoid adding the marker if this is an alias for an
127    // LLVM intrinsic.
128    char GlobalPrefix =
129        getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix();
130    if (GlobalPrefix && !ALA->getLabel().startswith("llvm."))
131      Out << '\01'// LLVM IR Marker for __asm("foo")
132
133    Out << ALA->getLabel();
134    return;
135  }
136
137  const ASTContext &ASTContext = getASTContext();
138  CCMangling CC = getCallingConvMangling(ASTContextD);
139  bool MCXX = shouldMangleCXXName(D);
140  const TargetInfo &TI = Context.getTargetInfo();
141  if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
142    if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
143      mangleObjCMethodName(OMDOut);
144    else
145      mangleCXXName(DOut);
146    return;
147  }
148
149  Out << '\01';
150  if (CC == CCM_Std)
151    Out << '_';
152  else if (CC == CCM_Fast)
153    Out << '@';
154  else if (CC == CCM_RegCall)
155    Out << "__regcall3__";
156
157  if (!MCXX)
158    Out << D->getIdentifier()->getName();
159  else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
160    mangleObjCMethodName(OMDOut);
161  else
162    mangleCXXName(DOut);
163
164  const FunctionDecl *FD = cast<FunctionDecl>(D);
165  const FunctionType *FT = FD->getType()->castAs<FunctionType>();
166  const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);
167  if (CC == CCM_Vector)
168    Out << '@';
169  Out << '@';
170  if (!Proto) {
171    Out << '0';
172    return;
173  }
174  isVariadic()", "/home/seafit/code_projects/clang_source/clang/lib/AST/Mangle.cpp", 174, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Proto->isVariadic());
175  unsigned ArgWords = 0;
176  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
177    if (!MD->isStatic())
178      ++ArgWords;
179  for (const auto &AT : Proto->param_types())
180    // Size should be aligned to pointer size.
181    ArgWords +=
182        llvm::alignTo(ASTContext.getTypeSize(AT), TI.getPointerWidth(0)) /
183        TI.getPointerWidth(0);
184  Out << ((TI.getPointerWidth(0) / 8) * ArgWords);
185}
186
187void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
188                                      const NamedDecl *ID,
189                                      raw_ostream &Out) {
190  unsigned discriminator = getBlockId(BDfalse);
191  if (ID) {
192    if (shouldMangleDeclName(ID))
193      mangleName(IDOut);
194    else {
195      Out << ID->getIdentifier()->getName();
196    }
197  }
198  if (discriminator == 0)
199    Out << "_block_invoke";
200  else
201    Out << "_block_invoke_" << discriminator+1;
202}
203
204void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
205                                    CXXCtorType CTconst BlockDecl *BD,
206                                    raw_ostream &ResStream) {
207  SmallString<64Buffer;
208  llvm::raw_svector_ostream Out(Buffer);
209  mangleCXXCtor(CD, CT, Out);
210  mangleFunctionBlock(*this, Buffer, BD, ResStream);
211}
212
213void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
214                                    CXXDtorType DTconst BlockDecl *BD,
215                                    raw_ostream &ResStream) {
216  SmallString<64Buffer;
217  llvm::raw_svector_ostream Out(Buffer);
218  mangleCXXDtor(DD, DT, Out);
219  mangleFunctionBlock(*this, Buffer, BD, ResStream);
220}
221
222void MangleContext::mangleBlock(const DeclContext *DCconst BlockDecl *BD,
223                                raw_ostream &Out) {
224  (DC) && !isa(DC)", "/home/seafit/code_projects/clang_source/clang/lib/AST/Mangle.cpp", 224, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
225
226  SmallString<64Buffer;
227  llvm::raw_svector_ostream Stream(Buffer);
228  if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
229    mangleObjCMethodName(Method, Stream);
230  } else {
231     (0) . __assert_fail ("(isa(DC) || isa(DC)) && \"expected a NamedDecl or BlockDecl\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Mangle.cpp", 232, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
232 (0) . __assert_fail ("(isa(DC) || isa(DC)) && \"expected a NamedDecl or BlockDecl\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Mangle.cpp", 232, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">           "expected a NamedDecl or BlockDecl");
233    if (isa<BlockDecl>(DC))
234      for (; DC && isa<BlockDecl>(DC); DC = DC->getParent())
235        (void) getBlockId(cast<BlockDecl>(DC), true);
236     (0) . __assert_fail ("(isa(DC) || isa(DC)) && \"expected a TranslationUnitDecl or a NamedDecl\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Mangle.cpp", 237, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
237 (0) . __assert_fail ("(isa(DC) || isa(DC)) && \"expected a TranslationUnitDecl or a NamedDecl\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Mangle.cpp", 237, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">           "expected a TranslationUnitDecl or a NamedDecl");
238    if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
239      mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
240    else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
241      mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
242    else if (auto ND = dyn_cast<NamedDecl>(DC)) {
243      if (!shouldMangleDeclName(ND) && ND->getIdentifier())
244        Stream << ND->getIdentifier()->getName();
245      else {
246        // FIXME: We were doing a mangleUnqualifiedName() before, but that's
247        // a private member of a class that will soon itself be private to the
248        // Itanium C++ ABI object. What should we do now? Right now, I'm just
249        // calling the mangleName() method on the MangleContext; is there a
250        // better way?
251        mangleName(ND, Stream);
252      }
253    }
254  }
255  mangleFunctionBlock(*this, Buffer, BD, Out);
256}
257
258void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD,
259                                                    raw_ostream &OS) {
260  const ObjCContainerDecl *CD =
261  dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
262   (0) . __assert_fail ("CD && \"Missing container decl in GetNameForMethod\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/Mangle.cpp", 262, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert (CD && "Missing container decl in GetNameForMethod");
263  OS << (MD->isInstanceMethod() ? '-' : '+') << '[';
264  if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) {
265    OS << CID->getClassInterface()->getName();
266    OS << '(' << *CID << ')';
267  } else {
268    OS << CD->getName();
269  }
270  OS << ' ';
271  MD->getSelector().print(OS);
272  OS << ']';
273}
274
275void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
276                                         raw_ostream &Out) {
277  SmallString<64Name;
278  llvm::raw_svector_ostream OS(Name);
279
280  mangleObjCMethodNameWithoutSize(MD, OS);
281  Out << OS.str().size() << OS.str();
282}
283
clang::MangleContext::anchor
clang::MangleContext::shouldMangleDeclName
clang::MangleContext::mangleName
clang::MangleContext::mangleGlobalBlock
clang::MangleContext::mangleCtorBlock
clang::MangleContext::mangleDtorBlock
clang::MangleContext::mangleBlock
clang::MangleContext::mangleObjCMethodNameWithoutSize
clang::MangleContext::mangleObjCMethodName