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