LLVM: lib/Demangle/ItaniumDemangle.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

15

16#include

17#include

18#include

19#include

20#include

21#include

22#include

23#include

24

25using namespace llvm;

27

28

29

30

31const char *itanium_demangle::parse_discriminator(const char *first,

32 const char *last) {

33

34 if (first != last) {

35 if (*first == '_') {

36 const char *t1 = first + 1;

37 if (t1 != last) {

38 if (std::isdigit(*t1))

39 first = t1 + 1;

40 else if (*t1 == '_') {

41 for (++t1; t1 != last && std::isdigit(*t1); ++t1)

42 ;

43 if (t1 != last && *t1 == '_')

44 first = t1 + 1;

45 }

46 }

47 } else if (std::isdigit(*first)) {

48 const char *t1 = first + 1;

49 for (; t1 != last && std::isdigit(*t1); ++t1)

50 ;

51 if (t1 == last)

53 }

54 }

55 return first;

56}

57

58#ifndef NDEBUG

59namespace {

60struct DumpVisitor {

61 unsigned Depth = 0;

62 bool PendingNewline = false;

63

64 template static constexpr bool wantsNewline(const NodeT *) {

65 return true;

66 }

67 static bool wantsNewline(NodeArray A) { return A.empty(); }

68 static constexpr bool wantsNewline(...) { return false; }

69

70 template<typename ...Ts> static bool anyWantNewline(Ts ...Vs) {

71 for (bool B : {wantsNewline(Vs)...})

72 if (B)

73 return true;

74 return false;

75 }

76

77 void printStr(const char *S) { fprintf(stderr, "%s", S); }

78 void print(std::string_view SV) {

79 fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.data());

80 }

81 void print(const Node *N) {

82 if (N)

83 N->visit(std::ref(*this));

84 else

85 printStr("");

86 }

87 void print(NodeArray A) {

88 ++Depth;

89 printStr("{");

90 bool First = true;

91 for (const Node *N : A) {

94 else

95 printWithComma(N);

97 }

98 printStr("}");

99 --Depth;

100 }

101

102

103 void print(bool B) { printStr(B ? "true" : "false"); }

104

105 template std::enable_if_t<std::is_unsigned::value> print(T N) {

106 fprintf(stderr, "%llu", (unsigned long long)N);

107 }

108

109 template std::enable_if_t<std::is_signed::value> print(T N) {

110 fprintf(stderr, "%lld", (long long)N);

111 }

112

114 switch (RK) {

116 return printStr("ReferenceKind::LValue");

118 return printStr("ReferenceKind::RValue");

119 }

120 }

122 switch (RQ) {

124 return printStr("FunctionRefQual::FrefQualNone");

126 return printStr("FunctionRefQual::FrefQualLValue");

128 return printStr("FunctionRefQual::FrefQualRValue");

129 }

130 }

132 if (!Qs) return printStr("QualNone");

133 struct QualName { Qualifiers Q; const char *Name; } Names[] = {

137 };

138 for (QualName Name : Names) {

139 if (Qs & Name.Q) {

140 printStr(Name.Name);

142 if (Qs) printStr(" | ");

143 }

144 }

145 }

147 switch (SSK) {

149 return printStr("SpecialSubKind::allocator");

151 return printStr("SpecialSubKind::basic_string");

153 return printStr("SpecialSubKind::string");

155 return printStr("SpecialSubKind::istream");

157 return printStr("SpecialSubKind::ostream");

159 return printStr("SpecialSubKind::iostream");

160 }

161 }

163 switch (TPK) {

165 return printStr("TemplateParamKind::Type");

167 return printStr("TemplateParamKind::NonType");

169 return printStr("TemplateParamKind::Template");

170 }

171 }

