clang: lib/AST/Mangle.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

23#include "llvm/ADT/StringExtras.h"

24#include "llvm/IR/DataLayout.h"

25#include "llvm/IR/Mangler.h"

26#include "llvm/Support/ErrorHandling.h"

27#include "llvm/Support/Format.h"

28#include "llvm/Support/raw_ostream.h"

29

30using namespace clang;

31

32

33

34

36 StringRef Outer,

38 raw_ostream &Out) {

39 unsigned discriminator = Context.getBlockId(BD, true);

40 if (discriminator == 0)

41 Out << "__" << Outer << "_block_invoke";

42 else

43 Out << "__" << Outer << "_block_invoke_" << discriminator+1;

44}

45

46void MangleContext::anchor() { }

47

56

58 if (const FunctionDecl *FD = dyn_cast(ND))

59 return FD->isExternC();

60 if (const VarDecl *VD = dyn_cast(ND))

61 return VD->isExternC();

62 return false;

63}

64

68 const llvm::Triple &Triple = TI.getTriple();

69

70

71

72 if (Triple.isWasm())

73 if (const FunctionDecl *FD = dyn_cast(ND))

74 if (FD->isMain() && FD->getNumParams() == 2)

76

77 if (!Triple.isOSWindows() || !Triple.isX86())

79

81 TI.getCXXABI() == TargetCXXABI::Microsoft)

83

84 const FunctionDecl *FD = dyn_cast(ND);

85 if (!FD)

88

90

92 switch (CC) {

93 default:

101 }

102}

103

106

109 return true;

110

111

112

114 return true;

115

116

117

120 return true;

121

122

124 return false;

125

126

127

128 if (D->hasAttr())

129 return true;

130

131

132 if (isa(D))

133 return true;

134

136}

137

141

142

143

144 if (const AsmLabelAttr *ALA = D->getAttr()) {

145

146

147

148

149 if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {

150 Out << ALA->getLabel();

151 return;

152 }

153

154

155

156

157

158

159 StringRef UserLabelPrefix =

161#ifndef NDEBUG

162 char GlobalPrefix =

163 llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString())

164 .getGlobalPrefix();

165 assert((UserLabelPrefix.empty() && !GlobalPrefix) ||

166 (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix));

167#endif

168 if (!UserLabelPrefix.empty())

169 Out << '\01';

170

171 Out << ALA->getLabel();

172 return;

173 }

174

175 if (auto *GD = dyn_cast(D))

177

179

181 Out << "__main_argc_argv";

182 return;

183 }

184

187 if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {

188 if (const ObjCMethodDecl *OMD = dyn_cast(D))

190 else

192 return;

193 }

194

195 Out << '\01';

197 Out << '_';

199 Out << '@';

202 Out << "__regcall4__";

203 else

204 Out << "__regcall3__";

205 }

206

207 if (!MCXX)

208 Out << D->getIdentifier()->getName();

209 else if (const ObjCMethodDecl *OMD = dyn_cast(D))

211 else

213

216 const FunctionProtoType *Proto = dyn_cast(FT);

218 Out << '@';

219 Out << '@';

220 if (!Proto) {

221 Out << '0';

222 return;

223 }

224 assert(!Proto->isVariadic());

225 unsigned ArgWords = 0;

226 if (const CXXMethodDecl *MD = dyn_cast(FD))

227 if (MD->isImplicitObjectMemberFunction())

228 ++ArgWords;

230 for (const auto &AT : Proto->param_types()) {

231

232

233

234 if (AT->isIncompleteType())

235 break;

236

238 DefaultPtrWidth;

239 }

240 Out << ((DefaultPtrWidth / 8) * ArgWords);

241}

242

244

245

247 Out << llvm::format("_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_",

248 P.Part1, P.Part2, P.Part3);

249 unsigned I = 0;

250 for (uint8_t C : P.Part4And5) {

251 Out << llvm::format("%02" PRIx8, C);

252 if (++I == 2)

253 Out << "_";

254 }

255}

256

