clang: lib/AST/Mangle.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
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
30using namespace clang;
31
34 std::optional CategoryName,
35 StringRef MethodName) {
36
37 if (includePrefixByte)
38 OS << "\01";
40 OS << '[';
41 OS << ClassName;
42 if (CategoryName)
43 OS << "(" << *CategoryName << ")";
44 OS << " ";
45 OS << MethodName;
46 OS << ']';
47}
48
49
50
51
53 StringRef Outer,
55 raw_ostream &Out) {
56 unsigned discriminator = Context.getBlockId(BD, true);
57 if (discriminator == 0)
58 Out << "__" << Outer << "_block_invoke";
59 else
60 Out << "__" << Outer << "_block_invoke_" << discriminator+1;
61}
62
63void MangleContext::anchor() { }
64
73
75 if (const FunctionDecl *FD = dyn_cast(ND))
76 return FD->isExternC();
77 if (const VarDecl *VD = dyn_cast(ND))
78 return VD->isExternC();
79 return false;
80}
81
84 const TargetInfo &TI = Context.getTargetInfo();
85 const llvm::Triple &Triple = TI.getTriple();
86
87
88
89 if (Triple.isWasm())
90 if (const FunctionDecl *FD = dyn_cast(ND))
91 if (FD->isMain() && FD->getNumParams() == 2)
93
96
97 if (Context.getLangOpts().CPlusPlus && (ND) &&
98 TI.getCXXABI() == TargetCXXABI::Microsoft)
100
101 const FunctionDecl *FD = dyn_cast(ND);
102 if (!FD)
105
107
109 switch (CC) {
110 default:
118 }
119}
120
123
126 return true;
127
128
129
131 return true;
132
133
134
137 return true;
138
139
141 return false;
142
143
144
145 if (D->hasAttr())
146 return true;
147
148
150 return true;
151
153}
154
156
157
158
159
160
161
162
163
164
165
166
167
169 llvm::raw_ostream &Out) {
171
173
174 if (auto *Ctor = llvm::dyn_castclang::CXXConstructorDecl(GD.getDecl())) {
175 Out << "C";
176 if (Ctor->getInheritedConstructor().getConstructor())
177 Out << "I";
179 } else if (llvm::isaclang::CXXDestructorDecl(GD.getDecl())) {
181 }
182
184}
185
189
190
191
192 if (const AsmLabelAttr *ALA = D->getAttr()) {
193
194
195
196
197 if (ALA->getLabel().starts_with("llvm.")) {
198 Out << ALA->getLabel();
199 return;
200 }
201
202
203
204
205
206
207 StringRef UserLabelPrefix =
209#ifndef NDEBUG
210 char GlobalPrefix =
211 llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString())
212 .getGlobalPrefix();
213 assert((UserLabelPrefix.empty() && !GlobalPrefix) ||
214 (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix));
215#endif
216 if (!UserLabelPrefix.empty())
217 Out << '\01';
218
221 else
222 Out << ALA->getLabel();
223
224 return;
225 }
226
227 if (auto *GD = dyn_cast(D))
229
231
233 Out << "__main_argc_argv";
234 return;
235 }
236
238 const TargetInfo &TI = Context.getTargetInfo();
239 if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
240 if (const ObjCMethodDecl *OMD = dyn_cast(D))
242 else
244 return;
245 }
246
247 Out << '\01';
249 Out << '_';
251 Out << '@';
254 Out << "__regcall4__";
255 else
256 Out << "__regcall3__";
257 }
258
259 if (!MCXX)
261 else if (const ObjCMethodDecl *OMD = dyn_cast(D))
263 else
265
268 const FunctionProtoType *Proto = dyn_cast(FT);
270 Out << '@';
271 Out << '@';
272 if (!Proto) {
273 Out << '0';
274 return;
275 }
276 assert(!Proto->isVariadic());
277 unsigned ArgWords = 0;
278 if (const CXXMethodDecl *MD = dyn_cast(FD))
279 if (MD->isImplicitObjectMemberFunction())
280 ++ArgWords;
282 for (const auto &AT : Proto->param_types()) {
283
284
285
286 if (AT->isIncompleteType())
287 break;
288
290 DefaultPtrWidth;
291 }
292 Out << ((DefaultPtrWidth / 8) * ArgWords);
293}
294
296 raw_ostream &Out) const {
297
298
300 Out << llvm::format("_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_",
302 unsigned I = 0;
304 Out << llvm::format("%02" PRIx8, C);
305 if (++I == 2)
306 Out << "_";
307 }
308}
309
312 raw_ostream &Out) {
313 unsigned discriminator = getBlockId(BD, false);
314 if (ID) {
317 else {
318 Out << ID->getIdentifier()->getName();
319 }
320 }
321 if (discriminator == 0)
322 Out << "_block_invoke";
323 else
324 Out << "_block_invoke_" << discriminator+1;
325}
326
329 raw_ostream &ResStream) {
331 llvm::raw_svector_ostream Out(Buffer);
334}
335
338 raw_ostream &ResStream) {
340 llvm::raw_svector_ostream Out(Buffer);
343}
344
346 raw_ostream &Out) {
348
350 llvm::raw_svector_ostream Stream(Buffer);
353 } else {
355 "expected a NamedDecl or BlockDecl");
356 for (; isa_and_nonnull(DC); DC = DC->getParent())
359 "expected a TranslationUnitDecl or a NamedDecl");
360 if (const auto *CD = dyn_cast(DC))
362 else if (const auto *DD = dyn_cast(DC))
364 else if (auto ND = dyn_cast(DC)) {
366 Stream << ND->getIdentifier()->getName();
367 else {
368
369
370
371
372
374 }
375 }
376 }
378}
379
381 raw_ostream &OS,
382 bool includePrefixByte,
383 bool includeCategoryNamespace) const {
385
386
387
388
391
392 if (includeCategoryNamespace) {
394 OS << category->getName();
395 }
396 OS << '_';
397
399 for (unsigned slotIndex = 0,
400 numArgs = selector.getNumArgs(),
401 slotEnd = std::max(numArgs, 1U);
402 slotIndex != slotEnd; ++slotIndex) {
403 if (auto name = selector.getIdentifierInfoForSlot(slotIndex))
404 OS << name->getName();
405
406
407
408
409 if (numArgs)
410 OS << '_';
411 }
412
413 return;
414 }
415
416
417 auto CategoryName = std::optional();
418 StringRef ClassName = "";
419 if (const auto *CID = MD->getCategory()) {
420 if (const auto *CI = CID->getClassInterface()) {
421 ClassName = CI->getName();
422 if (includeCategoryNamespace) {
423 CategoryName = CID->getName();
424 }
425 }
426 } else if (const auto *CD =
428 ClassName = CD->getName();
429 } else {
430 llvm_unreachable("Unexpected ObjC method decl context");
431 }
432 std::string MethodName;
433 llvm::raw_string_ostream MethodNameOS(MethodName);
436 ClassName, CategoryName, MethodName);
437}
438
440 raw_ostream &Out) const {
442 llvm::raw_svector_ostream OS(Name);
443
445 true);
446 Out << OS.str().size() << OS.str();
447}
448
450 std::unique_ptr MC;
451 llvm::DataLayout DL;
452
453public:
455 : MC(Ctx.createMangleContext()),
456 DL(Ctx.getTargetInfo().getDataLayoutString()) {}
457
459
461 llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
462 if (auto *FD = dyn_cast(D)) {
463 if (FD->isDependentContext())
464 return true;
465 if (writeFuncOrVarName(FD, FrontendBufOS))
466 return true;
467 } else if (auto *VD = dyn_cast(D)) {
468 if (writeFuncOrVarName(VD, FrontendBufOS))
469 return true;
470 } else if (auto *MD = dyn_cast(D)) {
471 MC->mangleObjCMethodName(MD, OS, false,
472 true);
473 return false;
474 } else if (auto *ID = dyn_cast(D)) {
475 writeObjCClassName(ID, FrontendBufOS);
476 } else {
477 return true;
478 }
479
480
481 llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
482 return false;
483 }
484
486 std::string Name;
487 {
488 llvm::raw_string_ostream OS(Name);
490 }
491 return Name;
492 }
493
498
501 if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
502 return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
503 return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
504 }
505
507 StringRef ClassName;
508 if (const auto *OID = dyn_cast(OCD))
509 ClassName = OID->getObjCRuntimeNameAsString();
510 else if (const auto *OID = dyn_cast(OCD))
511 ClassName = OID->getObjCRuntimeNameAsString();
512
513 if (ClassName.empty())
514 return {};
515
516 auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
519 llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
520 return std::string(Mangled);
521 };
522
523 return {
526 };
527 }
528
530 if (const auto *OCD = dyn_cast(D))
532
534 return {};
535
537
540
541 std::vectorstd::string Manglings;
542
544 auto DefaultCC = C.getDefaultCallingConvention(false,
545 true);
546 auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv();
547 return CC == DefaultCC;
548 };
549
550 if (const auto *CD = dyn_cast_or_null(ND)) {
551 Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
552
554 if (!CD->getParent()->isAbstract())
555 Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
556
558 if (CD->hasAttr() && CD->isDefaultConstructor())
561 } else if (const auto *DD = dyn_cast_or_null(ND)) {
562 Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
564 Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
565 if (DD->isVirtual())
566 Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
567 }
568 } else if (const auto *MD = dyn_cast_or_null(ND)) {
569 Manglings.emplace_back(getName(ND));
570 if (MD->isVirtual()) {
572 for (const auto &T : *TIV) {
573 std::string ThunkName;
574 std::string ContextualizedName =
575 getMangledThunk(MD, T, false);
577 ThunkName = getMangledThunk(MD, T, true);
578 else
579 ThunkName = ContextualizedName;
580 Manglings.emplace_back(ThunkName);
581 }
582 }
583 }
584 }
585
586 return Manglings;
587 }
588
589private:
590 bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
591 if (MC->shouldMangleDeclName(D)) {
593 if (const auto *CtorD = dyn_cast(D))
595 else if (const auto *DtorD = dyn_cast(D))
597 else if (const FunctionDecl *FD = dyn_cast(D)) {
599 } else
601 MC->mangleName(GD, OS);
602 return false;
603 } else {
605 if (!II)
606 return true;
608 return false;
609 }
610 }
611
612 void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
615 }
616
617 std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
618 std::string FrontendBuf;
619 llvm::raw_string_ostream FOS(FrontendBuf);
620
621 GlobalDecl GD;
622 if (const auto *CD = dyn_cast_or_null(ND))
623 GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));
624 else if (const auto *DD = dyn_cast_or_null(ND))
625 GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));
626 MC->mangleName(GD, FOS);
627
628 std::string BackendBuf;
629 llvm::raw_string_ostream BOS(BackendBuf);
630
631 llvm::Mangler::getNameWithPrefix(BOS, FrontendBuf, DL);
632
633 return BackendBuf;
634 }
635
636 std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T,
637 bool ElideOverrideInfo) {
638 std::string FrontendBuf;
639 llvm::raw_string_ostream FOS(FrontendBuf);
640
641 MC->mangleThunk(MD, T, ElideOverrideInfo, FOS);
642
643 std::string BackendBuf;
644 llvm::raw_string_ostream BOS(BackendBuf);
645
646 llvm::Mangler::getNameWithPrefix(BOS, FrontendBuf, DL);
647
648 return BackendBuf;
649 }
650};
651
654
656
658 return Impl->writeName(D, OS);
659}
660
662 return Impl->getName(D);
663}
664
666 return Impl->getAllManglings(D);
667}
Enums/classes describing ABI related information about constructors, destructors and thunks.
Defines the clang::ASTContext interface.
static bool hasDefaultCXXMethodCC(ASTContext &Context, const CXXMethodDecl *MD)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
CCMangling
Definition Mangle.cpp:65
@ CCM_Fast
Definition Mangle.cpp:67
@ CCM_Vector
Definition Mangle.cpp:69
@ CCM_Std
Definition Mangle.cpp:70
@ CCM_WasmMainArgcArgv
Definition Mangle.cpp:71
@ CCM_RegCall
Definition Mangle.cpp:68
@ CCM_Other
Definition Mangle.cpp:66
static llvm::StringRef g_lldb_func_call_label_prefix
Definition Mangle.cpp:155
static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD, llvm::raw_ostream &Out)
Given an LLDB function call label, this function prints the label into Out, together with the structo...
Definition Mangle.cpp:168
static void mangleFunctionBlock(MangleContext &Context, StringRef Outer, const BlockDecl *BD, raw_ostream &Out)
Definition Mangle.cpp:52
static bool isExternC(const NamedDecl *ND)
Definition Mangle.cpp:74
static CCMangling getCallingConvMangling(const ASTContext &Context, const NamedDecl *ND)
Definition Mangle.cpp:82
Definition Mangle.cpp:449
std::string getName(const Decl *D)
Definition Mangle.cpp:485
ObjCKind
Definition Mangle.cpp:494
@ ObjCClass
Definition Mangle.cpp:495
@ ObjCMetaclass
Definition Mangle.cpp:496
std::vector< std::string > getAllManglings(const Decl *D)
Definition Mangle.cpp:529
static StringRef getClassSymbolPrefix(ObjCKind Kind, const ASTContext &Context)
Definition Mangle.cpp:499
bool writeName(const Decl *D, raw_ostream &OS)
Definition Mangle.cpp:458
Implementation(ASTContext &Ctx)
Definition Mangle.cpp:454
std::vector< std::string > getAllManglings(const ObjCContainerDecl *OCD)
Definition Mangle.cpp:506
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
MangleContext * createMangleContext(const TargetInfo *T=nullptr)
If T is null pointer, assume the target in ASTContext.
bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl, StringRef MangledName)
VTableContextBase * getVTableContext()
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
const TargetInfo & getTargetInfo() const
std::string getName(const Decl *D)
Definition Mangle.cpp:661
ASTNameGenerator(ASTContext &Ctx)
Definition Mangle.cpp:652
bool writeName(const Decl *D, raw_ostream &OS)
Writes name for D to OS.
Definition Mangle.cpp:657
std::vector< std::string > getAllManglings(const Decl *D)
Definition Mangle.cpp:665
~ASTNameGenerator()
Definition Mangle.cpp:655
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
DeclContext * getDeclContext()
Module * getOwningModuleForLinkage() const
Get the module that owns this declaration for linkage purposes.
Represents a function declaration or definition.
Represents a prototype with parameter type info, e.g.
FunctionType - C99 6.7.5.3 - Function Declarators.
CallingConv getCallConv() const
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
CXXDtorType getDtorType() const
const Decl * getDecl() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Parts getParts() const
Get the decomposed parts of this declaration.
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
void mangleBlock(const DeclContext *DC, const BlockDecl *BD, raw_ostream &Out)
Definition Mangle.cpp:345
unsigned getBlockId(const BlockDecl *BD, bool Local)
void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, raw_ostream &Out)
Definition Mangle.cpp:327
ASTContext & getASTContext() const
void mangleGlobalBlock(const BlockDecl *BD, const NamedDecl *ID, raw_ostream &Out)
Definition Mangle.cpp:310
virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND)
bool shouldMangleDeclName(const NamedDecl *D)
Definition Mangle.cpp:121
virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream &) const
Definition Mangle.cpp:295
void mangleName(GlobalDecl GD, raw_ostream &)
Definition Mangle.cpp:186
virtual void mangleCXXName(GlobalDecl GD, raw_ostream &)=0
virtual bool shouldMangleCXXName(const NamedDecl *D)=0
void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT, const BlockDecl *BD, raw_ostream &Out)
Definition Mangle.cpp:336
void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &OS, bool includePrefixByte=true, bool includeCategoryNamespace=true) const
Definition Mangle.cpp:380
void mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD, raw_ostream &) const
Definition Mangle.cpp:439
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool hasExternalFormalLinkage() const
True if this decl has external linkage.
ObjCContainerDecl - Represents a container for method declarations.
StringRef getObjCRuntimeNameAsString() const
Produce a name to be used for class's metadata.
ObjCMethodDecl - Represents an instance or class method declaration.
Selector getSelector() const
bool isInstanceMethod() const
ObjCCategoryDecl * getCategory()
If this method is declared or implemented in a category, return that category.
bool isClassMethod() const
ObjCInterfaceDecl * getClassInterface()
The basic abstraction for the target Objective-C runtime.
bool isGNUFamily() const
Is this runtime basically of the GNU family of runtimes?
A (possibly-)qualified type.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
bool isItaniumFamily() const
Does this ABI generally fall into the Itanium family of ABIs?
Exposes information about the current target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
const char * getUserLabelPrefix() const
Returns the default value of the USER_LABEL_PREFIX macro, which is the prefix given to user symbols b...
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
bool shouldUseMicrosoftCCforMangling() const
Should the Microsoft mangling scheme be used for C Calling Convention.
const T * castAs() const
Member-template castAs.
virtual const ThunkInfoVectorTy * getThunkInfo(GlobalDecl GD)
Represents a variable declaration or definition.
Defines the clang::TargetInfo interface.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_DefaultClosure
Default closure variant of a ctor.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
bool isInstanceMethod(const Decl *D)
const FunctionProtoType * T
CXXDtorType
C++ destructor types.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
CallingConv
CallingConv - Specifies the calling convention that a function uses.
U cast(CodeGen::Address addr)
void mangleObjCMethodName(raw_ostream &OS, bool includePrefixByte, bool isInstanceMethod, StringRef ClassName, std::optional< StringRef > CategoryName, StringRef MethodName)
Extract mangling function name from MangleContext such that swift can call it to prepare for ObjCDire...
Definition Mangle.cpp:32
uint16_t Part2
...-89ab-...
uint32_t Part1
{01234567-...
uint16_t Part3
...-cdef-...
uint8_t Part4And5[8]
...-0123-456789abcdef}