Mangle.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Defines the C++ name mangling interface.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_CLANG_AST_MANGLE_H
  18. #define LLVM_CLANG_AST_MANGLE_H
  19. #include "clang/AST/Decl.h"
  20. #include "clang/AST/GlobalDecl.h"
  21. #include "clang/AST/Type.h"
  22. #include "clang/Basic/ABI.h"
  23. #include "llvm/ADT/DenseMap.h"
  24. #include "llvm/Support/Casting.h"
  25. #include <optional>
  26. namespace llvm {
  27. class raw_ostream;
  28. }
  29. namespace clang {
  30. class ASTContext;
  31. class BlockDecl;
  32. class CXXConstructorDecl;
  33. class CXXDestructorDecl;
  34. class CXXMethodDecl;
  35. class FunctionDecl;
  36. struct MethodVFTableLocation;
  37. class NamedDecl;
  38. class ObjCMethodDecl;
  39. class StringLiteral;
  40. struct ThisAdjustment;
  41. struct ThunkInfo;
  42. class VarDecl;
  43. /// MangleContext - Context for tracking state which persists across multiple
  44. /// calls to the C++ name mangler.
  45. class MangleContext {
  46. public:
  47. enum ManglerKind {
  48. MK_Itanium,
  49. MK_Microsoft
  50. };
  51. private:
  52. virtual void anchor();
  53. ASTContext &Context;
  54. DiagnosticsEngine &Diags;
  55. const ManglerKind Kind;
  56. /// For aux target. If true, uses mangling number for aux target from
  57. /// ASTContext.
  58. bool IsAux = false;
  59. llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
  60. llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
  61. llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
  62. llvm::DenseMap<const FunctionDecl*, unsigned> FuncAnonStructSize;
  63. public:
  64. ManglerKind getKind() const { return Kind; }
  65. bool isAux() const { return IsAux; }
  66. explicit MangleContext(ASTContext &Context, DiagnosticsEngine &Diags,
  67. ManglerKind Kind, bool IsAux = false)
  68. : Context(Context), Diags(Diags), Kind(Kind), IsAux(IsAux) {}
  69. virtual ~MangleContext() { }
  70. ASTContext &getASTContext() const { return Context; }
  71. DiagnosticsEngine &getDiags() const { return Diags; }
  72. virtual void startNewFunction() { LocalBlockIds.clear(); }
  73. unsigned getBlockId(const BlockDecl *BD, bool Local) {
  74. llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
  75. = Local? LocalBlockIds : GlobalBlockIds;
  76. std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
  77. Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
  78. return Result.first->second;
  79. }
  80. uint64_t getAnonymousStructId(const NamedDecl *D,
  81. const FunctionDecl *FD = nullptr) {
  82. auto FindResult = AnonStructIds.find(D);
  83. if (FindResult != AnonStructIds.end())
  84. return FindResult->second;
  85. // If FunctionDecl is passed in, the anonymous structID will be per-function
  86. // based.
  87. unsigned Id = FD ? FuncAnonStructSize[FD]++ : AnonStructIds.size();
  88. std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool>
  89. Result = AnonStructIds.insert(std::make_pair(D, Id));
  90. return Result.first->second;
  91. }
  92. uint64_t getAnonymousStructIdForDebugInfo(const NamedDecl *D) {
  93. llvm::DenseMap<const NamedDecl *, uint64_t>::iterator Result =
  94. AnonStructIds.find(D);
  95. // The decl should already be inserted, but return 0 in case it is not.
  96. if (Result == AnonStructIds.end())
  97. return 0;
  98. return Result->second;
  99. }
  100. virtual std::string getLambdaString(const CXXRecordDecl *Lambda) = 0;
  101. /// @name Mangler Entry Points
  102. /// @{
  103. bool shouldMangleDeclName(const NamedDecl *D);
  104. virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
  105. virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;
  106. virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) {
  107. return false;
  108. }
  109. virtual void needsUniqueInternalLinkageNames() { }
  110. // FIXME: consider replacing raw_ostream & with something like SmallString &.
  111. void mangleName(GlobalDecl GD, raw_ostream &);
  112. virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0;
  113. virtual void mangleThunk(const CXXMethodDecl *MD,
  114. const ThunkInfo &Thunk,
  115. raw_ostream &) = 0;
  116. virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
  117. const ThisAdjustment &ThisAdjustment,
  118. raw_ostream &) = 0;
  119. virtual void mangleReferenceTemporary(const VarDecl *D,
  120. unsigned ManglingNumber,
  121. raw_ostream &) = 0;
  122. virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
  123. virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
  124. virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
  125. virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&);
  126. void mangleGlobalBlock(const BlockDecl *BD,
  127. const NamedDecl *ID,
  128. raw_ostream &Out);
  129. void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
  130. const BlockDecl *BD, raw_ostream &Out);
  131. void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
  132. const BlockDecl *BD, raw_ostream &Out);
  133. void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
  134. raw_ostream &Out);
  135. void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &OS,
  136. bool includePrefixByte = true,
  137. bool includeCategoryNamespace = true);
  138. void mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,
  139. raw_ostream &);
  140. virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
  141. virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;
  142. virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
  143. raw_ostream &) = 0;
  144. virtual void mangleSEHFilterExpression(GlobalDecl EnclosingDecl,
  145. raw_ostream &Out) = 0;
  146. virtual void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl,
  147. raw_ostream &Out) = 0;
  148. /// Generates a unique string for an externally visible type for use with TBAA
  149. /// or type uniquing.
  150. /// TODO: Extend this to internal types by generating names that are unique
  151. /// across translation units so it can be used with LTO.
  152. virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
  153. /// @}
  154. };
  155. class ItaniumMangleContext : public MangleContext {
  156. public:
  157. using DiscriminatorOverrideTy =
  158. std::optional<unsigned> (*)(ASTContext &, const NamedDecl *);
  159. explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
  160. bool IsAux = false)
  161. : MangleContext(C, D, MK_Itanium, IsAux) {}
  162. virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
  163. virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
  164. virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
  165. const CXXRecordDecl *Type,
  166. raw_ostream &) = 0;
  167. virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
  168. raw_ostream &) = 0;
  169. virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
  170. raw_ostream &) = 0;
  171. virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
  172. raw_ostream &) = 0;
  173. virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
  174. raw_ostream &) = 0;
  175. virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
  176. virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;
  177. virtual void mangleModuleInitializer(const Module *Module, raw_ostream &) = 0;
  178. // This has to live here, otherwise the CXXNameMangler won't have access to
  179. // it.
  180. virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;
  181. static bool classof(const MangleContext *C) {
  182. return C->getKind() == MK_Itanium;
  183. }
  184. static ItaniumMangleContext *
  185. create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false);
  186. static ItaniumMangleContext *create(ASTContext &Context,
  187. DiagnosticsEngine &Diags,
  188. DiscriminatorOverrideTy Discriminator,
  189. bool IsAux = false);
  190. };
  191. class MicrosoftMangleContext : public MangleContext {
  192. public:
  193. explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D,
  194. bool IsAux = false)
  195. : MangleContext(C, D, MK_Microsoft, IsAux) {}
  196. /// Mangle vftable symbols. Only a subset of the bases along the path
  197. /// to the vftable are included in the name. It's up to the caller to pick
  198. /// them correctly.
  199. virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
  200. ArrayRef<const CXXRecordDecl *> BasePath,
  201. raw_ostream &Out) = 0;
  202. /// Mangle vbtable symbols. Only a subset of the bases along the path
  203. /// to the vbtable are included in the name. It's up to the caller to pick
  204. /// them correctly.
  205. virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
  206. ArrayRef<const CXXRecordDecl *> BasePath,
  207. raw_ostream &Out) = 0;
  208. virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD,
  209. unsigned GuardNum,
  210. raw_ostream &Out) = 0;
  211. virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
  212. const MethodVFTableLocation &ML,
  213. raw_ostream &Out) = 0;
  214. virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
  215. const CXXRecordDecl *DstRD,
  216. raw_ostream &Out) = 0;
  217. virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
  218. bool IsUnaligned, uint32_t NumEntries,
  219. raw_ostream &Out) = 0;
  220. virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
  221. raw_ostream &Out) = 0;
  222. virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
  223. CXXCtorType CT, uint32_t Size,
  224. uint32_t NVOffset, int32_t VBPtrOffset,
  225. uint32_t VBIndex, raw_ostream &Out) = 0;
  226. virtual void mangleCXXRTTIBaseClassDescriptor(
  227. const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
  228. uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;
  229. virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
  230. raw_ostream &Out) = 0;
  231. virtual void
  232. mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
  233. raw_ostream &Out) = 0;
  234. virtual void
  235. mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
  236. ArrayRef<const CXXRecordDecl *> BasePath,
  237. raw_ostream &Out) = 0;
  238. static bool classof(const MangleContext *C) {
  239. return C->getKind() == MK_Microsoft;
  240. }
  241. static MicrosoftMangleContext *
  242. create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false);
  243. };
  244. class ASTNameGenerator {
  245. public:
  246. explicit ASTNameGenerator(ASTContext &Ctx);
  247. ~ASTNameGenerator();
  248. /// Writes name for \p D to \p OS.
  249. /// \returns true on failure, false on success.
  250. bool writeName(const Decl *D, raw_ostream &OS);
  251. /// \returns name for \p D
  252. std::string getName(const Decl *D);
  253. /// \returns all applicable mangled names.
  254. /// For example C++ constructors/destructors can have multiple.
  255. std::vector<std::string> getAllManglings(const Decl *D);
  256. private:
  257. class Implementation;
  258. std::unique_ptr<Implementation> Impl;
  259. };
  260. }
  261. #endif
  262. #ifdef __GNUC__
  263. #pragma GCC diagnostic pop
  264. #endif