1e7145dcbSDimitry Andric //===- CodegenNameGenerator.cpp - Codegen name generation -----------------===//
2e7145dcbSDimitry Andric //
3e7145dcbSDimitry Andric // The LLVM Compiler Infrastructure
4e7145dcbSDimitry Andric //
5e7145dcbSDimitry Andric // This file is distributed under the University of Illinois Open Source
6e7145dcbSDimitry Andric // License. See LICENSE.TXT for details.
7e7145dcbSDimitry Andric //
8e7145dcbSDimitry Andric //===----------------------------------------------------------------------===//
9e7145dcbSDimitry Andric //
10e7145dcbSDimitry Andric // Determines the name that the symbol will get for code generation.
11e7145dcbSDimitry Andric //
12e7145dcbSDimitry Andric //===----------------------------------------------------------------------===//
13e7145dcbSDimitry Andric
14e7145dcbSDimitry Andric #include "clang/Index/CodegenNameGenerator.h"
15e7145dcbSDimitry Andric #include "clang/AST/ASTContext.h"
16e7145dcbSDimitry Andric #include "clang/AST/DeclCXX.h"
17e7145dcbSDimitry Andric #include "clang/AST/DeclObjC.h"
18e7145dcbSDimitry Andric #include "clang/AST/Mangle.h"
19e7145dcbSDimitry Andric #include "clang/AST/VTableBuilder.h"
20e7145dcbSDimitry Andric #include "clang/Basic/TargetInfo.h"
21e7145dcbSDimitry Andric #include "llvm/IR/DataLayout.h"
22e7145dcbSDimitry Andric #include "llvm/IR/Mangler.h"
23e7145dcbSDimitry Andric #include "llvm/Support/raw_ostream.h"
24e7145dcbSDimitry Andric
25e7145dcbSDimitry Andric using namespace clang;
26e7145dcbSDimitry Andric using namespace clang::index;
27e7145dcbSDimitry Andric
28e7145dcbSDimitry Andric struct CodegenNameGenerator::Implementation {
29e7145dcbSDimitry Andric std::unique_ptr<MangleContext> MC;
30e7145dcbSDimitry Andric llvm::DataLayout DL;
31e7145dcbSDimitry Andric
ImplementationCodegenNameGenerator::Implementation32e7145dcbSDimitry Andric Implementation(ASTContext &Ctx)
33e7145dcbSDimitry Andric : MC(Ctx.createMangleContext()),
34e7145dcbSDimitry Andric DL(Ctx.getTargetInfo().getDataLayout()) {}
35e7145dcbSDimitry Andric
writeNameCodegenNameGenerator::Implementation36e7145dcbSDimitry Andric bool writeName(const Decl *D, raw_ostream &OS) {
37e7145dcbSDimitry Andric // First apply frontend mangling.
38e7145dcbSDimitry Andric SmallString<128> FrontendBuf;
39e7145dcbSDimitry Andric llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
40e7145dcbSDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(D)) {
41e7145dcbSDimitry Andric if (FD->isDependentContext())
42e7145dcbSDimitry Andric return true;
43e7145dcbSDimitry Andric if (writeFuncOrVarName(FD, FrontendBufOS))
44e7145dcbSDimitry Andric return true;
45e7145dcbSDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) {
46e7145dcbSDimitry Andric if (writeFuncOrVarName(VD, FrontendBufOS))
47e7145dcbSDimitry Andric return true;
48e7145dcbSDimitry Andric } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
49e7145dcbSDimitry Andric MC->mangleObjCMethodNameWithoutSize(MD, OS);
50e7145dcbSDimitry Andric return false;
51e7145dcbSDimitry Andric } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
52e7145dcbSDimitry Andric writeObjCClassName(ID, FrontendBufOS);
53e7145dcbSDimitry Andric } else {
54e7145dcbSDimitry Andric return true;
55e7145dcbSDimitry Andric }
56e7145dcbSDimitry Andric
57e7145dcbSDimitry Andric // Now apply backend mangling.
58e7145dcbSDimitry Andric llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
59e7145dcbSDimitry Andric return false;
60e7145dcbSDimitry Andric }
61e7145dcbSDimitry Andric
getNameCodegenNameGenerator::Implementation62e7145dcbSDimitry Andric std::string getName(const Decl *D) {
63e7145dcbSDimitry Andric std::string Name;
64e7145dcbSDimitry Andric {
65e7145dcbSDimitry Andric llvm::raw_string_ostream OS(Name);
66e7145dcbSDimitry Andric writeName(D, OS);
67e7145dcbSDimitry Andric }
68e7145dcbSDimitry Andric return Name;
69e7145dcbSDimitry Andric }
70e7145dcbSDimitry Andric
71*9a199699SDimitry Andric enum ObjCKind {
72*9a199699SDimitry Andric ObjCClass,
73*9a199699SDimitry Andric ObjCMetaclass,
74*9a199699SDimitry Andric };
75*9a199699SDimitry Andric
getAllManglingsCodegenNameGenerator::Implementation76*9a199699SDimitry Andric std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
77*9a199699SDimitry Andric StringRef ClassName;
78*9a199699SDimitry Andric if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
79*9a199699SDimitry Andric ClassName = OID->getObjCRuntimeNameAsString();
80*9a199699SDimitry Andric else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))
81*9a199699SDimitry Andric ClassName = OID->getObjCRuntimeNameAsString();
82*9a199699SDimitry Andric
83*9a199699SDimitry Andric if (ClassName.empty())
84*9a199699SDimitry Andric return {};
85*9a199699SDimitry Andric
86*9a199699SDimitry Andric auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
87*9a199699SDimitry Andric SmallString<40> Mangled;
88*9a199699SDimitry Andric auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
89*9a199699SDimitry Andric llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
90*9a199699SDimitry Andric return Mangled.str();
91*9a199699SDimitry Andric };
92*9a199699SDimitry Andric
93*9a199699SDimitry Andric return {
94*9a199699SDimitry Andric Mangle(ObjCClass, ClassName),
95*9a199699SDimitry Andric Mangle(ObjCMetaclass, ClassName),
96*9a199699SDimitry Andric };
97*9a199699SDimitry Andric }
98*9a199699SDimitry Andric
getAllManglingsCodegenNameGenerator::Implementation99e7145dcbSDimitry Andric std::vector<std::string> getAllManglings(const Decl *D) {
100*9a199699SDimitry Andric if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
101*9a199699SDimitry Andric return getAllManglings(OCD);
102*9a199699SDimitry Andric
103e7145dcbSDimitry Andric if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
104e7145dcbSDimitry Andric return {};
105e7145dcbSDimitry Andric
106e7145dcbSDimitry Andric const NamedDecl *ND = cast<NamedDecl>(D);
107e7145dcbSDimitry Andric
108e7145dcbSDimitry Andric ASTContext &Ctx = ND->getASTContext();
109e7145dcbSDimitry Andric std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
110e7145dcbSDimitry Andric
111e7145dcbSDimitry Andric std::vector<std::string> Manglings;
112e7145dcbSDimitry Andric
113e7145dcbSDimitry Andric auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
114e7145dcbSDimitry Andric auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
115e7145dcbSDimitry Andric /*IsCSSMethod=*/true);
116e7145dcbSDimitry Andric auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
117e7145dcbSDimitry Andric return CC == DefaultCC;
118e7145dcbSDimitry Andric };
119e7145dcbSDimitry Andric
120e7145dcbSDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
121e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
122e7145dcbSDimitry Andric
123e7145dcbSDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
124e7145dcbSDimitry Andric if (!CD->getParent()->isAbstract())
125e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
126e7145dcbSDimitry Andric
127e7145dcbSDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
128e7145dcbSDimitry Andric if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
129e7145dcbSDimitry Andric if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
130e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
131e7145dcbSDimitry Andric } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
132e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
133e7145dcbSDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
134e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
135e7145dcbSDimitry Andric if (DD->isVirtual())
136e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
137e7145dcbSDimitry Andric }
138e7145dcbSDimitry Andric } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
139e7145dcbSDimitry Andric Manglings.emplace_back(getName(ND));
140e7145dcbSDimitry Andric if (MD->isVirtual())
141e7145dcbSDimitry Andric if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
142e7145dcbSDimitry Andric for (const auto &T : *TIV)
143e7145dcbSDimitry Andric Manglings.emplace_back(getMangledThunk(MD, T));
144e7145dcbSDimitry Andric }
145e7145dcbSDimitry Andric
146e7145dcbSDimitry Andric return Manglings;
147e7145dcbSDimitry Andric }
148e7145dcbSDimitry Andric
149e7145dcbSDimitry Andric private:
writeFuncOrVarNameCodegenNameGenerator::Implementation150e7145dcbSDimitry Andric bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
151e7145dcbSDimitry Andric if (MC->shouldMangleDeclName(D)) {
152e7145dcbSDimitry Andric if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
153e7145dcbSDimitry Andric MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
154e7145dcbSDimitry Andric else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
155e7145dcbSDimitry Andric MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
156e7145dcbSDimitry Andric else
157e7145dcbSDimitry Andric MC->mangleName(D, OS);
158e7145dcbSDimitry Andric return false;
159e7145dcbSDimitry Andric } else {
160e7145dcbSDimitry Andric IdentifierInfo *II = D->getIdentifier();
161e7145dcbSDimitry Andric if (!II)
162e7145dcbSDimitry Andric return true;
163e7145dcbSDimitry Andric OS << II->getName();
164e7145dcbSDimitry Andric return false;
165e7145dcbSDimitry Andric }
166e7145dcbSDimitry Andric }
167e7145dcbSDimitry Andric
writeObjCClassNameCodegenNameGenerator::Implementation168e7145dcbSDimitry Andric void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
169*9a199699SDimitry Andric OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
170e7145dcbSDimitry Andric OS << D->getObjCRuntimeNameAsString();
171e7145dcbSDimitry Andric }
172e7145dcbSDimitry Andric
getClassSymbolPrefixCodegenNameGenerator::Implementation173*9a199699SDimitry Andric static StringRef getClassSymbolPrefix(ObjCKind Kind, const ASTContext &Context) {
174*9a199699SDimitry Andric if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
175*9a199699SDimitry Andric return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
176*9a199699SDimitry Andric return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
177e7145dcbSDimitry Andric }
178e7145dcbSDimitry Andric
getMangledStructorCodegenNameGenerator::Implementation179e7145dcbSDimitry Andric std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
180e7145dcbSDimitry Andric std::string FrontendBuf;
181e7145dcbSDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf);
182e7145dcbSDimitry Andric
183e7145dcbSDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
184e7145dcbSDimitry Andric MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
185e7145dcbSDimitry Andric else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
186e7145dcbSDimitry Andric MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
187e7145dcbSDimitry Andric
188e7145dcbSDimitry Andric std::string BackendBuf;
189e7145dcbSDimitry Andric llvm::raw_string_ostream BOS(BackendBuf);
190e7145dcbSDimitry Andric
191e7145dcbSDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
192e7145dcbSDimitry Andric
193e7145dcbSDimitry Andric return BOS.str();
194e7145dcbSDimitry Andric }
195e7145dcbSDimitry Andric
getMangledThunkCodegenNameGenerator::Implementation196e7145dcbSDimitry Andric std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
197e7145dcbSDimitry Andric std::string FrontendBuf;
198e7145dcbSDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf);
199e7145dcbSDimitry Andric
200e7145dcbSDimitry Andric MC->mangleThunk(MD, T, FOS);
201e7145dcbSDimitry Andric
202e7145dcbSDimitry Andric std::string BackendBuf;
203e7145dcbSDimitry Andric llvm::raw_string_ostream BOS(BackendBuf);
204e7145dcbSDimitry Andric
205e7145dcbSDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
206e7145dcbSDimitry Andric
207e7145dcbSDimitry Andric return BOS.str();
208e7145dcbSDimitry Andric }
209e7145dcbSDimitry Andric };
210e7145dcbSDimitry Andric
CodegenNameGenerator(ASTContext & Ctx)211e7145dcbSDimitry Andric CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx)
212e7145dcbSDimitry Andric : Impl(new Implementation(Ctx)) {
213e7145dcbSDimitry Andric }
214e7145dcbSDimitry Andric
~CodegenNameGenerator()215e7145dcbSDimitry Andric CodegenNameGenerator::~CodegenNameGenerator() {
216e7145dcbSDimitry Andric }
217e7145dcbSDimitry Andric
writeName(const Decl * D,raw_ostream & OS)218e7145dcbSDimitry Andric bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
219e7145dcbSDimitry Andric return Impl->writeName(D, OS);
220e7145dcbSDimitry Andric }
221e7145dcbSDimitry Andric
getName(const Decl * D)222e7145dcbSDimitry Andric std::string CodegenNameGenerator::getName(const Decl *D) {
223e7145dcbSDimitry Andric return Impl->getName(D);
224e7145dcbSDimitry Andric }
225e7145dcbSDimitry Andric
getAllManglings(const Decl * D)226e7145dcbSDimitry Andric std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) {
227e7145dcbSDimitry Andric return Impl->getAllManglings(D);
228e7145dcbSDimitry Andric }
229