173 switch (P) {

175 return printStr("Node::Prec::Primary");

177 return printStr("Node::Prec::Postfix");

179 return printStr("Node::Prec::Unary");

181 return printStr("Node::Prec::Cast");

183 return printStr("Node::Prec::PtrMem");

185 return printStr("Node::Prec::Multiplicative");

187 return printStr("Node::Prec::Additive");

189 return printStr("Node::Prec::Shift");

191 return printStr("Node::Prec::Spaceship");

193 return printStr("Node::Prec::Relational");

195 return printStr("Node::Prec::Equality");

197 return printStr("Node::Prec::And");

199 return printStr("Node::Prec::Xor");

201 return printStr("Node::Prec::Ior");

203 return printStr("Node::Prec::AndIf");

205 return printStr("Node::Prec::OrIf");

207 return printStr("Node::Prec::Conditional");

209 return printStr("Node::Prec::Assign");

211 return printStr("Node::Prec::Comma");

213 return printStr("Node::Prec::Default");

214 }

215 }

216

217 void newLine() {

218 printStr("\n");

219 for (unsigned I = 0; I != Depth; ++I)

220 printStr(" ");

221 PendingNewline = false;

222 }

223

224 template void printWithPendingNewline(T V) {

226 if (wantsNewline(V))

227 PendingNewline = true;

228 }

229

230 template void printWithComma(T V) {

231 if (PendingNewline || wantsNewline(V)) {

232 printStr(",");

233 newLine();

234 } else {

235 printStr(", ");

236 }

237

238 printWithPendingNewline(V);

239 }

240

241 struct CtorArgPrinter {

242 DumpVisitor &Visitor;

243

244 template<typename T, typename ...Rest> void operator()(T V, Rest ...Vs) {

245 if (Visitor.anyWantNewline(V, Vs...))

246 Visitor.newLine();

247 Visitor.printWithPendingNewline(V);

248 int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };

249 (void)PrintInOrder;

250 }

251 };

252

253 template void operator()(const NodeT *Node) {

254 Depth += 2;

255 fprintf(stderr, "%s(", itanium_demangle::NodeKind::name());

256 Node->match(CtorArgPrinter{*this});

257 fprintf(stderr, ")");

258 Depth -= 2;

259 }

260

261 void operator()(const ForwardTemplateReference *Node) {

262 Depth += 2;

263 fprintf(stderr, "ForwardTemplateReference(");

264 if (Node->Ref && Node->Printing) {

265 Node->Printing = true;

266 CtorArgPrinter{*this}(Node->Ref);

267 Node->Printing = false;

268 } else {

269 CtorArgPrinter{*this}(Node->Index);

270 }

271 fprintf(stderr, ")");

272 Depth -= 2;

273 }

274};

275}

276

277void itanium_demangle::Node::dump() const {

278 DumpVisitor V;

279 visit(std::ref(V));

280 V.newLine();

281}

282#endif

283

284namespace {

285class BumpPointerAllocator {

286 struct BlockMeta {

287 BlockMeta* Next;

288 size_t Current;

289 };

290

291 static constexpr size_t AllocSize = 4096;

292 static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta);

293

294 alignas(long double) char InitialBuffer[AllocSize];

295 BlockMeta* BlockList = nullptr;

296

297 void grow() {

298 char* NewMeta = static_cast<char *>(std::malloc(AllocSize));

299 if (NewMeta == nullptr)

300 std::terminate();

301 BlockList = new (NewMeta) BlockMeta{BlockList, 0};

302 }

303

304 void* allocateMassive(size_t NBytes) {

305 NBytes += sizeof(BlockMeta);

306 BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(std::malloc(NBytes));

307 if (NewMeta == nullptr)

308 std::terminate();

309 BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0};

310 return static_cast<void*>(NewMeta + 1);

311 }

312

313public:

314 BumpPointerAllocator()

315 : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}

316

317 void* allocate(size_t N) {

318 N = (N + 15u) & ~15u;

319 if (N + BlockList->Current >= UsableAllocSize) {

320 if (N > UsableAllocSize)

321 return allocateMassive(N);

322 grow();

323 }

324 BlockList->Current += N;

325 return static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) +

326 BlockList->Current - N);

327 }

328

329 void reset() {

330 while (BlockList) {

331 BlockMeta* Tmp = BlockList;

332 BlockList = BlockList->Next;

333 if (reinterpret_cast<char*>(Tmp) != InitialBuffer)

334 std::free(Tmp);

335 }

336 BlockList = new (InitialBuffer) BlockMeta{nullptr, 0};

337 }

