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/Mangle.h" |
13 | #include "clang/AST/ASTContext.h" |
14 | #include "clang/AST/Attr.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/VTableBuilder.h" |
21 | #include "clang/Basic/ABI.h" |
22 | #include "clang/Basic/TargetInfo.h" |
23 | #include "llvm/ADT/StringExtras.h" |
24 | #include "llvm/IR/DataLayout.h" |
25 | #include "llvm/IR/Mangler.h" |
26 | #include "llvm/Support/ErrorHandling.h" |
27 | #include "llvm/Support/Format.h" |
28 | #include "llvm/Support/raw_ostream.h" |
29 | |
30 | using namespace clang; |
31 | |
32 | void clang::mangleObjCMethodName(raw_ostream &OS, bool includePrefixByte, |
33 | bool isInstanceMethod, StringRef ClassName, |
34 | std::optional<StringRef> CategoryName, |
35 | StringRef MethodName) { |
36 | // \01+[ContainerName(CategoryName) SelectorName] |
37 | if (includePrefixByte) |
38 | OS << "\01"; |
39 | OS << (isInstanceMethod ? '-' : '+'); |
40 | OS << '['; |
41 | OS << ClassName; |
42 | if (CategoryName) |
43 | OS << "("<< *CategoryName << ")"; |
44 | OS << " "; |
45 | OS << MethodName; |
46 | OS << ']'; |
47 | } |
48 | |
49 | // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves |
50 | // much to be desired. Come up with a better mangling scheme. |
51 | |
52 | static void mangleFunctionBlock(MangleContext &Context, |
53 | StringRef Outer, |
54 | const BlockDecl *BD, |
55 | raw_ostream &Out) { |
56 | unsigned discriminator = Context.getBlockId(BD, Local: true); |
57 | if (discriminator == 0) |
58 | Out << "__"<< Outer << "_block_invoke"; |
59 | else |
60 | Out << "__"<< Outer << "_block_invoke_"<< discriminator+1; |
61 | } |
62 | |
63 | void MangleContext::anchor() { } |
64 | |
65 | enum CCMangling { |
66 | CCM_Other, |
67 | CCM_Fast, |
68 | CCM_RegCall, |
69 | CCM_Vector, |
70 | CCM_Std, |
71 | CCM_WasmMainArgcArgv |
72 | }; |
73 | |
74 | static bool isExternC(const NamedDecl *ND) { |
75 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: ND)) |
76 | return FD->isExternC(); |
77 | if (const VarDecl *VD = dyn_cast<VarDecl>(Val: ND)) |
78 | return VD->isExternC(); |
79 | return false; |
80 | } |
81 | |
82 | static CCMangling getCallingConvMangling(const ASTContext &Context, |
83 | const NamedDecl *ND) { |
84 | const TargetInfo &TI = Context.getTargetInfo(); |
85 | const llvm::Triple &Triple = TI.getTriple(); |
86 | |
87 | // On wasm, the argc/argv form of "main" is renamed so that the startup code |
88 | // can call it with the correct function signature. |
89 | if (Triple.isWasm()) |
90 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: ND)) |
91 | if (FD->isMain() && FD->getNumParams() == 2) |
92 | return CCM_WasmMainArgcArgv; |
93 | |
94 | if (!TI.shouldUseMicrosoftCCforMangling()) |
95 | return CCM_Other; |
96 | |
97 | if (Context.getLangOpts().CPlusPlus && !isExternC(ND) && |
98 | TI.getCXXABI() == TargetCXXABI::Microsoft) |
99 | return CCM_Other; |
100 | |
101 | const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: ND); |
102 | if (!FD) |
103 | return CCM_Other; |
104 | QualType T = FD->getType(); |
105 | |
106 | const FunctionType *FT = T->castAs<FunctionType>(); |
107 | |
108 | CallingConv CC = FT->getCallConv(); |
109 | switch (CC) { |
110 | default: |
111 | return CCM_Other; |
112 | case CC_X86FastCall: |
113 | return CCM_Fast; |
114 | case CC_X86StdCall: |
115 | return CCM_Std; |
116 | case CC_X86VectorCall: |
117 | return CCM_Vector; |
118 | } |
119 | } |
120 | |
121 | bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { |
122 | const ASTContext &ASTContext = getASTContext(); |
123 | |
124 | CCMangling CC = getCallingConvMangling(Context: ASTContext, ND: D); |
125 | if (CC != CCM_Other) |
126 | return true; |
127 | |
128 | // If the declaration has an owning module for linkage purposes that needs to |
129 | // be mangled, we must mangle its name. |
130 | if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage()) |
131 | return true; |
132 | |
133 | // C functions with internal linkage have to be mangled with option |
134 | // -funique-internal-linkage-names. |
135 | if (!getASTContext().getLangOpts().CPlusPlus && |
136 | isUniqueInternalLinkageDecl(ND: D)) |
137 | return true; |
138 | |
139 | // In C, functions with no attributes never need to be mangled. Fastpath them. |
140 | if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) |
141 | return false; |
142 | |
143 | // Any decl can be declared with __asm("foo") on it, and this takes precedence |
144 | // over all other naming in the .o file. |
145 | if (D->hasAttr<AsmLabelAttr>()) |
146 | return true; |
147 | |
148 | // Declarations that don't have identifier names always need to be mangled. |
149 | if (isa<MSGuidDecl>(Val: D)) |
150 | return true; |
151 | |
152 | return shouldMangleCXXName(D); |
153 | } |
154 | |
155 | void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) { |
156 | const ASTContext &ASTContext = getASTContext(); |
157 | const NamedDecl *D = cast<NamedDecl>(Val: GD.getDecl()); |
158 | |
159 | // Any decl can be declared with __asm("foo") on it, and this takes precedence |
160 | // over all other naming in the .o file. |
161 | if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { |
162 | // If we have an asm name, then we use it as the mangling. |
163 | |
164 | // If the label isn't literal, or if this is an alias for an LLVM intrinsic, |
165 | // do not add a "\01" prefix. |
166 | if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) { |
167 | Out << ALA->getLabel(); |
168 | return; |
169 | } |
170 | |
171 | // Adding the prefix can cause problems when one file has a "foo" and |
172 | // another has a "\01foo". That is known to happen on ELF with the |
173 | // tricks normally used for producing aliases (PR9177). Fortunately the |
174 | // llvm mangler on ELF is a nop, so we can just avoid adding the \01 |
175 | // marker. |
176 | StringRef UserLabelPrefix = |
177 | getASTContext().getTargetInfo().getUserLabelPrefix(); |
178 | #ifndef NDEBUG |
179 | char GlobalPrefix = |
180 | llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString()) |
181 | .getGlobalPrefix(); |
182 | assert((UserLabelPrefix.empty() && !GlobalPrefix) || |
183 | (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix)); |
184 | #endif |
185 | if (!UserLabelPrefix.empty()) |
186 | Out << '\01'; // LLVM IR Marker for __asm("foo") |
187 | |
188 | Out << ALA->getLabel(); |
189 | return; |
190 | } |
191 | |
192 | if (auto *GD = dyn_cast<MSGuidDecl>(Val: D)) |
193 | return mangleMSGuidDecl(GD, Out); |
194 | |
195 | CCMangling CC = getCallingConvMangling(Context: ASTContext, ND: D); |
196 | |
197 | if (CC == CCM_WasmMainArgcArgv) { |
198 | Out << "__main_argc_argv"; |
199 | return; |
200 | } |
201 | |
202 | bool MCXX = shouldMangleCXXName(D); |
203 | const TargetInfo &TI = Context.getTargetInfo(); |
204 | if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { |
205 | if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D)) |
206 | mangleObjCMethodNameAsSourceName(MD: OMD, Out); |
207 | else |
208 | mangleCXXName(GD, Out); |
209 | return; |
210 | } |
211 | |
212 | Out << '\01'; |
213 | if (CC == CCM_Std) |
214 | Out << '_'; |
215 | else if (CC == CCM_Fast) |
216 | Out << '@'; |
217 | else if (CC == CCM_RegCall) { |
218 | if (getASTContext().getLangOpts().RegCall4) |
219 | Out << "__regcall4__"; |
220 | else |
221 | Out << "__regcall3__"; |
222 | } |
223 | |
224 | if (!MCXX) |
225 | Out << D->getIdentifier()->getName(); |
226 | else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D)) |
227 | mangleObjCMethodNameAsSourceName(MD: OMD, Out); |
228 | else |
229 | mangleCXXName(GD, Out); |
230 | |
231 | const FunctionDecl *FD = cast<FunctionDecl>(Val: D); |
232 | const FunctionType *FT = FD->getType()->castAs<FunctionType>(); |
233 | const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Val: FT); |
234 | if (CC == CCM_Vector) |
235 | Out << '@'; |
236 | Out << '@'; |
237 | if (!Proto) { |
238 | Out << '0'; |
239 | return; |
240 | } |
241 | assert(!Proto->isVariadic()); |
242 | unsigned ArgWords = 0; |
243 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Val: FD)) |
244 | if (MD->isImplicitObjectMemberFunction()) |
245 | ++ArgWords; |
246 | uint64_t DefaultPtrWidth = TI.getPointerWidth(AddrSpace: LangAS::Default); |
247 | for (const auto &AT : Proto->param_types()) { |
248 | // If an argument type is incomplete there is no way to get its size to |
249 | // correctly encode into the mangling scheme. |
250 | // Follow GCCs behaviour by simply breaking out of the loop. |
251 | if (AT->isIncompleteType()) |
252 | break; |
253 | // Size should be aligned to pointer size. |
254 | ArgWords += llvm::alignTo(ASTContext.getTypeSize(AT), DefaultPtrWidth) / |
255 | DefaultPtrWidth; |
256 | } |
257 | Out << ((DefaultPtrWidth / 8) * ArgWords); |
258 | } |
259 | |
260 | void MangleContext::mangleMSGuidDecl(const MSGuidDecl *GD, |
261 | raw_ostream &Out) const { |
262 | // For now, follow the MSVC naming convention for GUID objects on all |
263 | // targets. |
264 | MSGuidDecl::Parts P = GD->getParts(); |
265 | Out << llvm::format(Fmt: "_GUID_%08"PRIx32 "_%04"PRIx32 "_%04"PRIx32 "_", |
266 | Vals: P.Part1, Vals: P.Part2, Vals: P.Part3); |
267 | unsigned I = 0; |
268 | for (uint8_t C : P.Part4And5) { |
269 | Out << llvm::format(Fmt: "%02"PRIx8, Vals: C); |
270 | if (++I == 2) |
271 | Out << "_"; |
272 | } |
273 | } |
274 | |
275 | void MangleContext::mangleGlobalBlock(const BlockDecl *BD, |
276 | const NamedDecl *ID, |
277 | raw_ostream &Out) { |
278 | unsigned discriminator = getBlockId(BD, Local: false); |
279 | if (ID) { |
280 | if (shouldMangleDeclName(D: ID)) |
281 | mangleName(GD: ID, Out); |
282 | else { |
283 | Out << ID->getIdentifier()->getName(); |
284 | } |
285 | } |
286 | if (discriminator == 0) |
287 | Out << "_block_invoke"; |
288 | else |
289 | Out << "_block_invoke_"<< discriminator+1; |
290 | } |
291 | |
292 | void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, |
293 | CXXCtorType CT, const BlockDecl *BD, |
294 | raw_ostream &ResStream) { |
295 | SmallString<64> Buffer; |
296 | llvm::raw_svector_ostream Out(Buffer); |
297 | mangleName(GD: GlobalDecl(CD, CT), Out); |
298 | mangleFunctionBlock(Context&: *this, Outer: Buffer, BD, Out&: ResStream); |
299 | } |
300 | |
301 | void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, |
302 | CXXDtorType DT, const BlockDecl *BD, |
303 | raw_ostream &ResStream) { |
304 | SmallString<64> Buffer; |
305 | llvm::raw_svector_ostream Out(Buffer); |
306 | mangleName(GD: GlobalDecl(DD, DT), Out); |
307 | mangleFunctionBlock(Context&: *this, Outer: Buffer, BD, Out&: ResStream); |
308 | } |
309 | |
310 | void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, |
311 | raw_ostream &Out) { |
312 | assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); |
313 | |
314 | SmallString<64> Buffer; |
315 | llvm::raw_svector_ostream Stream(Buffer); |
316 | if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Val: DC)) { |
317 | mangleObjCMethodNameAsSourceName(MD: Method, Stream); |
318 | } else { |
319 | assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) && |
320 | "expected a NamedDecl or BlockDecl"); |
321 | for (; isa_and_nonnull<BlockDecl>(Val: DC); DC = DC->getParent()) |
322 | (void)getBlockId(BD: cast<BlockDecl>(Val: DC), Local: true); |
323 | assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) && |
324 | "expected a TranslationUnitDecl or a NamedDecl"); |
325 | if (const auto *CD = dyn_cast<CXXConstructorDecl>(Val: DC)) |
326 | mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, ResStream&: Out); |
327 | else if (const auto *DD = dyn_cast<CXXDestructorDecl>(Val: DC)) |
328 | mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, ResStream&: Out); |
329 | else if (auto ND = dyn_cast<NamedDecl>(Val: DC)) { |
330 | if (!shouldMangleDeclName(D: ND) && ND->getIdentifier()) |
331 | Stream << ND->getIdentifier()->getName(); |
332 | else { |
333 | // FIXME: We were doing a mangleUnqualifiedName() before, but that's |
334 | // a private member of a class that will soon itself be private to the |
335 | // Itanium C++ ABI object. What should we do now? Right now, I'm just |
336 | // calling the mangleName() method on the MangleContext; is there a |
337 | // better way? |
338 | mangleName(GD: ND, Out&: Stream); |
339 | } |
340 | } |
341 | } |
342 | mangleFunctionBlock(Context&: *this, Outer: Buffer, BD, Out); |
343 | } |
344 | |
345 | void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, |
346 | raw_ostream &OS, |
347 | bool includePrefixByte, |
348 | bool includeCategoryNamespace) const { |
349 | if (getASTContext().getLangOpts().ObjCRuntime.isGNUFamily()) { |
350 | // This is the mangling we've always used on the GNU runtimes, but it |
351 | // has obvious collisions in the face of underscores within class |
352 | // names, category names, and selectors; maybe we should improve it. |
353 | |
354 | OS << (MD->isClassMethod() ? "_c_": "_i_") |
355 | << MD->getClassInterface()->getName() << '_'; |
356 | |
357 | if (includeCategoryNamespace) { |
358 | if (auto category = MD->getCategory()) |
359 | OS << category->getName(); |
360 | } |
361 | OS << '_'; |
362 | |
363 | auto selector = MD->getSelector(); |
364 | for (unsigned slotIndex = 0, |
365 | numArgs = selector.getNumArgs(), |
366 | slotEnd = std::max(a: numArgs, b: 1U); |
367 | slotIndex != slotEnd; ++slotIndex) { |
368 | if (auto name = selector.getIdentifierInfoForSlot(argIndex: slotIndex)) |
369 | OS << name->getName(); |
370 | |
371 | // Replace all the positions that would've been ':' with '_'. |
372 | // That's after each slot except that a unary selector doesn't |
373 | // end in ':'. |
374 | if (numArgs) |
375 | OS << '_'; |
376 | } |
377 | |
378 | return; |
379 | } |
380 | |
381 | // \01+[ContainerName(CategoryName) SelectorName] |
382 | auto CategoryName = std::optional<StringRef>(); |
383 | StringRef ClassName = ""; |
384 | if (const auto *CID = MD->getCategory()) { |
385 | if (const auto *CI = CID->getClassInterface()) { |
386 | ClassName = CI->getName(); |
387 | if (includeCategoryNamespace) { |
388 | CategoryName = CID->getName(); |
389 | } |
390 | } |
391 | } else if (const auto *CD = |
392 | dyn_cast<ObjCContainerDecl>(MD->getDeclContext())) { |
393 | ClassName = CD->getName(); |
394 | } else { |
395 | llvm_unreachable("Unexpected ObjC method decl context"); |
396 | } |
397 | std::string MethodName; |
398 | llvm::raw_string_ostream MethodNameOS(MethodName); |
399 | MD->getSelector().print(OS&: MethodNameOS); |
400 | clang::mangleObjCMethodName(OS, includePrefixByte, isInstanceMethod: MD->isInstanceMethod(), |
401 | ClassName, CategoryName, MethodName); |
402 | } |
403 | |
404 | void MangleContext::mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD, |
405 | raw_ostream &Out) const { |
406 | SmallString<64> Name; |
407 | llvm::raw_svector_ostream OS(Name); |
408 | |
409 | mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false, |
410 | /*includeCategoryNamespace=*/true); |
411 | Out << OS.str().size() << OS.str(); |
412 | } |
413 | |
414 | class ASTNameGenerator::Implementation { |
415 | std::unique_ptr<MangleContext> MC; |
416 | llvm::DataLayout DL; |
417 | |
418 | public: |
419 | explicit Implementation(ASTContext &Ctx) |
420 | : MC(Ctx.createMangleContext()), |
421 | DL(Ctx.getTargetInfo().getDataLayoutString()) {} |
422 | |
423 | bool writeName(const Decl *D, raw_ostream &OS) { |
424 | // First apply frontend mangling. |
425 | SmallString<128> FrontendBuf; |
426 | llvm::raw_svector_ostream FrontendBufOS(FrontendBuf); |
427 | if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) { |
428 | if (FD->isDependentContext()) |
429 | return true; |
430 | if (writeFuncOrVarName(FD, FrontendBufOS)) |
431 | return true; |
432 | } else if (auto *VD = dyn_cast<VarDecl>(Val: D)) { |
433 | if (writeFuncOrVarName(VD, FrontendBufOS)) |
434 | return true; |
435 | } else if (auto *MD = dyn_cast<ObjCMethodDecl>(Val: D)) { |
436 | MC->mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false, |
437 | /*includeCategoryNamespace=*/true); |
438 | return false; |
439 | } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(Val: D)) { |
440 | writeObjCClassName(D: ID, OS&: FrontendBufOS); |
441 | } else { |
442 | return true; |
443 | } |
444 | |
445 | // Now apply backend mangling. |
446 | llvm::Mangler::getNameWithPrefix(OS, GVName: FrontendBufOS.str(), DL); |
447 | return false; |
448 | } |
449 | |
450 | std::string getName(const Decl *D) { |
451 | std::string Name; |
452 | { |
453 | llvm::raw_string_ostream OS(Name); |
454 | writeName(D, OS); |
455 | } |
456 | return Name; |
457 | } |
458 | |
459 | enum ObjCKind { |
460 | ObjCClass, |
461 | ObjCMetaclass, |
462 | }; |
463 | |
464 | static StringRef getClassSymbolPrefix(ObjCKind Kind, |
465 | const ASTContext &Context) { |
466 | if (Context.getLangOpts().ObjCRuntime.isGNUFamily()) |
467 | return Kind == ObjCMetaclass ? "_OBJC_METACLASS_": "_OBJC_CLASS_"; |
468 | return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_": "OBJC_CLASS_$_"; |
469 | } |
470 | |
471 | std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) { |
472 | StringRef ClassName; |
473 | if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(Val: OCD)) |
474 | ClassName = OID->getObjCRuntimeNameAsString(); |
475 | else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(Val: OCD)) |
476 | ClassName = OID->getObjCRuntimeNameAsString(); |
477 | |
478 | if (ClassName.empty()) |
479 | return {}; |
480 | |
481 | auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string { |
482 | SmallString<40> Mangled; |
483 | auto Prefix = getClassSymbolPrefix(Kind, Context: OCD->getASTContext()); |
484 | llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL); |
485 | return std::string(Mangled); |
486 | }; |
487 | |
488 | return { |
489 | Mangle(ObjCClass, ClassName), |
490 | Mangle(ObjCMetaclass, ClassName), |
491 | }; |
492 | } |
493 | |
494 | std::vector<std::string> getAllManglings(const Decl *D) { |
495 | if (const auto *OCD = dyn_cast<ObjCContainerDecl>(Val: D)) |
496 | return getAllManglings(OCD); |
497 | |
498 | if (!(isa<CXXRecordDecl>(Val: D) || isa<CXXMethodDecl>(Val: D))) |
499 | return {}; |
500 | |
501 | const NamedDecl *ND = cast<NamedDecl>(Val: D); |
502 | |
503 | ASTContext &Ctx = ND->getASTContext(); |
504 | std::unique_ptr<MangleContext> M(Ctx.createMangleContext()); |
505 | |
506 | std::vector<std::string> Manglings; |
507 | |
508 | auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { |
509 | auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, |
510 | /*IsCXXMethod=*/true); |
511 | auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv(); |
512 | return CC == DefaultCC; |
513 | }; |
514 | |
515 | if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Val: ND)) { |
516 | Manglings.emplace_back(args: getMangledStructor(CD, Ctor_Base)); |
517 | |
518 | if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) |
519 | if (!CD->getParent()->isAbstract()) |
520 | Manglings.emplace_back(args: getMangledStructor(CD, Ctor_Complete)); |
521 | |
522 | if (Ctx.getTargetInfo().getCXXABI().isMicrosoft()) |
523 | if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor()) |
524 | if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0)) |
525 | Manglings.emplace_back(args: getMangledStructor(CD, Ctor_DefaultClosure)); |
526 | } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(Val: ND)) { |
527 | Manglings.emplace_back(args: getMangledStructor(DD, Dtor_Base)); |
528 | if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) { |
529 | Manglings.emplace_back(args: getMangledStructor(DD, Dtor_Complete)); |
530 | if (DD->isVirtual()) |
531 | Manglings.emplace_back(args: getMangledStructor(DD, Dtor_Deleting)); |
532 | } |
533 | } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Val: ND)) { |
534 | Manglings.emplace_back(args: getName(ND)); |
535 | if (MD->isVirtual()) { |
536 | if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) { |
537 | for (const auto &T : *TIV) { |
538 | std::string ThunkName; |
539 | std::string ContextualizedName = |
540 | getMangledThunk(MD, T, /* ElideOverrideInfo */ false); |
541 | if (Ctx.useAbbreviatedThunkName(MD, ContextualizedName)) |
542 | ThunkName = getMangledThunk(MD, T, /* ElideOverrideInfo */ true); |
543 | else |
544 | ThunkName = ContextualizedName; |
545 | Manglings.emplace_back(ThunkName); |
546 | } |
547 | } |
548 | } |
549 | } |
550 | |
551 | return Manglings; |
552 | } |
553 | |
554 | private: |
555 | bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) { |
556 | if (MC->shouldMangleDeclName(D)) { |
557 | GlobalDecl GD; |
558 | if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(Val: D)) |
559 | GD = GlobalDecl(CtorD, Ctor_Complete); |
560 | else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(Val: D)) |
561 | GD = GlobalDecl(DtorD, Dtor_Complete); |
562 | else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) { |
563 | GD = FD->isReferenceableKernel() ? GlobalDecl(FD) : GlobalDecl(D); |
564 | } else |
565 | GD = GlobalDecl(D); |
566 | MC->mangleName(GD, Out&: OS); |
567 | return false; |
568 | } else { |
569 | IdentifierInfo *II = D->getIdentifier(); |
570 | if (!II) |
571 | return true; |
572 | OS << II->getName(); |
573 | return false; |
574 | } |
575 | } |
576 | |
577 | void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) { |
578 | OS << getClassSymbolPrefix(Kind: ObjCClass, Context: D->getASTContext()); |
579 | OS << D->getObjCRuntimeNameAsString(); |
580 | } |
581 | |
582 | std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) { |
583 | std::string FrontendBuf; |
584 | llvm::raw_string_ostream FOS(FrontendBuf); |
585 | |
586 | GlobalDecl GD; |
587 | if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Val: ND)) |
588 | GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType)); |
589 | else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(Val: ND)) |
590 | GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType)); |
591 | MC->mangleName(GD, Out&: FOS); |
592 | |
593 | std::string BackendBuf; |
594 | llvm::raw_string_ostream BOS(BackendBuf); |
595 | |
596 | llvm::Mangler::getNameWithPrefix(OS&: BOS, GVName: FrontendBuf, DL); |
597 | |
598 | return BackendBuf; |
599 | } |
600 | |
601 | std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T, |
602 | bool ElideOverrideInfo) { |
603 | std::string FrontendBuf; |
604 | llvm::raw_string_ostream FOS(FrontendBuf); |
605 | |
606 | MC->mangleThunk(MD, Thunk: T, ElideOverrideInfo, FOS); |
607 | |
608 | std::string BackendBuf; |
609 | llvm::raw_string_ostream BOS(BackendBuf); |
610 | |
611 | llvm::Mangler::getNameWithPrefix(OS&: BOS, GVName: FrontendBuf, DL); |
612 | |
613 | return BackendBuf; |
614 | } |
615 | }; |
616 | |
617 | ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx) |
618 | : Impl(std::make_unique<Implementation>(args&: Ctx)) {} |
619 | |
620 | ASTNameGenerator::~ASTNameGenerator() {} |
621 | |
622 | bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) { |
623 | return Impl->writeName(D, OS); |
624 | } |
625 | |
626 | std::string ASTNameGenerator::getName(const Decl *D) { |
627 | return Impl->getName(D); |
628 | } |
629 | |
630 | std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) { |
631 | return Impl->getAllManglings(D); |
632 | } |
633 |
Definitions
- mangleObjCMethodName
- mangleFunctionBlock
- anchor
- CCMangling
- isExternC
- getCallingConvMangling
- shouldMangleDeclName
- mangleName
- mangleMSGuidDecl
- mangleGlobalBlock
- mangleCtorBlock
- mangleDtorBlock
- mangleBlock
- mangleObjCMethodName
- mangleObjCMethodNameAsSourceName
- Implementation
- Implementation
- writeName
- getName
- ObjCKind
- getClassSymbolPrefix
- getAllManglings
- getAllManglings
- writeFuncOrVarName
- writeObjCClassName
- getMangledStructor
- getMangledThunk
- ASTNameGenerator
- ~ASTNameGenerator
- writeName
- getName
Learn to use CMake with our Intro Training
Find out more