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