338

339 ~BumpPointerAllocator() { reset(); }

340};

341

342class DefaultAllocator {

343 BumpPointerAllocator Alloc;

344

345public:

346 void reset() { Alloc.reset(); }

347

348 template<typename T, typename ...Args> T *makeNode(Args &&...args) {

349 return new (Alloc.allocate(sizeof(T)))

350 T(std::forward(args)...);

351 }

352

353 void *allocateNodeArray(size_t sz) {

354 return Alloc.allocate(sizeof(Node *) * sz);

355 }

356};

357}

358

359

360

361

362

363using Demangler = itanium_demangle::ManglingParser;

364

366 if (MangledName.empty())

367 return nullptr;

368

369 Demangler Parser(MangledName.data(),

370 MangledName.data() + MangledName.length());

371 Node *AST = Parser.parse(ParseParams);

372 if (!AST)

373 return nullptr;

374

376 assert(Parser.ForwardTemplateRefs.empty());

378 OB += '\0';

379 return OB.getBuffer();

380}

381

383 : RootNode(nullptr), Context(new Demangler{nullptr, nullptr}) {}

384

386 delete static_cast<Demangler *>(Context);

387}

388

391 : RootNode(Other.RootNode), Context(Other.Context) {

392 Other.Context = Other.RootNode = nullptr;

393}

394

401

402

404 Demangler *Parser = static_cast<Demangler *>(Context);

405 size_t Len = std::strlen(MangledName);

406 Parser->reset(MangledName, MangledName + Len);

407 RootNode = Parser->parse();

408 return RootNode == nullptr;

409}

411 RootNode->print(OB);

412 OB += '\0';

413 if (N != nullptr)

414 *N = OB.getCurrentPosition();

415 return OB.getBuffer();

416}

417

422

425 return nullptr;

426

428

429 while (true) {

430 switch (Name->getKind()) {

431 case Node::KAbiTagAttr:

433 continue;

434 case Node::KModuleEntity:

435 Name = static_cast<const ModuleEntity *>(Name)->Name;

436 continue;

437 case Node::KNestedName:

438 Name = static_cast<const NestedName *>(Name)->Name;

439 continue;

440 case Node::KLocalName:

441 Name = static_cast<const LocalName *>(Name)->Entity;

442 continue;

443 case Node::KNameWithTemplateArgs:

445 continue;

446 default:

448 }

449 }

450}

451

453 size_t *N) const {

455 return nullptr;

457

459

460 KeepGoingLocalFunction:

461 while (true) {

462 if (Name->getKind() == Node::KAbiTagAttr) {

464 continue;

465 }

466 if (Name->getKind() == Node::KNameWithTemplateArgs) {

468 continue;

469 }

470 break;

471 }

472

473 if (Name->getKind() == Node::KModuleEntity)

474 Name = static_cast<const ModuleEntity *>(Name)->Name;

475

476 switch (Name->getKind()) {

477 case Node::KNestedName:

479 break;

480 case Node::KLocalName: {

481 auto *LN = static_cast<const LocalName *>(Name);

483 OB += "::";

484 Name = LN->Entity;

485 goto KeepGoingLocalFunction;

486 }

487 default:

488 break;

489 }

490 OB += '\0';

491 if (N != nullptr)

492 *N = OB.getCurrentPosition();

493 return OB.getBuffer();

494}

495

502

504 size_t *N) const {

506 return nullptr;

508

510

511 OB += '(';

513 OB += ')';

514 OB += '\0';

515 if (N != nullptr)

516 *N = OB.getCurrentPosition();

517 return OB.getBuffer();

518}

519

521 char *Buf, size_t *N) const {

523 return nullptr;

524

526

527 if (const Node *Ret =

528 static_cast<const FunctionEncoding *>(RootNode)->getReturnType())

529 Ret->print(OB);

530

531 OB += '\0';

532 if (N != nullptr)

533 *N = OB.getCurrentPosition();

534 return OB.getBuffer();

535}

536

538 assert(RootNode != nullptr && "must call partialDemangle()");

539 return printNode(static_cast<Node *>(RootNode), Buf, N);

540}

541

