clang  9.0.0svn
Mangle.cpp
Go to the documentation of this file.
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"
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 
27 using 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 
32 static void mangleFunctionBlock(MangleContext &Context,
33  StringRef Outer,
34  const BlockDecl *BD,
35  raw_ostream &Out) {
36  unsigned discriminator = Context.getBlockId(BD, true);
37  if (discriminator == 0)
38  Out << "__" << Outer << "_block_invoke";
39  else
40  Out << "__" << Outer << "_block_invoke_" << discriminator+1;
41 }
42 
43 void MangleContext::anchor() { }
44 
45 enum CCMangling {
51 };
52 
53 static 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 
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) &&
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 
94 
95  CCMangling CC = getCallingConvMangling(ASTContext, D);
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.
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 
116 void MangleContext::mangleName(const NamedDecl *D, raw_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 
138  CCMangling CC = getCallingConvMangling(ASTContext, D);
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(OMD, Out);
144  else
145  mangleCXXName(D, Out);
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(OMD, Out);
161  else
162  mangleCXXName(D, Out);
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  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 
188  const NamedDecl *ID,
189  raw_ostream &Out) {
190  unsigned discriminator = getBlockId(BD, false);
191  if (ID) {
192  if (shouldMangleDeclName(ID))
193  mangleName(ID, Out);
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 
205  CXXCtorType CT, const BlockDecl *BD,
206  raw_ostream &ResStream) {
207  SmallString<64> Buffer;
208  llvm::raw_svector_ostream Out(Buffer);
209  mangleCXXCtor(CD, CT, Out);
210  mangleFunctionBlock(*this, Buffer, BD, ResStream);
211 }
212 
214  CXXDtorType DT, const BlockDecl *BD,
215  raw_ostream &ResStream) {
216  SmallString<64> Buffer;
217  llvm::raw_svector_ostream Out(Buffer);
218  mangleCXXDtor(DD, DT, Out);
219  mangleFunctionBlock(*this, Buffer, BD, ResStream);
220 }
221 
223  raw_ostream &Out) {
224  assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
225 
226  SmallString<64> Buffer;
227  llvm::raw_svector_ostream Stream(Buffer);
228  if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
229  mangleObjCMethodName(Method, Stream);
230  } else {
231  assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
232  "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  assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
237  "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 
259  raw_ostream &OS) {
260  const ObjCContainerDecl *CD =
261  dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
262  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 
276  raw_ostream &Out) {
277  SmallString<64> Name;
278  llvm::raw_svector_ostream OS(Name);
279 
281  Out << OS.str().size() << OS.str();
282 }
Defines the clang::ASTContext interface.
Represents a function declaration or definition.
Definition: Decl.h:1748
Complete object ctor.
Definition: ABI.h:25
A (possibly-)qualified type.
Definition: Type.h:643
Module * getOwningModuleForLinkage(bool IgnoreLinkage=false) const
Get the module that owns this declaration for linkage purposes.
Definition: Decl.cpp:1504
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:3372
virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, raw_ostream &)=0
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:983
Defines the SourceManager interface.
virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, raw_ostream &)=0
Defines the C++ template declaration subclasses.
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:693
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2561
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:138
Defines the clang::Expr interface and subclasses for C++ expressions.
void mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, raw_ostream &)
Definition: Mangle.cpp:258
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:269
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
Definition: TargetInfo.h:358
static CCMangling getCallingConvMangling(const ASTContext &Context, const NamedDecl *ND)
Definition: Mangle.cpp:59
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
Definition: TargetInfo.h:1052
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:154
bool shouldMangleDeclName(const NamedDecl *D)
Definition: Mangle.cpp:92
ObjCContainerDecl - Represents a container for method declarations.
Definition: DeclObjC.h:968
The Microsoft ABI is the ABI used by Microsoft Visual Studio (and compatible compilers).
Definition: TargetCXXABI.h:112
Enums/classes describing ABI related information about constructors, destructors and thunks...
void mangleName(const NamedDecl *D, raw_ostream &)
Definition: Mangle.cpp:116
bool hasAttr() const
Definition: DeclBase.h:542
Represents a prototype with parameter type info, e.g.
Definition: Type.h:3704
Exposes information about the current target.
Definition: TargetInfo.h:161
CXXDtorType
C++ destructor types.
Definition: ABI.h:33
ASTContext & getASTContext() const
Definition: Mangle.h:71
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:3884
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:6883
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2825
DeclContext * getDeclContext()
Definition: DeclBase.h:438
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1772
bool isInstanceMethod() const
Definition: DeclObjC.h:421
Selector getSelector() const
Definition: DeclObjC.h:320
CallingConv
CallingConv - Specifies the calling convention that a function uses.
Definition: Specifiers.h:264
bool hasAttrs() const
Definition: DeclBase.h:484
unsigned getBlockId(const BlockDecl *BD, bool Local)
Definition: Mangle.h:77
void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT, const BlockDecl *BD, raw_ostream &Out)
Definition: Mangle.cpp:213
virtual bool shouldMangleCXXName(const NamedDecl *D)=0
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2109
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition: Mangle.h:43
virtual void mangleCXXName(const NamedDecl *D, raw_ostream &)=0
const llvm::DataLayout & getDataLayout() const
Definition: TargetInfo.h:987
Complete object dtor.
Definition: ABI.h:35
CXXCtorType
C++ constructor types.
Definition: ABI.h:24
StringRef getName() const
Return the actual identifier string.
void mangleGlobalBlock(const BlockDecl *BD, const NamedDecl *ID, raw_ostream &Out)
Definition: Mangle.cpp:187
void mangleBlock(const DeclContext *DC, const BlockDecl *BD, raw_ostream &Out)
Definition: Mangle.cpp:222
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1271
void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &)
Definition: Mangle.cpp:275
T * getAttr() const
Definition: DeclBase.h:538
static void mangleFunctionBlock(MangleContext &Context, StringRef Outer, const BlockDecl *BD, raw_ostream &Out)
Definition: Mangle.cpp:32
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2079
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
CallingConv getCallConv() const
Definition: Type.h:3640
Defines the clang::TargetInfo interface.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:275
QualType getType() const
Definition: Decl.h:647
This represents a decl that may have a name.
Definition: Decl.h:248
CCMangling
Definition: Mangle.cpp:45
void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, raw_ostream &Out)
Definition: Mangle.cpp:204
const LangOptions & getLangOpts() const
Definition: ASTContext.h:710
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
Definition: DeclObjC.h:2498
bool hasExternalFormalLinkage() const
True if this decl has external linkage.
Definition: Decl.h:375
static bool isExternC(const NamedDecl *ND)
Definition: Mangle.cpp:53