clang  6.0.0svn
CodegenNameGenerator.cpp
Go to the documentation of this file.
1 //===- CodegenNameGenerator.cpp - Codegen name generation -----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Determines the name that the symbol will get for code generation.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/Mangle.h"
20 #include "clang/Basic/TargetInfo.h"
21 #include "llvm/IR/DataLayout.h"
22 #include "llvm/IR/Mangler.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 using namespace clang;
26 using namespace clang::index;
27 
29  std::unique_ptr<MangleContext> MC;
30  llvm::DataLayout DL;
31 
33  : MC(Ctx.createMangleContext()),
34  DL(Ctx.getTargetInfo().getDataLayout()) {}
35 
36  bool writeName(const Decl *D, raw_ostream &OS) {
37  // First apply frontend mangling.
38  SmallString<128> FrontendBuf;
39  llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
40  if (auto *FD = dyn_cast<FunctionDecl>(D)) {
41  if (FD->isDependentContext())
42  return true;
43  if (writeFuncOrVarName(FD, FrontendBufOS))
44  return true;
45  } else if (auto *VD = dyn_cast<VarDecl>(D)) {
46  if (writeFuncOrVarName(VD, FrontendBufOS))
47  return true;
48  } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
49  MC->mangleObjCMethodNameWithoutSize(MD, OS);
50  return false;
51  } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
52  writeObjCClassName(ID, FrontendBufOS);
53  } else {
54  return true;
55  }
56 
57  // Now apply backend mangling.
58  llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
59  return false;
60  }
61 
62  std::string getName(const Decl *D) {
63  std::string Name;
64  {
65  llvm::raw_string_ostream OS(Name);
66  writeName(D, OS);
67  }
68  return Name;
69  }
70 
71  enum ObjCKind {
74  };
75 
76  std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
77  StringRef ClassName;
78  if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
79  ClassName = OID->getObjCRuntimeNameAsString();
80  else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))
81  ClassName = OID->getObjCRuntimeNameAsString();
82 
83  if (ClassName.empty())
84  return {};
85 
86  auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
87  SmallString<40> Mangled;
88  auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
89  llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
90  return Mangled.str();
91  };
92 
93  return {
94  Mangle(ObjCClass, ClassName),
95  Mangle(ObjCMetaclass, ClassName),
96  };
97  }
98 
99  std::vector<std::string> getAllManglings(const Decl *D) {
100  if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
101  return getAllManglings(OCD);
102 
103  if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
104  return {};
105 
106  const NamedDecl *ND = cast<NamedDecl>(D);
107 
108  ASTContext &Ctx = ND->getASTContext();
109  std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
110 
111  std::vector<std::string> Manglings;
112 
113  auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
114  auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
115  /*IsCSSMethod=*/true);
116  auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
117  return CC == DefaultCC;
118  };
119 
120  if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
121  Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
122 
123  if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
124  if (!CD->getParent()->isAbstract())
125  Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
126 
127  if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
128  if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
129  if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
130  Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
131  } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
132  Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
133  if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
134  Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
135  if (DD->isVirtual())
136  Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
137  }
138  } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
139  Manglings.emplace_back(getName(ND));
140  if (MD->isVirtual())
141  if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
142  for (const auto &T : *TIV)
143  Manglings.emplace_back(getMangledThunk(MD, T));
144  }
145 
146  return Manglings;
147  }
148 
149 private:
150  bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
151  if (MC->shouldMangleDeclName(D)) {
152  if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
153  MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
154  else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
155  MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
156  else
157  MC->mangleName(D, OS);
158  return false;
159  } else {
160  IdentifierInfo *II = D->getIdentifier();
161  if (!II)
162  return true;
163  OS << II->getName();
164  return false;
165  }
166  }
167 
168  void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
169  OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
170  OS << D->getObjCRuntimeNameAsString();
171  }
172 
173  static StringRef getClassSymbolPrefix(ObjCKind Kind, const ASTContext &Context) {
174  if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
175  return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
176  return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
177  }
178 
179  std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
180  std::string FrontendBuf;
181  llvm::raw_string_ostream FOS(FrontendBuf);
182 
183  if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
184  MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
185  else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
186  MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
187 
188  std::string BackendBuf;
189  llvm::raw_string_ostream BOS(BackendBuf);
190 
191  llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
192 
193  return BOS.str();
194  }
195 
196  std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
197  std::string FrontendBuf;
198  llvm::raw_string_ostream FOS(FrontendBuf);
199 
200  MC->mangleThunk(MD, T, FOS);
201 
202  std::string BackendBuf;
203  llvm::raw_string_ostream BOS(BackendBuf);
204 
205  llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
206 
207  return BOS.str();
208  }
209 };
210 
212  : Impl(new Implementation(Ctx)) {
213 }
214 
216 }
217 
218 bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
219  return Impl->writeName(D, OS);
220 }
221 
222 std::string CodegenNameGenerator::getName(const Decl *D) {
223  return Impl->getName(D);
224 }
225 
226 std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) {
227  return Impl->getAllManglings(D);
228 }
Defines the clang::ASTContext interface.
Complete object ctor.
Definition: ABI.h:26
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Default closure variant of a ctor.
Definition: ABI.h:30
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:265
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:149
The this pointer adjustment as well as an optional return adjustment for a thunk. ...
Definition: ABI.h:179
Base object ctor.
Definition: ABI.h:27
ObjCContainerDecl - Represents a container for method declarations.
Definition: DeclObjC.h:986
std::vector< std::string > getAllManglings(const ObjCContainerDecl *OCD)
Deleting dtor.
Definition: ABI.h:35
std::vector< std::string > getAllManglings(const Decl *D)
This can return multiple mangled names when applicable, e.g.
static bool hasDefaultCXXMethodCC(ASTContext &Context, const CXXMethodDecl *MD)
bool writeName(const Decl *D, raw_ostream &OS)
Represents an ObjC class declaration.
Definition: DeclObjC.h:1191
Represents a prototype with parameter type info, e.g.
Definition: Type.h:3270
bool isGNUFamily() const
Is this runtime basically of the GNU family of runtimes?
Definition: ObjCRuntime.h:117
const FunctionProtoType * T
Base object dtor.
Definition: ABI.h:37
clang::ObjCRuntime ObjCRuntime
Definition: LangOptions.h:117
Kind
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:365
std::string getName(const Decl *D)
Version of writeName function that returns a string.
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1964
Complete object dtor.
Definition: ABI.h:36
StringRef getName() const
Return the actual identifier string.
CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod) const
Retrieves the default calling convention for the current target.
Dataflow Directional Tag Classes.
std::vector< std::string > getAllManglings(const Decl *D)
StringRef getObjCRuntimeNameAsString() const
Produce a name to be used for class&#39;s metadata.
Definition: DeclObjC.cpp:1497
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Defines the clang::TargetInfo interface.
NamedDecl - This represents a decl with a name.
Definition: Decl.h:245
const LangOptions & getLangOpts() const
Definition: ASTContext.h:688