259 raw_ostream &Out) {

260 unsigned discriminator = getBlockId(BD, false);

261 if (ID) {

264 else {

265 Out << ID->getIdentifier()->getName();

266 }

267 }

268 if (discriminator == 0)

269 Out << "_block_invoke";

270 else

271 Out << "_block_invoke_" << discriminator+1;

272}

273

276 raw_ostream &ResStream) {

278 llvm::raw_svector_ostream Out(Buffer);

281}

282

285 raw_ostream &ResStream) {

287 llvm::raw_svector_ostream Out(Buffer);

290}

291

293 raw_ostream &Out) {

294 assert(!isa(DC) && !isa(DC));

295

297 llvm::raw_svector_ostream Stream(Buffer);

298 if (const ObjCMethodDecl *Method = dyn_cast(DC)) {

300 } else {

301 assert((isa(DC) || isa(DC)) &&

302 "expected a NamedDecl or BlockDecl");

303 for (; isa_and_nonnull(DC); DC = DC->getParent())

304 (void)getBlockId(cast(DC), true);

305 assert((isa(DC) || isa(DC)) &&

306 "expected a TranslationUnitDecl or a NamedDecl");

307 if (const auto *CD = dyn_cast(DC))

309 else if (const auto *DD = dyn_cast(DC))

311 else if (auto ND = dyn_cast(DC)) {

313 Stream << ND->getIdentifier()->getName();

314 else {

315

316

317

318

319

321 }

322 }

323 }

325}

326

328 raw_ostream &OS,

329 bool includePrefixByte,

330 bool includeCategoryNamespace) {

332

333

334

335

338

339 if (includeCategoryNamespace) {

341 OS << category->getName();

342 }

343 OS << '_';

344

346 for (unsigned slotIndex = 0,

347 numArgs = selector.getNumArgs(),

348 slotEnd = std::max(numArgs, 1U);

349 slotIndex != slotEnd; ++slotIndex) {

350 if (auto name = selector.getIdentifierInfoForSlot(slotIndex))

351 OS << name->getName();

352

353

354

355

356 if (numArgs)

357 OS << '_';

358 }

359

360 return;

361 }

362

363

364 if (includePrefixByte) {

365 OS << '\01';

366 }

368 if (const auto *CID = MD->getCategory()) {

369 OS << CID->getClassInterface()->getName();

370 if (includeCategoryNamespace) {

371 OS << '(' << *CID << ')';

372 }

373 } else if (const auto *CD =

375 OS << CD->getName();

376 } else {

377 llvm_unreachable("Unexpected ObjC method decl context");

378 }

379 OS << ' ';

381 OS << ']';

382}

383

385 raw_ostream &Out) {

387 llvm::raw_svector_ostream OS(Name);

388

390 true);

391 Out << OS.str().size() << OS.str();

392}

393

395 std::unique_ptr MC;

396 llvm::DataLayout DL;

397

398public:

400 : MC(Ctx.createMangleContext()),

401 DL(Ctx.getTargetInfo().getDataLayoutString()) {}

402

404

406 llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);

407 if (auto *FD = dyn_cast(D)) {

408 if (FD->isDependentContext())

409 return true;

410 if (writeFuncOrVarName(FD, FrontendBufOS))

411 return true;

412 } else if (auto *VD = dyn_cast(D)) {

413 if (writeFuncOrVarName(VD, FrontendBufOS))

414 return true;

415 } else if (auto *MD = dyn_cast(D)) {

416 MC->mangleObjCMethodName(MD, OS, false,

417 true);

418 return false;

419 } else if (auto *ID = dyn_cast(D)) {

420 writeObjCClassName(ID, FrontendBufOS);

421 } else {

422 return true;

423 }

424

425

426 llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);

427 return false;

428 }

429

431 std::string Name;

432 {

433 llvm::raw_string_ostream OS(Name);

435 }

436 return Name;

437 }

438

442 };

443

447 return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";

448 return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";

449 }

450

452 StringRef ClassName;

453 if (const auto *OID = dyn_cast(OCD))

454 ClassName = OID->getObjCRuntimeNameAsString();

455 else if (const auto *OID = dyn_cast(OCD))

456 ClassName = OID->getObjCRuntimeNameAsString();

457

458 if (ClassName.empty())

