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