Clang Project

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