1 //===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Implements generic name mangling support for blocks and Objective-C.
12 //===----------------------------------------------------------------------===//
13 #include "clang/AST/Attr.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/ExprCXX.h"
20 #include "clang/AST/Mangle.h"
21 #include "clang/Basic/ABI.h"
22 #include "clang/Basic/SourceManager.h"
23 #include "clang/Basic/TargetInfo.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/raw_ostream.h"
28 #define MANGLE_CHECKER 0
34 using namespace clang
;
36 // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
37 // much to be desired. Come up with a better mangling scheme.
39 static void mangleFunctionBlock(MangleContext
&Context
,
43 unsigned discriminator
= Context
.getBlockId(BD
, true);
44 if (discriminator
== 0)
45 Out
<< "__" << Outer
<< "_block_invoke";
47 Out
<< "__" << Outer
<< "_block_invoke_" << discriminator
+1;
50 void MangleContext::anchor() { }
59 static bool isExternC(const NamedDecl
*ND
) {
60 if (const FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(ND
))
61 return FD
->isExternC();
62 return cast
<VarDecl
>(ND
)->isExternC();
65 static CCMangling
getCallingConvMangling(const ASTContext
&Context
,
66 const NamedDecl
*ND
) {
67 const TargetInfo
&TI
= Context
.getTargetInfo();
68 const llvm::Triple
&Triple
= TI
.getTriple();
69 if (!Triple
.isOSWindows() ||
70 !(Triple
.getArch() == llvm::Triple::x86
||
71 Triple
.getArch() == llvm::Triple::x86_64
))
74 if (Context
.getLangOpts().CPlusPlus
&& !isExternC(ND
) &&
75 TI
.getCXXABI() == TargetCXXABI::Microsoft
)
78 const FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(ND
);
81 QualType T
= FD
->getType();
83 const FunctionType
*FT
= T
->castAs
<FunctionType
>();
85 CallingConv CC
= FT
->getCallConv();
93 case CC_X86VectorCall
:
98 bool MangleContext::shouldMangleDeclName(const NamedDecl
*D
) {
99 const ASTContext
&ASTContext
= getASTContext();
101 CCMangling CC
= getCallingConvMangling(ASTContext
, D
);
105 // In C, functions with no attributes never need to be mangled. Fastpath them.
106 if (!getASTContext().getLangOpts().CPlusPlus
&& !D
->hasAttrs())
109 // Any decl can be declared with __asm("foo") on it, and this takes precedence
110 // over all other naming in the .o file.
111 if (D
->hasAttr
<AsmLabelAttr
>())
114 return shouldMangleCXXName(D
);
117 void MangleContext::mangleName(const NamedDecl
*D
, raw_ostream
&Out
) {
118 // Any decl can be declared with __asm("foo") on it, and this takes precedence
119 // over all other naming in the .o file.
120 if (const AsmLabelAttr
*ALA
= D
->getAttr
<AsmLabelAttr
>()) {
121 // If we have an asm name, then we use it as the mangling.
123 // Adding the prefix can cause problems when one file has a "foo" and
124 // another has a "\01foo". That is known to happen on ELF with the
125 // tricks normally used for producing aliases (PR9177). Fortunately the
126 // llvm mangler on ELF is a nop, so we can just avoid adding the \01
127 // marker. We also avoid adding the marker if this is an alias for an
129 StringRef UserLabelPrefix
=
130 getASTContext().getTargetInfo().getUserLabelPrefix();
131 if (!UserLabelPrefix
.empty() && !ALA
->getLabel().startswith("llvm."))
132 Out
<< '\01'; // LLVM IR Marker for __asm("foo")
134 Out
<< ALA
->getLabel();
138 const ASTContext
&ASTContext
= getASTContext();
139 CCMangling CC
= getCallingConvMangling(ASTContext
, D
);
140 bool MCXX
= shouldMangleCXXName(D
);
141 const TargetInfo
&TI
= Context
.getTargetInfo();
142 if (CC
== CCM_Other
|| (MCXX
&& TI
.getCXXABI() == TargetCXXABI::Microsoft
)) {
143 if (const ObjCMethodDecl
*OMD
= dyn_cast
<ObjCMethodDecl
>(D
))
144 mangleObjCMethodName(OMD
, Out
);
146 mangleCXXName(D
, Out
);
153 else if (CC
== CCM_Fast
)
157 Out
<< D
->getIdentifier()->getName();
158 else if (const ObjCMethodDecl
*OMD
= dyn_cast
<ObjCMethodDecl
>(D
))
159 mangleObjCMethodName(OMD
, Out
);
161 mangleCXXName(D
, Out
);
163 const FunctionDecl
*FD
= cast
<FunctionDecl
>(D
);
164 const FunctionType
*FT
= FD
->getType()->castAs
<FunctionType
>();
165 const FunctionProtoType
*Proto
= dyn_cast
<FunctionProtoType
>(FT
);
166 if (CC
== CCM_Vector
)
173 assert(!Proto
->isVariadic());
174 unsigned ArgWords
= 0;
175 if (const CXXMethodDecl
*MD
= dyn_cast
<CXXMethodDecl
>(FD
))
178 for (const auto &AT
: Proto
->param_types())
179 // Size should be aligned to pointer size.
180 ArgWords
+= llvm::RoundUpToAlignment(ASTContext
.getTypeSize(AT
),
181 TI
.getPointerWidth(0)) /
182 TI
.getPointerWidth(0);
183 Out
<< ((TI
.getPointerWidth(0) / 8) * ArgWords
);
186 void MangleContext::mangleGlobalBlock(const BlockDecl
*BD
,
189 unsigned discriminator
= getBlockId(BD
, false);
191 if (shouldMangleDeclName(ID
))
194 Out
<< ID
->getIdentifier()->getName();
197 if (discriminator
== 0)
198 Out
<< "_block_invoke";
200 Out
<< "_block_invoke_" << discriminator
+1;
203 void MangleContext::mangleCtorBlock(const CXXConstructorDecl
*CD
,
204 CXXCtorType CT
, const BlockDecl
*BD
,
205 raw_ostream
&ResStream
) {
206 SmallString
<64> Buffer
;
207 llvm::raw_svector_ostream
Out(Buffer
);
208 mangleCXXCtor(CD
, CT
, Out
);
210 mangleFunctionBlock(*this, Buffer
, BD
, ResStream
);
213 void MangleContext::mangleDtorBlock(const CXXDestructorDecl
*DD
,
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
);
220 mangleFunctionBlock(*this, Buffer
, BD
, ResStream
);
223 void MangleContext::mangleBlock(const DeclContext
*DC
, const BlockDecl
*BD
,
225 assert(!isa
<CXXConstructorDecl
>(DC
) && !isa
<CXXDestructorDecl
>(DC
));
227 SmallString
<64> Buffer
;
228 llvm::raw_svector_ostream
Stream(Buffer
);
229 if (const ObjCMethodDecl
*Method
= dyn_cast
<ObjCMethodDecl
>(DC
)) {
230 mangleObjCMethodName(Method
, Stream
);
232 assert((isa
<NamedDecl
>(DC
) || isa
<BlockDecl
>(DC
)) &&
233 "expected a NamedDecl or BlockDecl");
234 if (isa
<BlockDecl
>(DC
))
235 for (; DC
&& isa
<BlockDecl
>(DC
); DC
= DC
->getParent())
236 (void) getBlockId(cast
<BlockDecl
>(DC
), true);
237 assert((isa
<TranslationUnitDecl
>(DC
) || isa
<NamedDecl
>(DC
)) &&
238 "expected a TranslationUnitDecl or a NamedDecl");
239 if (const auto *CD
= dyn_cast
<CXXConstructorDecl
>(DC
))
240 mangleCtorBlock(CD
, /*CT*/ Ctor_Complete
, BD
, Out
);
241 else if (const auto *DD
= dyn_cast
<CXXDestructorDecl
>(DC
))
242 mangleDtorBlock(DD
, /*DT*/ Dtor_Complete
, BD
, Out
);
243 else if (auto ND
= dyn_cast
<NamedDecl
>(DC
)) {
244 if (!shouldMangleDeclName(ND
) && ND
->getIdentifier())
245 Stream
<< ND
->getIdentifier()->getName();
247 // FIXME: We were doing a mangleUnqualifiedName() before, but that's
248 // a private member of a class that will soon itself be private to the
249 // Itanium C++ ABI object. What should we do now? Right now, I'm just
250 // calling the mangleName() method on the MangleContext; is there a
252 mangleName(ND
, Stream
);
257 mangleFunctionBlock(*this, Buffer
, BD
, Out
);
260 void MangleContext::mangleObjCMethodName(const ObjCMethodDecl
*MD
,
262 SmallString
<64> Name
;
263 llvm::raw_svector_ostream
OS(Name
);
265 const ObjCContainerDecl
*CD
=
266 dyn_cast
<ObjCContainerDecl
>(MD
->getDeclContext());
267 assert (CD
&& "Missing container decl in GetNameForMethod");
268 OS
<< (MD
->isInstanceMethod() ? '-' : '+') << '[' << CD
->getName();
269 if (const ObjCCategoryImplDecl
*CID
= dyn_cast
<ObjCCategoryImplDecl
>(CD
))
270 OS
<< '(' << *CID
<< ')';
272 MD
->getSelector().print(OS
);
275 Out
<< OS
.str().size() << OS
.str();