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