28constexpr const char *itanium_demangle::FloatData<float>::spec;
29constexpr const char *itanium_demangle::FloatData<double>::spec;
30constexpr const char *itanium_demangle::FloatData<long double>::spec;
35const char *itanium_demangle::parse_discriminator(
const char *first,
40 const char *t1 = first + 1;
42 if (std::isdigit(*t1))
44 else if (*t1 ==
'_') {
45 for (++t1; t1 !=
last && std::isdigit(*t1); ++t1)
47 if (t1 != last && *t1 ==
'_')
51 }
else if (std::isdigit(*first)) {
52 const char *t1 = first + 1;
53 for (; t1 !=
last && std::isdigit(*t1); ++t1)
66 bool PendingNewline =
false;
68 template<
typename NodeT>
static constexpr bool wantsNewline(
const NodeT *) {
71 static bool wantsNewline(
NodeArray A) {
return !
A.empty(); }
72 static constexpr bool wantsNewline(...) {
return false; }
74 template<
typename ...Ts>
static bool anyWantNewline(Ts ...Vs) {
75 for (
bool B : {wantsNewline(Vs)...})
81 void printStr(
const char *S) { fprintf(stderr,
"%s", S); }
82 void print(std::string_view SV) {
83 fprintf(stderr,
"\"%.*s\"", (
int)SV.size(), SV.data());
87 N->visit(std::ref(*
this));
107 void print(
bool B) { printStr(
B ?
"true" :
"false"); }
109 template <
class T> std::enable_if_t<std::is_unsigned<T>::value>
print(
T N) {
110 fprintf(stderr,
"%llu", (
unsigned long long)
N);
113 template <
class T> std::enable_if_t<std::is_signed<T>::value>
print(
T N) {
114 fprintf(stderr,
"%lld", (
long long)
N);
119 case ReferenceKind::LValue:
120 return printStr(
"ReferenceKind::LValue");
121 case ReferenceKind::RValue:
122 return printStr(
"ReferenceKind::RValue");
127 case FunctionRefQual::FrefQualNone:
128 return printStr(
"FunctionRefQual::FrefQualNone");
129 case FunctionRefQual::FrefQualLValue:
130 return printStr(
"FunctionRefQual::FrefQualLValue");
131 case FunctionRefQual::FrefQualRValue:
132 return printStr(
"FunctionRefQual::FrefQualRValue");
136 if (!Qs)
return printStr(
"QualNone");
142 for (QualName
Name : Names) {
146 if (Qs) printStr(
" | ");
152 case SpecialSubKind::allocator:
153 return printStr(
"SpecialSubKind::allocator");
154 case SpecialSubKind::basic_string:
155 return printStr(
"SpecialSubKind::basic_string");
156 case SpecialSubKind::string:
157 return printStr(
"SpecialSubKind::string");
158 case SpecialSubKind::istream:
159 return printStr(
"SpecialSubKind::istream");
160 case SpecialSubKind::ostream:
161 return printStr(
"SpecialSubKind::ostream");
162 case SpecialSubKind::iostream:
163 return printStr(
"SpecialSubKind::iostream");
168 case TemplateParamKind::Type:
169 return printStr(
"TemplateParamKind::Type");
170 case TemplateParamKind::NonType:
171 return printStr(
"TemplateParamKind::NonType");
172 case TemplateParamKind::Template:
173 return printStr(
"TemplateParamKind::Template");
179 return printStr(
"Node::Prec::Primary");
181 return printStr(
"Node::Prec::Postfix");
183 return printStr(
"Node::Prec::Unary");
185 return printStr(
"Node::Prec::Cast");
187 return printStr(
"Node::Prec::PtrMem");
189 return printStr(
"Node::Prec::Multiplicative");
191 return printStr(
"Node::Prec::Additive");
193 return printStr(
"Node::Prec::Shift");
195 return printStr(
"Node::Prec::Spaceship");
197 return printStr(
"Node::Prec::Relational");
199 return printStr(
"Node::Prec::Equality");
201 return printStr(
"Node::Prec::And");
203 return printStr(
"Node::Prec::Xor");
205 return printStr(
"Node::Prec::Ior");
207 return printStr(
"Node::Prec::AndIf");
209 return printStr(
"Node::Prec::OrIf");
211 return printStr(
"Node::Prec::Conditional");
213 return printStr(
"Node::Prec::Assign");
215 return printStr(
"Node::Prec::Comma");
217 return printStr(
"Node::Prec::Default");
223 for (
unsigned I = 0;
I !=
Depth; ++
I)
225 PendingNewline =
false;
228 template<
typename T>
void printWithPendingNewline(
T V) {
231 PendingNewline =
true;
234 template<
typename T>
void printWithComma(
T V) {
235 if (PendingNewline || wantsNewline(V)) {
242 printWithPendingNewline(V);
245 struct CtorArgPrinter {
246 DumpVisitor &Visitor;
248 template<
typename T,
typename ...Rest>
void operator()(
T V, Rest ...Vs) {
249 if (Visitor.anyWantNewline(V, Vs...))
251 Visitor.printWithPendingNewline(V);
252 int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };
257 template<
typename NodeT>
void operator()(
const NodeT *
Node) {
259 fprintf(stderr,
"%s(", itanium_demangle::NodeKind<NodeT>::name());
260 Node->match(CtorArgPrinter{*
this});
261 fprintf(stderr,
")");
267 fprintf(stderr,
"ForwardTemplateReference(");
269 Node->Printing =
true;
270 CtorArgPrinter{*
this}(
Node->Ref);
271 Node->Printing =
false;
273 CtorArgPrinter{*
this}(
Node->Index);
275 fprintf(stderr,
")");
281void itanium_demangle::Node::dump()
const {
289class BumpPointerAllocator {
295 static constexpr size_t AllocSize = 4096;
296 static constexpr size_t UsableAllocSize = AllocSize -
sizeof(BlockMeta);
298 alignas(
long double)
char InitialBuffer[AllocSize];
299 BlockMeta* BlockList =
nullptr;
302 char* NewMeta =
static_cast<char *
>(std::malloc(AllocSize));
303 if (NewMeta ==
nullptr)
305 BlockList =
new (NewMeta) BlockMeta{BlockList, 0};
308 void* allocateMassive(
size_t NBytes) {
309 NBytes +=
sizeof(BlockMeta);
310 BlockMeta* NewMeta =
reinterpret_cast<BlockMeta*
>(std::malloc(NBytes));
311 if (NewMeta ==
nullptr)
313 BlockList->Next =
new (NewMeta) BlockMeta{BlockList->Next, 0};
314 return static_cast<void*
>(NewMeta + 1);
318 BumpPointerAllocator()
319 : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
321 void* allocate(
size_t N) {
322 N = (
N + 15u) & ~15u;
323 if (
N + BlockList->Current >= UsableAllocSize) {
324 if (
N > UsableAllocSize)
325 return allocateMassive(
N);
328 BlockList->Current +=
N;
329 return static_cast<void*
>(
reinterpret_cast<char*
>(BlockList + 1) +
330 BlockList->Current -
N);
335 BlockMeta* Tmp = BlockList;
336 BlockList = BlockList->Next;
337 if (
reinterpret_cast<char*
>(Tmp) != InitialBuffer)
340 BlockList =
new (InitialBuffer) BlockMeta{
nullptr, 0};
343 ~BumpPointerAllocator() { reset(); }
346class DefaultAllocator {
347 BumpPointerAllocator Alloc;
350 void reset() { Alloc.reset(); }
352 template<
typename T,
typename ...Args>
T *makeNode(Args &&...
args) {
353 return new (Alloc.allocate(
sizeof(
T)))
354 T(std::forward<Args>(
args)...);
357 void *allocateNodeArray(
size_t sz) {
358 return Alloc.allocate(
sizeof(
Node *) * sz);
367using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
370 if (MangledName.empty())
374 MangledName.data() + MangledName.length());
375 Node *AST = Parser.parse(ParseParams);
380 assert(Parser.ForwardTemplateRefs.empty());
383 return OB.getBuffer();
387 : RootNode(nullptr), Context(new
Demangler{nullptr, nullptr}) {}
390 delete static_cast<Demangler *
>(Context);
395 : RootNode(
Other.RootNode), Context(
Other.Context) {
409 size_t Len = std::strlen(MangledName);
410 Parser->reset(MangledName, MangledName + Len);
411 RootNode = Parser->parse();
412 return RootNode ==
nullptr;
420 *
N = OB.getCurrentPosition();
421 return OB.getBuffer();
431 switch (
Name->getKind()) {
432 case Node::KAbiTagAttr:
435 case Node::KModuleEntity:
438 case Node::KNestedName:
441 case Node::KLocalName:
444 case Node::KNameWithTemplateArgs:
459 OutputBuffer OB(Buf,
N);
461 KeepGoingLocalFunction:
463 if (
Name->getKind() == Node::KAbiTagAttr) {
467 if (
Name->getKind() == Node::KNameWithTemplateArgs) {
474 if (
Name->getKind() == Node::KModuleEntity)
477 switch (
Name->getKind()) {
478 case Node::KNestedName:
481 case Node::KLocalName: {
486 goto KeepGoingLocalFunction;
493 *
N = OB.getCurrentPosition();
494 return OB.getBuffer();
510 OutputBuffer OB(Buf,
N);
517 *
N = OB.getCurrentPosition();
518 return OB.getBuffer();
522 char *Buf,
size_t *
N)
const {
526 OutputBuffer OB(Buf,
N);
528 if (
const Node *Ret =
534 *
N = OB.getCurrentPosition();
535 return OB.getBuffer();
539 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
540 return printNode(
static_cast<Node *
>(RootNode), Buf,
N);
544 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
552 const Node *
N =
static_cast<const Node *
>(RootNode);
554 switch (
N->getKind()) {
557 case Node::KCtorDtorName:
560 case Node::KAbiTagAttr:
563 case Node::KFunctionEncoding:
566 case Node::KLocalName:
569 case Node::KNameWithTemplateArgs:
572 case Node::KNestedName:
575 case Node::KModuleEntity:
584 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
585 return static_cast<const Node *
>(RootNode)->getKind() ==
586 Node::KFunctionEncoding;
590 assert(RootNode !=
nullptr &&
"must call partialDemangle()");
591 auto K =
static_cast<const Node *
>(RootNode)->getKind();
592 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")
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 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.
This is an optimization pass for GlobalISel generic memory operations.
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.
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 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.