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 isUniqueInternalLinkageDecl(const NamedDecl * ND)110 virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) { 111 return false; 112 } 113 needsUniqueInternalLinkageNames()114 virtual void needsUniqueInternalLinkageNames() { } 115 116 // FIXME: consider replacing raw_ostream & with something like SmallString &. 117 void mangleName(GlobalDecl GD, raw_ostream &); 118 virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0; 119 virtual void mangleThunk(const CXXMethodDecl *MD, 120 const ThunkInfo &Thunk, 121 raw_ostream &) = 0; 122 virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, 123 const ThisAdjustment &ThisAdjustment, 124 raw_ostream &) = 0; 125 virtual void mangleReferenceTemporary(const VarDecl *D, 126 unsigned ManglingNumber, 127 raw_ostream &) = 0; 128 virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0; 129 virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0; 130 virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0; 131 virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&); 132 133 void mangleGlobalBlock(const BlockDecl *BD, 134 const NamedDecl *ID, 135 raw_ostream &Out); 136 void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, 137 const BlockDecl *BD, raw_ostream &Out); 138 void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT, 139 const BlockDecl *BD, raw_ostream &Out); 140 void mangleBlock(const DeclContext *DC, const BlockDecl *BD, 141 raw_ostream &Out); 142 143 void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &OS, 144 bool includePrefixByte = true, 145 bool includeCategoryNamespace = true); 146 void mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD, 147 raw_ostream &); 148 149 virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0; 150 151 virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0; 152 153 virtual void mangleDynamicAtExitDestructor(const VarDecl *D, 154 raw_ostream &) = 0; 155 156 virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl, 157 raw_ostream &Out) = 0; 158 159 virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl, 160 raw_ostream &Out) = 0; 161 162 /// Generates a unique string for an externally visible type for use with TBAA 163 /// or type uniquing. 164 /// TODO: Extend this to internal types by generating names that are unique 165 /// across translation units so it can be used with LTO. 166 virtual void mangleTypeName(QualType T, raw_ostream &) = 0; 167 168 /// @} 169 }; 170 171 class ItaniumMangleContext : public MangleContext { 172 public: 173 using DiscriminatorOverrideTy = 174 llvm::Optional<unsigned> (*)(ASTContext &, const NamedDecl *); ItaniumMangleContext(ASTContext & C,DiagnosticsEngine & D)175 explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D) 176 : MangleContext(C, D, MK_Itanium) {} 177 178 virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0; 179 virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0; 180 virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, 181 const CXXRecordDecl *Type, 182 raw_ostream &) = 0; 183 virtual void mangleItaniumThreadLocalInit(const VarDecl *D, 184 raw_ostream &) = 0; 185 virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D, 186 raw_ostream &) = 0; 187 188 virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D, 189 raw_ostream &) = 0; 190 virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D, 191 raw_ostream &) = 0; 192 193 virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0; 194 195 virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0; 196 197 // This has to live here, otherwise the CXXNameMangler won't have access to 198 // it. 199 virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0; classof(const MangleContext * C)200 static bool classof(const MangleContext *C) { 201 return C->getKind() == MK_Itanium; 202 } 203 204 static ItaniumMangleContext *create(ASTContext &Context, 205 DiagnosticsEngine &Diags); 206 static ItaniumMangleContext *create(ASTContext &Context, 207 DiagnosticsEngine &Diags, 208 DiscriminatorOverrideTy Discriminator); 209 }; 210 211 class MicrosoftMangleContext : public MangleContext { 212 public: MicrosoftMangleContext(ASTContext & C,DiagnosticsEngine & D)213 explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D) 214 : MangleContext(C, D, MK_Microsoft) {} 215 216 /// Mangle vftable symbols. Only a subset of the bases along the path 217 /// to the vftable are included in the name. It's up to the caller to pick 218 /// them correctly. 219 virtual void mangleCXXVFTable(const CXXRecordDecl *Derived, 220 ArrayRef<const CXXRecordDecl *> BasePath, 221 raw_ostream &Out) = 0; 222 223 /// Mangle vbtable symbols. Only a subset of the bases along the path 224 /// to the vbtable are included in the name. It's up to the caller to pick 225 /// them correctly. 226 virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, 227 ArrayRef<const CXXRecordDecl *> BasePath, 228 raw_ostream &Out) = 0; 229 230 virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD, 231 unsigned GuardNum, 232 raw_ostream &Out) = 0; 233 234 virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, 235 const MethodVFTableLocation &ML, 236 raw_ostream &Out) = 0; 237 238 virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD, 239 const CXXRecordDecl *DstRD, 240 raw_ostream &Out) = 0; 241 242 virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile, 243 bool IsUnaligned, uint32_t NumEntries, 244 raw_ostream &Out) = 0; 245 246 virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries, 247 raw_ostream &Out) = 0; 248 249 virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD, 250 CXXCtorType CT, uint32_t Size, 251 uint32_t NVOffset, int32_t VBPtrOffset, 252 uint32_t VBIndex, raw_ostream &Out) = 0; 253 254 virtual void mangleCXXRTTIBaseClassDescriptor( 255 const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, 256 uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0; 257 258 virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived, 259 raw_ostream &Out) = 0; 260 virtual void 261 mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived, 262 raw_ostream &Out) = 0; 263 264 virtual void 265 mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, 266 ArrayRef<const CXXRecordDecl *> BasePath, 267 raw_ostream &Out) = 0; 268 classof(const MangleContext * C)269 static bool classof(const MangleContext *C) { 270 return C->getKind() == MK_Microsoft; 271 } 272 273 static MicrosoftMangleContext *create(ASTContext &Context, 274 DiagnosticsEngine &Diags); 275 }; 276 277 class ASTNameGenerator { 278 public: 279 explicit ASTNameGenerator(ASTContext &Ctx); 280 ~ASTNameGenerator(); 281 282 /// Writes name for \p D to \p OS. 283 /// \returns true on failure, false on success. 284 bool writeName(const Decl *D, raw_ostream &OS); 285 286 /// \returns name for \p D 287 std::string getName(const Decl *D); 288 289 /// \returns all applicable mangled names. 290 /// For example C++ constructors/destructors can have multiple. 291 std::vector<std::string> getAllManglings(const Decl *D); 292 293 private: 294 class Implementation; 295 std::unique_ptr<Implementation> Impl; 296 }; 297 } 298 299 #endif 300