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