27constexpr const char *itanium_demangle::FloatData<float>::spec;
28constexpr const char *itanium_demangle::FloatData<double>::spec;
29constexpr const char *itanium_demangle::FloatData<long double>::spec;
34const char *itanium_demangle::parse_discriminator(
const char *first,
39 const char *t1 = first + 1;
41 if (std::isdigit(*t1))
43 else if (*t1 ==
'_') {
44 for (++t1; t1 !=
last && std::isdigit(*t1); ++t1)
46 if (t1 != last && *t1 ==
'_')
50 }
else if (std::isdigit(*first)) {
51 const char *t1 = first + 1;
52 for (; t1 !=
last && std::isdigit(*t1); ++t1)
65 bool PendingNewline =
false;
67 template<
typename NodeT>
static constexpr bool wantsNewline(
const NodeT *) {
70 static bool wantsNewline(
NodeArray A) {
return !
A.empty(); }
71 static constexpr bool wantsNewline(...) {
return false; }
73 template<
typename ...Ts>
static bool anyWantNewline(Ts ...Vs) {
74 for (
bool B : {wantsNewline(Vs)...})
80 void printStr(
const char *S) { fprintf(stderr,
"%s", S); }
81 void print(std::string_view SV) {
82 fprintf(stderr,
"\"%.*s\"", (
int)SV.size(), &*SV.begin());
86 N->visit(std::ref(*
this));
106 void print(
bool B) { printStr(
B ?
"true" :
"false"); }
108 template <
class T> std::enable_if_t<std::is_unsigned<T>::value>
print(
T N) {
109 fprintf(stderr,
"%llu", (
unsigned long long)
N);
112 template <
class T> std::enable_if_t<std::is_signed<T>::value>
print(
T N) {
113 fprintf(stderr,
"%lld", (
long long)
N);
118 case ReferenceKind::LValue:
119 return printStr(
"ReferenceKind::LValue");
120 case ReferenceKind::RValue:
121 return printStr(
"ReferenceKind::RValue");
126 case FunctionRefQual::FrefQualNone:
127 return printStr(
"FunctionRefQual::FrefQualNone");
128 case FunctionRefQual::FrefQualLValue:
129 return printStr(
"FunctionRefQual::FrefQualLValue");
130 case FunctionRefQual::FrefQualRValue:
131 return printStr(
"FunctionRefQual::FrefQualRValue");
135 if (!Qs)
return printStr(
"QualNone");
145 if (Qs) printStr(
" | ");
151 case SpecialSubKind::allocator:
152 return printStr(
"SpecialSubKind::allocator");
153 case SpecialSubKind::basic_string:
154 return printStr(
"SpecialSubKind::basic_string");
155 case SpecialSubKind::string:
156 return printStr(
"SpecialSubKind::string");
157 case SpecialSubKind::istream:
158 return printStr(
"SpecialSubKind::istream");
159 case SpecialSubKind::ostream:
160 return printStr(
"SpecialSubKind::ostream");
161 case SpecialSubKind::iostream:
162 return printStr(
"SpecialSubKind::iostream");
167 case TemplateParamKind::Type:
168 return printStr(
"TemplateParamKind::Type");
169 case TemplateParamKind::NonType:
170 return printStr(
"TemplateParamKind::NonType");
171 case TemplateParamKind::Template:
172 return printStr(
"TemplateParamKind::Template");
178 return printStr(
"Node::Prec::Primary");
180 return printStr(
"Node::Prec::Postfix");
182 return printStr(
"Node::Prec::Unary");
184 return printStr(
"Node::Prec::Cast");
186 return printStr(
"Node::Prec::PtrMem");
188 return printStr(
"Node::Prec::Multiplicative");
190 return printStr(
"Node::Prec::Additive");
192 return printStr(
"Node::Prec::Shift");
194 return printStr(
"Node::Prec::Spaceship");
196 return printStr(
"Node::Prec::Relational");
198 return printStr(
"Node::Prec::Equality");
200 return printStr(
"Node::Prec::And");
202 return printStr(
"Node::Prec::Xor");
204 return printStr(
"Node::Prec::Ior");
206 return printStr(
"Node::Prec::AndIf");
208 return printStr(
"Node::Prec::OrIf");
210 return printStr(
"Node::Prec::Conditional");
212 return printStr(
"Node::Prec::Assign");
214 return printStr(
"Node::Prec::Comma");
216 return printStr(
"Node::Prec::Default");
222 for (
unsigned I = 0;
I !=
Depth; ++
I)
224 PendingNewline =
false;
227 template<
typename T>
void printWithPendingNewline(
T V) {
230 PendingNewline =
true;
233 template<
typename T>
void printWithComma(
T V) {
234 if (PendingNewline || wantsNewline(V)) {
241 printWithPendingNewline(V);
244 struct CtorArgPrinter {
245 DumpVisitor &Visitor;
247 template<
typename T,
typename ...Rest>
void operator()(
T V, Rest ...Vs) {
248 if (Visitor.anyWantNewline(V, Vs...))
250 Visitor.printWithPendingNewline(V);
251 int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };
256 template<
typename NodeT>
void operator()(
const NodeT *
Node) {
258 fprintf(stderr,
"%s(", itanium_demangle::NodeKind<NodeT>::name());
259 Node->match(CtorArgPrinter{*
this});
260 fprintf(stderr,
")");
266 fprintf(stderr,
"ForwardTemplateReference(");
268 Node->Printing =
true;
269 CtorArgPrinter{*
this}(
Node->Ref);
270 Node->Printing =
false;
272 CtorArgPrinter{*
this}(
Node->Index);
274 fprintf(stderr,
")");
280void itanium_demangle::Node::dump()
const {
288class BumpPointerAllocator {
294 static constexpr size_t AllocSize = 4096;
295 static constexpr size_t UsableAllocSize = AllocSize -
sizeof(BlockMeta);
297 alignas(
long double)
char InitialBuffer[AllocSize];
298 BlockMeta* BlockList =
nullptr;
301 char* NewMeta =
static_cast<char *
>(std::malloc(AllocSize));
302 if (NewMeta ==
nullptr)
304 BlockList =
new (NewMeta) BlockMeta{BlockList, 0};
307 void* allocateMassive(
size_t NBytes) {
308 NBytes +=
sizeof(BlockMeta);
309 BlockMeta* NewMeta =
reinterpret_cast<BlockMeta*
>(std::malloc(NBytes));
310 if (NewMeta ==
nullptr)
312 BlockList->Next =
new (NewMeta) BlockMeta{BlockList->Next, 0};
313 return static_cast<void*
>(NewMeta + 1);
317 BumpPointerAllocator()
318 : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
320 void* allocate(
size_t N) {
321 N = (
N + 15u) & ~15u;
322 if (
N + BlockList->Current >= UsableAllocSize) {
323 if (
N > UsableAllocSize)
324 return allocateMassive(
N);
327 BlockList->Current +=
N;
328 return static_cast<void*
>(
reinterpret_cast<char*
>(BlockList + 1) +
329 BlockList->Current -
N);
334 BlockMeta* Tmp = BlockList;
335 BlockList = BlockList->Next;
336 if (
reinterpret_cast<char*
>(Tmp) != InitialBuffer)
339 BlockList =
new (InitialBuffer) BlockMeta{
nullptr, 0};
342 ~BumpPointerAllocator() { reset(); }
345class DefaultAllocator {
346 BumpPointerAllocator Alloc;
349 void reset() { Alloc.reset(); }
351 template<
typename T,
typename ...Args>
T *makeNode(Args &&...
args) {
352 return new (Alloc.allocate(
sizeof(
T)))
353 T(std::forward<Args>(
args)...);
356 void *allocateNodeArray(
size_t sz) {
357 return Alloc.allocate(
sizeof(
Node *) * sz);
366using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
369 if (MangledName.empty())
373 MangledName.data() + MangledName.length());
374 Node *AST = Parser.parse();
379 assert(Parser.ForwardTemplateRefs.empty());
382 return OB.getBuffer();
389 delete static_cast<Demangler *
>(Context);
408 size_t Len = std::strlen(MangledName);
409 Parser->reset(MangledName, MangledName + Len);
410 RootNode = Parser->parse();
411 return RootNode ==
nullptr;
419 *
N = OB.getCurrentPosition();
420 return OB.getBuffer();
430 switch (
Name->getKind()) {
431 case Node::KAbiTagAttr:
434 case Node::KModuleEntity:
437 case Node::KNestedName:
440 case Node::KLocalName:
443 case Node::KNameWithTemplateArgs:
458 OutputBuffer OB(Buf,
N);
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: {
485 goto KeepGoingLocalFunction;
492 *
N = OB.getCurrentPosition();
493 return OB.getBuffer();
509 OutputBuffer OB(Buf,
N);
516 *
N = OB.getCurrentPosition();
517 return OB.getBuffer();
521 char *Buf,
size_t *
N)
const {
525 OutputBuffer OB(Buf,
N);
527 if (
const Node *Ret =
533 *
N = OB.getCurrentPosition();
534 return OB.getBuffer();
538 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
539 return printNode(
static_cast<Node *
>(RootNode), Buf,
N);
543 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
551 const Node *
N =
static_cast<const Node *
>(RootNode);
553 switch (
N->getKind()) {
556 case Node::KCtorDtorName:
559 case Node::KAbiTagAttr:
562 case Node::KFunctionEncoding:
565 case Node::KLocalName:
568 case Node::KNameWithTemplateArgs:
571 case Node::KNestedName:
574 case Node::KModuleEntity:
583 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
584 return static_cast<const Node *
>(RootNode)->getKind() ==
585 Node::KFunctionEncoding;
589 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
590 auto K =
static_cast<const Node *
>(RootNode)->getKind();
591 return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName;
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
itanium_demangle::ManglingParser< DefaultAllocator > Demangler
static void printNode(raw_ostream &OS, LazyCallGraph::Node &N)
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void printWithComma(OutputBuffer &OB) const
void print(OutputBuffer &OB) const
Prec
Operator precedence for expression nodes.
This is an optimization pass for GlobalISel generic memory operations.
char * itaniumDemangle(std::string_view mangled_name)
Returns a non-NULL pointer to a NUL-terminated C style string that should be explicitly freed,...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A forward-reference to a template argument that was not known at the point where the template paramet...
char * getFunctionParameters(char *Buf, size_t *N) const
Get the parameters for this function.
bool isFunction() const
If this symbol describes a function.
char * getFunctionBaseName(char *Buf, size_t *N) const
Get the base name of a function.
bool isSpecialName() const
If this symbol is a <special-name>.
bool partialDemangle(const char *MangledName)
Demangle into an AST.
char * getFunctionName(char *Buf, size_t *N) const
Get the entire name of this function.
bool hasFunctionQualifiers() const
If this function has any any cv or reference qualifiers.
char * finishDemangle(char *Buf, size_t *N) const
Just print the entire mangled name into Buf.
char * getFunctionReturnType(char *Buf, size_t *N) const
ItaniumPartialDemangler()
ItaniumPartialDemangler & operator=(ItaniumPartialDemangler &&Other)
bool isCtorOrDtor() const
If this symbol describes a constructor or destructor.
~ItaniumPartialDemangler()
char * getFunctionDeclContextName(char *Buf, size_t *N) const
Get the context name for a function.
bool isData() const
If this symbol describes a variable.