459 return {};

460

461 auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {

464 llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);

465 return std::string(Mangled);

466 };

467

468 return {

471 };

472 }

473

475 if (const auto *OCD = dyn_cast(D))

477

478 if (!(isa(D) || isa(D)))

479 return {};

480

481 const NamedDecl *ND = cast(D);

482

485

486 std::vectorstd::string Manglings;

487

489 auto DefaultCC = C.getDefaultCallingConvention(false,

490 true);

491 auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv();

492 return CC == DefaultCC;

493 };

494

495 if (const auto *CD = dyn_cast_or_null(ND)) {

496 Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));

497

499 if (!CD->getParent()->isAbstract())

500 Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));

501

503 if (CD->hasAttr() && CD->isDefaultConstructor())

506 } else if (const auto *DD = dyn_cast_or_null(ND)) {

507 Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));

509 Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));

510 if (DD->isVirtual())

511 Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));

512 }

513 } else if (const auto *MD = dyn_cast_or_null(ND)) {

514 Manglings.emplace_back(getName(ND));

515 if (MD->isVirtual()) {

517 for (const auto &T : *TIV) {

518 std::string ThunkName;

519 std::string ContextualizedName =

520 getMangledThunk(MD, T, false);

522 ThunkName = getMangledThunk(MD, T, true);

523 else

524 ThunkName = ContextualizedName;

525 Manglings.emplace_back(ThunkName);

526 }

527 }

528 }

529 }

530

531 return Manglings;

532 }

533

534private:

535 bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {

536 if (MC->shouldMangleDeclName(D)) {

538 if (const auto *CtorD = dyn_cast(D))

540 else if (const auto *DtorD = dyn_cast(D))

542 else if (D->hasAttr())

544 else

546 MC->mangleName(GD, OS);

547 return false;

548 } else {

550 if (!II)

551 return true;

553 return false;

554 }

555 }

556

557 void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {

559 OS << D->getObjCRuntimeNameAsString();

560 }

561

562 std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {

563 std::string FrontendBuf;

564 llvm::raw_string_ostream FOS(FrontendBuf);

565

567 if (const auto *CD = dyn_cast_or_null(ND))

569 else if (const auto *DD = dyn_cast_or_null(ND))

571 MC->mangleName(GD, FOS);

572

573 std::string BackendBuf;

574 llvm::raw_string_ostream BOS(BackendBuf);

575

576 llvm::Mangler::getNameWithPrefix(BOS, FrontendBuf, DL);

577

578 return BackendBuf;

579 }

580

582 bool ElideOverrideInfo) {

583 std::string FrontendBuf;

584 llvm::raw_string_ostream FOS(FrontendBuf);

585

586 MC->mangleThunk(MD, T, ElideOverrideInfo, FOS);

587

588 std::string BackendBuf;

589 llvm::raw_string_ostream BOS(BackendBuf);

590

591 llvm::Mangler::getNameWithPrefix(BOS, FrontendBuf, DL);

592

593 return BackendBuf;

594 }

595};

596

599

601

603 return Impl->writeName(D, OS);

604}

605

607 return Impl->getName(D);

608}

609

611 return Impl->getAllManglings(D);

612}

Enums/classes describing ABI related information about constructors, destructors and thunks.

Defines the clang::ASTContext interface.

static bool hasDefaultCXXMethodCC(ASTContext &Context, const CXXMethodDecl *MD)

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the C++ template declaration subclasses.

Defines the clang::Expr interface and subclasses for C++ expressions.

static void mangleFunctionBlock(MangleContext &Context, StringRef Outer, const BlockDecl *BD, raw_ostream &Out)

static bool isExternC(const NamedDecl *ND)

static CCMangling getCallingConvMangling(const ASTContext &Context, const NamedDecl *ND)

std::string getName(const Decl *D)

std::vector< std::string > getAllManglings(const Decl *D)

static StringRef getClassSymbolPrefix(ObjCKind Kind, const ASTContext &Context)

bool writeName(const Decl *D, raw_ostream &OS)

Implementation(ASTContext &Ctx)

std::vector< std::string > getAllManglings(const ObjCContainerDecl *OCD)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

