31const char *itanium_demangle::parse_discriminator(
const char *first,
36 const char *t1 = first + 1;
38 if (std::isdigit(*t1))
40 else if (*t1 ==
'_') {
41 for (++t1; t1 !=
last && std::isdigit(*t1); ++t1)
43 if (t1 != last && *t1 ==
'_')
47 }
else if (std::isdigit(*first)) {
48 const char *t1 = first + 1;
49 for (; t1 !=
last && std::isdigit(*t1); ++t1)
62 bool PendingNewline =
false;
64 template<
typename NodeT>
static constexpr bool wantsNewline(
const NodeT *) {
67 static bool wantsNewline(NodeArray
A) {
return !
A.empty(); }
68 static constexpr bool wantsNewline(...) {
return false; }
70 template<
typename ...Ts>
static bool anyWantNewline(Ts ...Vs) {
71 for (
bool B : {wantsNewline(Vs)...})
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());
81 void print(
const Node *
N) {
83 N->visit(std::ref(*
this));
91 for (
const Node *
N :
A) {
103 void print(
bool B) { printStr(
B ?
"true" :
"false"); }
105 template <
class T> std::enable_if_t<std::is_unsigned<T>::value>
print(
T N) {
106 fprintf(stderr,
"%llu", (
unsigned long long)
N);
109 template <
class T> std::enable_if_t<std::is_signed<T>::value>
print(
T N) {
110 fprintf(stderr,
"%lld", (
long long)
N);
116 return printStr(
"ReferenceKind::LValue");
118 return printStr(
"ReferenceKind::RValue");
124 return printStr(
"FunctionRefQual::FrefQualNone");
126 return printStr(
"FunctionRefQual::FrefQualLValue");
128 return printStr(
"FunctionRefQual::FrefQualRValue");
132 if (!Qs)
return printStr(
"QualNone");
138 for (QualName Name : Names) {
142 if (Qs) printStr(
" | ");
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");
165 return printStr(
"TemplateParamKind::Type");
167 return printStr(
"TemplateParamKind::NonType");
169 return printStr(
"TemplateParamKind::Template");
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");
219 for (
unsigned I = 0;
I != Depth; ++
I)
221 PendingNewline =
false;
224 template<
typename T>
void printWithPendingNewline(
T V) {
227 PendingNewline =
true;
230 template<
typename T>
void printWithComma(
T V) {
231 if (PendingNewline || wantsNewline(V)) {
238 printWithPendingNewline(V);
241 struct CtorArgPrinter {
242 DumpVisitor &Visitor;
244 template<
typename T,
typename ...Rest>
void operator()(
T V, Rest ...Vs) {
245 if (Visitor.anyWantNewline(V, Vs...))
247 Visitor.printWithPendingNewline(V);
248 int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };
253 template<
typename NodeT>
void operator()(
const NodeT *Node) {
255 fprintf(stderr,
"%s(", itanium_demangle::NodeKind<NodeT>::name());
256 Node->match(CtorArgPrinter{*
this});
257 fprintf(stderr,
")");
261 void operator()(
const ForwardTemplateReference *Node) {
263 fprintf(stderr,
"ForwardTemplateReference(");
265 Node->Printing =
true;
266 CtorArgPrinter{*
this}(
Node->Ref);
267 Node->Printing =
false;
269 CtorArgPrinter{*
this}(
Node->Index);
271 fprintf(stderr,
")");
277void itanium_demangle::Node::dump()
const {
285class BumpPointerAllocator {
291 static constexpr size_t AllocSize = 4096;
292 static constexpr size_t UsableAllocSize = AllocSize -
sizeof(BlockMeta);
294 alignas(
long double)
char InitialBuffer[AllocSize];
295 BlockMeta* BlockList =
nullptr;
298 char* NewMeta =
static_cast<char *
>(std::malloc(AllocSize));
299 if (NewMeta ==
nullptr)
301 BlockList =
new (NewMeta) BlockMeta{BlockList, 0};
304 void* allocateMassive(
size_t NBytes) {
305 NBytes +=
sizeof(BlockMeta);
306 BlockMeta* NewMeta =
reinterpret_cast<BlockMeta*
>(std::malloc(NBytes));
307 if (NewMeta ==
nullptr)
309 BlockList->Next =
new (NewMeta) BlockMeta{BlockList->Next, 0};
310 return static_cast<void*
>(NewMeta + 1);
314 BumpPointerAllocator()
315 : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
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);
324 BlockList->Current +=
N;
325 return static_cast<void*
>(
reinterpret_cast<char*
>(BlockList + 1) +
326 BlockList->Current -
N);
331 BlockMeta* Tmp = BlockList;
332 BlockList = BlockList->Next;
333 if (
reinterpret_cast<char*
>(Tmp) != InitialBuffer)
336 BlockList =
new (InitialBuffer) BlockMeta{
nullptr, 0};
339 ~BumpPointerAllocator() { reset(); }
342class DefaultAllocator {
343 BumpPointerAllocator Alloc;
346 void reset() { Alloc.reset(); }
348 template<
typename T,
typename ...Args>
T *makeNode(Args &&...
args) {
349 return new (Alloc.allocate(
sizeof(
T)))
350 T(std::forward<Args>(
args)...);
353 void *allocateNodeArray(
size_t sz) {
354 return Alloc.allocate(
sizeof(Node *) * sz);
363using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
366 if (MangledName.empty())
369 Demangler Parser(MangledName.data(),
370 MangledName.data() + MangledName.length());
371 Node *AST = Parser.parse(ParseParams);
376 assert(Parser.ForwardTemplateRefs.empty());
379 return OB.getBuffer();
383 : RootNode(nullptr), Context(new Demangler{nullptr, nullptr}) {}
386 delete static_cast<Demangler *
>(Context);
391 : RootNode(
Other.RootNode), Context(
Other.Context) {
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;
414 *
N = OB.getCurrentPosition();
415 return OB.getBuffer();
430 switch (Name->getKind()) {
431 case Node::KAbiTagAttr:
434 case Node::KModuleEntity:
437 case Node::KNestedName:
438 Name =
static_cast<const NestedName *
>(Name)->Name;
440 case Node::KLocalName:
441 Name =
static_cast<const LocalName *
>(Name)->Entity;
443 case Node::KNameWithTemplateArgs:
460 KeepGoingLocalFunction:
462 if (Name->getKind() == Node::KAbiTagAttr) {
466 if (Name->getKind() == Node::KNameWithTemplateArgs) {
473 if (Name->getKind() == Node::KModuleEntity)
476 switch (Name->getKind()) {
477 case Node::KNestedName:
480 case Node::KLocalName: {
481 auto *LN =
static_cast<const LocalName *
>(Name);
485 goto KeepGoingLocalFunction;
492 *
N = OB.getCurrentPosition();
493 return OB.getBuffer();
516 *
N = OB.getCurrentPosition();
517 return OB.getBuffer();
521 char *Buf,
size_t *
N)
const {
527 if (
const Node *Ret =
533 *
N = OB.getCurrentPosition();
534 return OB.getBuffer();
538 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
543 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
544 assert(OB !=
nullptr &&
"valid OutputBuffer argument required");
551 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
559 const Node *
N =
static_cast<const Node *
>(RootNode);
561 switch (
N->getKind()) {
564 case Node::KCtorDtorName:
567 case Node::KAbiTagAttr:
570 case Node::KFunctionEncoding:
573 case Node::KLocalName:
576 case Node::KNameWithTemplateArgs:
579 case Node::KNestedName:
582 case Node::KModuleEntity:
591 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
592 return static_cast<const Node *
>(RootNode)->getKind() ==
593 Node::KFunctionEncoding;
597 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
598 auto K =
static_cast<const Node *
>(RootNode)->getKind();
599 return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName;
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,...
@ 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.
DEMANGLE_ABI bool isFunction() const
If this symbol describes a function.
DEMANGLE_ABI char * getFunctionBaseName(char *Buf, size_t *N) const
Get the base name of a function.
DEMANGLE_ABI bool isSpecialName() const
If this symbol is a <special-name>.
DEMANGLE_ABI bool partialDemangle(const char *MangledName)
Demangle into an AST.
DEMANGLE_ABI char * getFunctionName(char *Buf, size_t *N) const
Get the entire name of this function.
DEMANGLE_ABI bool hasFunctionQualifiers() const
If this function has any cv or reference qualifiers.
DEMANGLE_ABI char * finishDemangle(char *Buf, size_t *N) const
Just print the entire mangled name into Buf.
DEMANGLE_ABI char * getFunctionReturnType(char *Buf, size_t *N) const
DEMANGLE_ABI ItaniumPartialDemangler()
DEMANGLE_ABI ItaniumPartialDemangler & operator=(ItaniumPartialDemangler &&Other)
DEMANGLE_ABI bool isCtorOrDtor() const
If this symbol describes a constructor or destructor.
DEMANGLE_ABI ~ItaniumPartialDemangler()
DEMANGLE_ABI char * getFunctionDeclContextName(char *Buf, size_t *N) const
Get the context name for a function.
DEMANGLE_ABI bool isData() const
If this symbol describes a variable.