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