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