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