543 assert(RootNode != nullptr && "must call partialDemangle()");

544 assert(OB != nullptr && "valid OutputBuffer argument required");

547 nullptr);

548}

549

551 assert(RootNode != nullptr && "must call partialDemangle()");

553 return false;

556}

557

559 const Node *N = static_cast<const Node *>(RootNode);

560 while (N) {

561 switch (N->getKind()) {

562 default:

563 return false;

564 case Node::KCtorDtorName:

565 return true;

566

567 case Node::KAbiTagAttr:

569 break;

570 case Node::KFunctionEncoding:

572 break;

573 case Node::KLocalName:

574 N = static_cast<const LocalName *>(N)->Entity;

575 break;

576 case Node::KNameWithTemplateArgs:

578 break;

579 case Node::KNestedName:

580 N = static_cast<const NestedName *>(N)->Name;

581 break;

582 case Node::KModuleEntity:

584 break;

585 }

586 }

587 return false;

588}

589

591 assert(RootNode != nullptr && "must call partialDemangle()");

592 return static_cast<const Node *>(RootNode)->getKind() ==

593 Node::KFunctionEncoding;

594}

595

597 assert(RootNode != nullptr && "must call partialDemangle()");

598 auto K = static_cast<const Node *>(RootNode)->getKind();

599 return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName;

600}

601

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static void printNode(raw_ostream &OS, LazyCallGraph::Node &N)

static StringRef getName(Value *V)

void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)

Qualifiers getCVQuals() const

void printWithComma(OutputBuffer &OB) const

void print(OutputBuffer &OB) const

Prec

Operator precedence for expression nodes.

NodeAddr< NodeBase * > Node

This is an optimization pass for GlobalISel generic memory operations.

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)

DEMANGLE_ABI char * itaniumDemangle(std::string_view mangled_name, bool ParseParams=true)

Returns a non-NULL pointer to a NUL-terminated C style string that should be explicitly freed,...

Definition ItaniumDemangle.cpp:365

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

DEMANGLE_ABI char * getFunctionParameters(char *Buf, size_t *N) const

Get the parameters for this function.

Definition ItaniumDemangle.cpp:503

DEMANGLE_ABI bool isFunction() const

If this symbol describes a function.

Definition ItaniumDemangle.cpp:590

DEMANGLE_ABI char * getFunctionBaseName(char *Buf, size_t *N) const

Get the base name of a function.

Definition ItaniumDemangle.cpp:423

DEMANGLE_ABI bool isSpecialName() const

If this symbol is a .

Definition ItaniumDemangle.cpp:596

DEMANGLE_ABI bool partialDemangle(const char *MangledName)

Demangle into an AST.

Definition ItaniumDemangle.cpp:403

DEMANGLE_ABI char * getFunctionName(char *Buf, size_t *N) const

Get the entire name of this function.

Definition ItaniumDemangle.cpp:496

DEMANGLE_ABI bool hasFunctionQualifiers() const

If this function has any cv or reference qualifiers.

Definition ItaniumDemangle.cpp:550

DEMANGLE_ABI char * finishDemangle(char *Buf, size_t *N) const

Just print the entire mangled name into Buf.

Definition ItaniumDemangle.cpp:537

DEMANGLE_ABI char * getFunctionReturnType(char *Buf, size_t *N) const

Definition ItaniumDemangle.cpp:520

DEMANGLE_ABI ItaniumPartialDemangler()

Definition ItaniumDemangle.cpp:382

DEMANGLE_ABI ItaniumPartialDemangler & operator=(ItaniumPartialDemangler &&Other)

Definition ItaniumDemangle.cpp:396

DEMANGLE_ABI bool isCtorOrDtor() const

If this symbol describes a constructor or destructor.

Definition ItaniumDemangle.cpp:558

DEMANGLE_ABI ~ItaniumPartialDemangler()

Definition ItaniumDemangle.cpp:385

DEMANGLE_ABI char * getFunctionDeclContextName(char *Buf, size_t *N) const

Get the context name for a function.

Definition ItaniumDemangle.cpp:452

DEMANGLE_ABI bool isData() const

If this symbol describes a variable.

Definition ItaniumDemangle.cpp:602