MangleContext * createMangleContext(const TargetInfo *T=nullptr)

If T is null pointer, assume the target in ASTContext.

const LangOptions & getLangOpts() const

bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl, StringRef MangledName)

VTableContextBase * getVTableContext()

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

const TargetInfo & getTargetInfo() const

std::string getName(const Decl *D)

ASTNameGenerator(ASTContext &Ctx)

bool writeName(const Decl *D, raw_ostream &OS)

Writes name for D to OS.

std::vector< std::string > getAllManglings(const Decl *D)

Represents a block literal declaration, which is like an unnamed FunctionDecl.

Represents a C++ constructor within a class.

Represents a C++ destructor within a class.

Represents a static or instance method of a struct/union/class.

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

DeclContext * getParent()

getParent - Returns the containing DeclContext.

Decl - This represents one declaration (or definition), e.g.

ASTContext & getASTContext() const LLVM_READONLY

DeclContext * getDeclContext()

Module * getOwningModuleForLinkage() const

Get the module that owns this declaration for linkage purposes.

Represents a function declaration or definition.

Represents a prototype with parameter type info, e.g.

FunctionType - C99 6.7.5.3 - Function Declarators.

CallingConv getCallConv() const

GlobalDecl - represents a global declaration.

const Decl * getDecl() const

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

clang::ObjCRuntime ObjCRuntime

Parts getParts() const

Get the decomposed parts of this declaration.

MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...

void mangleBlock(const DeclContext *DC, const BlockDecl *BD, raw_ostream &Out)

unsigned getBlockId(const BlockDecl *BD, bool Local)

void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, raw_ostream &Out)

ASTContext & getASTContext() const

void mangleGlobalBlock(const BlockDecl *BD, const NamedDecl *ID, raw_ostream &Out)

virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND)

bool shouldMangleDeclName(const NamedDecl *D)

void mangleName(GlobalDecl GD, raw_ostream &)

void mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD, raw_ostream &)

virtual void mangleCXXName(GlobalDecl GD, raw_ostream &)=0

virtual bool shouldMangleCXXName(const NamedDecl *D)=0

void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &OS, bool includePrefixByte=true, bool includeCategoryNamespace=true)

void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT, const BlockDecl *BD, raw_ostream &Out)

virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream &)

This represents a decl that may have a name.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

ObjCContainerDecl - Represents a container for method declarations.

Represents an ObjC class declaration.

ObjCMethodDecl - Represents an instance or class method declaration.

Selector getSelector() const

bool isInstanceMethod() const

ObjCCategoryDecl * getCategory()

If this method is declared or implemented in a category, return that category.

bool isClassMethod() const

ObjCInterfaceDecl * getClassInterface()

The basic abstraction for the target Objective-C runtime.

bool isGNUFamily() const

Is this runtime basically of the GNU family of runtimes?

A (possibly-)qualified type.

void print(llvm::raw_ostream &OS) const

Prints the full selector name (e.g. "foo:bar:").

bool isMicrosoft() const

Is this ABI an MSVC-compatible ABI?

bool isItaniumFamily() const

Does this ABI generally fall into the Itanium family of ABIs?

Exposes information about the current target.

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

uint64_t getPointerWidth(LangAS AddrSpace) const

Return the width of pointers on this target, for the specified address space.

const char * getUserLabelPrefix() const

Returns the default value of the USER_LABEL_PREFIX macro, which is the prefix given to user symbols b...

TargetCXXABI getCXXABI() const

Get the C++ ABI currently in use.

const T * castAs() const

Member-template castAs.

virtual const ThunkInfoVectorTy * getThunkInfo(GlobalDecl GD)

Represents a variable declaration or definition.

Defines the clang::TargetInfo interface.

The JSON file list parser is used to communicate input to InstallAPI.

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_DefaultClosure

Default closure variant of a ctor.

@ Ctor_Complete

Complete object ctor.

CXXDtorType

C++ destructor types.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

const FunctionProtoType * T

CallingConv

CallingConv - Specifies the calling convention that a function uses.

Parts of a decomposed MSGuidDecl.

The this pointer adjustment as well as an optional return adjustment for a thunk.