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