1218887Sdim//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim// Defines the C++ name mangling interface.
11218887Sdim//
12218887Sdim//===----------------------------------------------------------------------===//
13218887Sdim
14218887Sdim#ifndef LLVM_CLANG_AST_MANGLE_H
15218887Sdim#define LLVM_CLANG_AST_MANGLE_H
16218887Sdim
17218887Sdim#include "clang/AST/Type.h"
18218887Sdim#include "clang/Basic/ABI.h"
19218887Sdim#include "llvm/ADT/DenseMap.h"
20249423Sdim#include "llvm/ADT/SmallString.h"
21218887Sdim#include "llvm/ADT/StringRef.h"
22263508Sdim#include "llvm/Support/Casting.h"
23218887Sdim#include "llvm/Support/raw_ostream.h"
24218887Sdim
25218887Sdimnamespace clang {
26218887Sdim  class ASTContext;
27218887Sdim  class BlockDecl;
28218887Sdim  class CXXConstructorDecl;
29218887Sdim  class CXXDestructorDecl;
30218887Sdim  class CXXMethodDecl;
31218887Sdim  class FunctionDecl;
32218887Sdim  class NamedDecl;
33218887Sdim  class ObjCMethodDecl;
34218887Sdim  class VarDecl;
35218887Sdim  struct ThisAdjustment;
36218887Sdim  struct ThunkInfo;
37218887Sdim
38218887Sdim/// MangleBuffer - a convenient class for storing a name which is
39218887Sdim/// either the result of a mangling or is a constant string with
40218887Sdim/// external memory ownership.
41218887Sdimclass MangleBuffer {
42218887Sdimpublic:
43226633Sdim  void setString(StringRef Ref) {
44218887Sdim    String = Ref;
45218887Sdim  }
46218887Sdim
47226633Sdim  SmallVectorImpl<char> &getBuffer() {
48218887Sdim    return Buffer;
49218887Sdim  }
50218887Sdim
51226633Sdim  StringRef getString() const {
52218887Sdim    if (!String.empty()) return String;
53218887Sdim    return Buffer.str();
54218887Sdim  }
55218887Sdim
56226633Sdim  operator StringRef() const {
57218887Sdim    return getString();
58218887Sdim  }
59218887Sdim
60218887Sdimprivate:
61226633Sdim  StringRef String;
62234353Sdim  SmallString<256> Buffer;
63218887Sdim};
64218887Sdim
65218887Sdim/// MangleContext - Context for tracking state which persists across multiple
66218887Sdim/// calls to the C++ name mangler.
67218887Sdimclass MangleContext {
68263508Sdimpublic:
69263508Sdim  enum ManglerKind {
70263508Sdim    MK_Itanium,
71263508Sdim    MK_Microsoft
72263508Sdim  };
73263508Sdim
74263508Sdimprivate:
75234353Sdim  virtual void anchor();
76234353Sdim
77218887Sdim  ASTContext &Context;
78226633Sdim  DiagnosticsEngine &Diags;
79263508Sdim  const ManglerKind Kind;
80218887Sdim
81218887Sdim  llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
82218887Sdim  llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
83263508Sdim
84218887Sdimpublic:
85263508Sdim  ManglerKind getKind() const { return Kind; }
86263508Sdim
87218887Sdim  explicit MangleContext(ASTContext &Context,
88263508Sdim                         DiagnosticsEngine &Diags,
89263508Sdim                         ManglerKind Kind)
90263508Sdim      : Context(Context), Diags(Diags), Kind(Kind) {}
91218887Sdim
92218887Sdim  virtual ~MangleContext() { }
93218887Sdim
94218887Sdim  ASTContext &getASTContext() const { return Context; }
95218887Sdim
96226633Sdim  DiagnosticsEngine &getDiags() const { return Diags; }
97218887Sdim
98218887Sdim  virtual void startNewFunction() { LocalBlockIds.clear(); }
99218887Sdim
100218887Sdim  unsigned getBlockId(const BlockDecl *BD, bool Local) {
101218887Sdim    llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
102218887Sdim      = Local? LocalBlockIds : GlobalBlockIds;
103218887Sdim    std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
104218887Sdim      Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
105218887Sdim    return Result.first->second;
106218887Sdim  }
107218887Sdim
108218887Sdim  /// @name Mangler Entry Points
109218887Sdim  /// @{
110218887Sdim
111263508Sdim  bool shouldMangleDeclName(const NamedDecl *D);
112263508Sdim  virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
113263508Sdim
114263508Sdim  // FIXME: consider replacing raw_ostream & with something like SmallString &.
115263508Sdim  void mangleName(const NamedDecl *D, raw_ostream &);
116263508Sdim  virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0;
117218887Sdim  virtual void mangleThunk(const CXXMethodDecl *MD,
118218887Sdim                          const ThunkInfo &Thunk,
119226633Sdim                          raw_ostream &) = 0;
120218887Sdim  virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
121218887Sdim                                  const ThisAdjustment &ThisAdjustment,
122226633Sdim                                  raw_ostream &) = 0;
123218887Sdim  virtual void mangleReferenceTemporary(const VarDecl *D,
124226633Sdim                                        raw_ostream &) = 0;
125226633Sdim  virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
126226633Sdim  virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
127218887Sdim  virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
128226633Sdim                             raw_ostream &) = 0;
129218887Sdim  virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
130226633Sdim                             raw_ostream &) = 0;
131218887Sdim
132218887Sdim  void mangleGlobalBlock(const BlockDecl *BD,
133239462Sdim                         const NamedDecl *ID,
134226633Sdim                         raw_ostream &Out);
135218887Sdim  void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
136226633Sdim                       const BlockDecl *BD, raw_ostream &Out);
137218887Sdim  void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
138226633Sdim                       const BlockDecl *BD, raw_ostream &Out);
139218887Sdim  void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
140226633Sdim                   raw_ostream &Out);
141218887Sdim
142263508Sdim  void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &);
143218887Sdim
144263508Sdim  virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
145263508Sdim
146263508Sdim  virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;
147263508Sdim
148263508Sdim  virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
149263508Sdim                                             raw_ostream &) = 0;
150263508Sdim
151263508Sdim  /// Generates a unique string for an externally visible type for use with TBAA
152263508Sdim  /// or type uniquing.
153263508Sdim  /// TODO: Extend this to internal types by generating names that are unique
154263508Sdim  /// across translation units so it can be used with LTO.
155263508Sdim  virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
156263508Sdim
157263508Sdim  /// @}
158263508Sdim};
159263508Sdim
160263508Sdimclass ItaniumMangleContext : public MangleContext {
161263508Sdimpublic:
162263508Sdim  explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
163263508Sdim      : MangleContext(C, D, MK_Itanium) {}
164263508Sdim
165263508Sdim  virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
166263508Sdim  virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
167263508Sdim  virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
168263508Sdim                                   const CXXRecordDecl *Type,
169263508Sdim                                   raw_ostream &) = 0;
170251662Sdim  virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
171263508Sdim                                            raw_ostream &) = 0;
172251662Sdim  virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
173263508Sdim                                               raw_ostream &) = 0;
174263508Sdim
175263508Sdim  static bool classof(const MangleContext *C) {
176263508Sdim    return C->getKind() == MK_Itanium;
177251662Sdim  }
178251662Sdim
179263508Sdim  static ItaniumMangleContext *create(ASTContext &Context,
180263508Sdim                                      DiagnosticsEngine &Diags);
181218887Sdim};
182218887Sdim
183263508Sdimclass MicrosoftMangleContext : public MangleContext {
184263508Sdimpublic:
185263508Sdim  explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
186263508Sdim      : MangleContext(C, D, MK_Microsoft) {}
187218887Sdim
188263508Sdim  /// \brief Mangle vftable symbols.  Only a subset of the bases along the path
189263508Sdim  /// to the vftable are included in the name.  It's up to the caller to pick
190263508Sdim  /// them correctly.
191263508Sdim  virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
192263508Sdim                                ArrayRef<const CXXRecordDecl *> BasePath,
193263508Sdim                                raw_ostream &Out) = 0;
194263508Sdim
195263508Sdim  /// \brief Mangle vbtable symbols.  Only a subset of the bases along the path
196263508Sdim  /// to the vbtable are included in the name.  It's up to the caller to pick
197263508Sdim  /// them correctly.
198263508Sdim  virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
199263508Sdim                                ArrayRef<const CXXRecordDecl *> BasePath,
200263508Sdim                                raw_ostream &Out) = 0;
201263508Sdim
202263508Sdim  virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
203263508Sdim                                        uint64_t OffsetInVFTable,
204263508Sdim                                        raw_ostream &) = 0;
205263508Sdim
206263508Sdim  static bool classof(const MangleContext *C) {
207263508Sdim    return C->getKind() == MK_Microsoft;
208263508Sdim  }
209263508Sdim
210263508Sdim  static MicrosoftMangleContext *create(ASTContext &Context,
211263508Sdim                                        DiagnosticsEngine &Diags);
212263508Sdim};
213218887Sdim}
214218887Sdim
215218887Sdim#endif
216