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