1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

Add a Microsoft Demangler.

This adds initial support for a demangling library (LLVMDemangle)
and tool (llvm-undname) for demangling Microsoft names.  This
doesn't cover 100% of cases and there are some known limitations
which I intend to address in followup patches, at least until such
time that we have (near) 100% test coverage matching up with all
of the test cases in clang/test/CodeGenCXX/mangle-ms-*.

Differential Revision: https://reviews.llvm.org/D49552

llvm-svn: 337584
This commit is contained in:
Zachary Turner 2018-07-20 17:27:48 +00:00
parent b9adc67df4
commit 0bef0a2efc
10 changed files with 2259 additions and 2 deletions

View File

@ -16,7 +16,7 @@ namespace llvm {
/// The mangled_name is demangled into buf and returned. If the buffer is not
/// large enough, realloc is used to expand it.
///
/// The *status will be set to a value from the enumeration
/// The *status will be set to a value from the following enumeration
enum : int {
demangle_unknown_error = -4,
demangle_invalid_args = -3,
@ -27,6 +27,8 @@ enum : int {
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
int *status);
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
int *status);
/// "Partial" demangler. This supports demangling a string into an AST
/// (typically an intermediate stage in itaniumDemangle) and querying certain

View File

@ -1,6 +1,7 @@
add_llvm_library(LLVMDemangle
ItaniumDemangle.cpp
MicrosoftDemangle.cpp
ADDITIONAL_HEADER_DIRS
"${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"
)

File diff suppressed because it is too large Load Diff

230
test/Demangle/ms-basic.test Normal file
View File

@ -0,0 +1,230 @@
; RUN: llvm-undname < %s | FileCheck %s
; CHECK-NOT: Invalid mangled name
?x@@3HA
; CHECK: int x
?x@@3PEAHEA
; CHECK: int *x
?x@@3PEAPEAHEA
; CHECK: int **x
?x@@3PEAY02HEA
; CHECK: int (*x)[3]
?x@@3PEAY124HEA
; CHECK: int (*x)[3][5]
?x@@3PEAY02$$CBHEA
; CHECK: int const (*x)[3]
?x@@3PEAEEA
; CHECK: unsigned char *x
?x@@3PEAY1NKM@5HEA
; CHECK: int (*x)[3500][6]
?x@@YAXMH@Z
; CHECK: void __cdecl x(float, int)
?x@@3P6AHMNH@ZEA
; CHECK: int __cdecl (*x)(float, double, int)
?x@@3P6AHP6AHM@ZN@ZEA
; CHECK: int __cdecl (*x)(int __cdecl (*)(float), double)
?x@@3P6AHP6AHM@Z0@ZEA
; CHECK: int __cdecl (*x)(int __cdecl (*)(float), int __cdecl (*)(float))
?x@ns@@3HA
; CHECK: int ns::x
; Microsoft's undname doesn't handle Q correctly or the multiple occurrences
; of the const modifier. So the results here differ, but ours are correct.
?x@@3PEAHEA
; CHECK: int *x
?x@@3PEBHEB
; CHECK: int const *x
?x@@3QEAHEA
; CHECK: int *const x
?x@@3QEBHEB
; CHECK: int const *const x
?x@@3AEBHEB
; CHECK: int const &x
?x@@3PEAUty@@EA
; CHECK: struct ty *x
?x@@3PEATty@@EA
; CHECK: union ty *x
?x@@3PEAUty@@EA
; CHECK: struct ty *x
?x@@3PEAW4ty@@EA
; CHECK: enum ty *x
?x@@3PEAVty@@EA
; CHECK: class ty *x
?x@@3PEAV?$tmpl@H@@EA
; CHECK: class tmpl<int> *x
?x@@3PEAU?$tmpl@H@@EA
; CHECK: struct tmpl<int> *x
?x@@3PEAT?$tmpl@H@@EA
; CHECK: union tmpl<int> *x
?instance@@3Vklass@@A
; CHECK: class klass instance
?instance$initializer$@@3P6AXXZEA
; CHECK: void __cdecl (*instance$initializer$)(void)
??0klass@@QEAA@XZ
; CHECK: __cdecl klass::klass(void)
??1klass@@QEAA@XZ
; CHECK: __cdecl klass::~klass(void)
?x@@YAHPEAVklass@@AEAV1@@Z
; CHECK: int __cdecl x(class klass *, class klass &)
?x@ns@@3PEAV?$klass@HH@1@EA
; CHECK: class ns::klass<int, int> *ns::x
?fn@?$klass@H@ns@@QEBAIXZ
; CHECK: unsigned int __cdecl ns::klass<int>::fn(void) const
??4klass@@QEAAAEBV0@AEBV0@@Z
; CHECK: class klass const &__cdecl klass::operator=(class klass const &)
??7klass@@QEAA_NXZ
; CHECK: bool __cdecl klass::operator!(void)
??8klass@@QEAA_NAEBV0@@Z
; CHECK: bool __cdecl klass::operator==(class klass const &)
??9klass@@QEAA_NAEBV0@@Z
; CHECK: bool __cdecl klass::operator!=(class klass const &)
??Aklass@@QEAAH_K@Z
; CHECK: int __cdecl klass::operator[](unsigned __int64)
??Cklass@@QEAAHXZ
; CHECK: int __cdecl klass::operator->(void)
??Dklass@@QEAAHXZ
; CHECK: int __cdecl klass::operator*(void)
??Eklass@@QEAAHXZ
; CHECK: int __cdecl klass::operator++(void)
??Eklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator++(int)
??Fklass@@QEAAHXZ
; CHECK: int __cdecl klass::operator--(void)
??Fklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator--(int)
??Hklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator+(int)
??Gklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator-(int)
??Iklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator&(int)
??Jklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator->*(int)
??Kklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator/(int)
??Mklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator<(int)
??Nklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator<=(int)
??Oklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator>(int)
??Pklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator>=(int)
??Qklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator,(int)
??Rklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator()(int)
??Sklass@@QEAAHXZ
; CHECK: int __cdecl klass::operator~(void)
??Tklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator^(int)
??Uklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator|(int)
??Vklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator&&(int)
??Wklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator||(int)
??Xklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator*=(int)
??Yklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator+=(int)
??Zklass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator-=(int)
??_0klass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator/=(int)
??_1klass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator%=(int)
??_2klass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator>>=(int)
??_3klass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator<<=(int)
??_6klass@@QEAAHH@Z
; CHECK: int __cdecl klass::operator^=(int)
??6@YAAEBVklass@@AEBV0@H@Z
; CHECK: class klass const &__cdecl operator<<(class klass const &, int)
??5@YAAEBVklass@@AEBV0@_K@Z
; CHECK: class klass const &__cdecl operator>>(class klass const &, unsigned __int64)
??2@YAPEAX_KAEAVklass@@@Z
; CHECK: void *__cdecl operator new(unsigned __int64, class klass &)
??_U@YAPEAX_KAEAVklass@@@Z
; CHECK: void *__cdecl operator new[](unsigned __int64, class klass &)
??3@YAXPEAXAEAVklass@@@Z
; CHECK: void __cdecl operator delete(void *, class klass &)
??_V@YAXPEAXAEAVklass@@@Z
; CHECK: void __cdecl operator delete[](void *, class klass &)

View File

@ -0,0 +1,363 @@
; These tests are based on clang/test/CodeGenCXX/mangle-ms.cpp
; RUN: llvm-undname < %s | FileCheck %s
; CHECK-NOT: Invalid mangled name
?k@@3PTfoo@@DT1
?a@@3HA
; CHECK: int a
?b@N@@3HA
; CHECK: int N::b
?anonymous@?A@N@@3HA
; CHECK: int N::`anonymous namespace'::anonymous
?_c@@YAHXZ
; CHECK: int __cdecl _c(void)
?d@foo@@0FB
; CHECK: static short const foo::d
?e@foo@@1JC
; CHECK: static long volatile foo::e
?f@foo@@2DD
; CHECK: static char const volatile foo::f
??0foo@@QAE@XZ
; CHECK: __thiscall foo::foo(void)
??0foo@@QEAA@XZ
; CHECK: __cdecl foo::foo(void)
??1foo@@QAE@XZ
; CHECK: __thiscall foo::~foo(void)
??1foo@@QEAA@XZ
; CHECK: __cdecl foo::~foo(void)
??0foo@@QAE@H@Z
; CHECK: __thiscall foo::foo(int)
??0foo@@QEAA@H@Z
; CHECK: __cdecl foo::foo(int)
??0foo@@QAE@PAD@Z
; CHECK: __thiscall foo::foo(char *)
??0foo@@QEAA@PEAD@Z
; CHECK: __cdecl foo::foo(char *)
?bar@@YA?AVfoo@@XZ
; CHECK: class foo __cdecl bar(void)
?bar@@YA?AVfoo@@XZ
; CHECK: class foo __cdecl bar(void)
??Hfoo@@QAEHH@Z
; CHECK: int __thiscall foo::operator+(int)
??Hfoo@@QEAAHH@Z
; CHECK: int __cdecl foo::operator+(int)
?static_method@foo@@SAPAV1@XZ
; CHECK: static class foo *__cdecl foo::static_method(void)
?static_method@foo@@SAPEAV1@XZ
; CHECK: static class foo *__cdecl foo::static_method(void)
?g@bar@@2HA
; CHECK: static int bar::g
; undname returns `int *h1`, but it is a bug in their demangler. Their mangler
; correctly mangles `int *h1` as ?h1@3PAHA and `int * const h1` as ?h1@3QAHA
?h1@@3QAHA
; CHECK: int *const h1
?h2@@3QBHB
; CHECK: int const *const h2
?h3@@3QIAHIA
; CHECK: int * __restrict const h3
?h3@@3QEIAHEIA
; CHECK: int * __restrict const h3
?i@@3PAY0BE@HA
; CHECK: int (*i)[20]
?FunArr@@3PAY0BE@P6AHHH@ZA
; CHECK: int __cdecl (*(*FunArr)[20])(int, int)
?j@@3P6GHCE@ZA
; CHECK: int __stdcall (*j)(signed char, unsigned char)
; FIXME: We don't handle member pointers yet.
; ?k@@3PTfoo@@DT1
; FIXME: char const volatile foo::*k
; ?k@@3PETfoo@@DET1
; FIXME: char const volatile foo::*k
; ?l@@3P8foo@@AEHH@ZQ1
; FIXME: int __thiscall (foo::*l)(int)
?g_cInt@@3HB
; CHECK: int const g_cInt
?g_vInt@@3HC
; CHECK: int volatile g_vInt
?g_cvInt@@3HD
; CHECK: int const volatile g_cvInt
?beta@@YI_N_J_W@Z
; CHECK: bool __fastcall beta(__int64, wchar_t)
?beta@@YA_N_J_W@Z
; CHECK: bool __cdecl beta(__int64, wchar_t)
?alpha@@YGXMN@Z
; CHECK: void __stdcall alpha(float, double)
?alpha@@YAXMN@Z
; CHECK: void __cdecl alpha(float, double)
?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z
; CHECK: void __cdecl gamma(class foo, struct bar, union baz, enum quux)
?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z
; CHECK: void __cdecl gamma(class foo, struct bar, union baz, enum quux)
?delta@@YAXQAHABJ@Z
; CHECK: void __cdecl delta(int *const, long const &)
?delta@@YAXQEAHAEBJ@Z
; CHECK: void __cdecl delta(int *const, long const &)
?epsilon@@YAXQAY19BE@H@Z
; CHECK: void __cdecl epsilon(int (*const)[10][20])
?epsilon@@YAXQEAY19BE@H@Z
; CHECK: void __cdecl epsilon(int (*const)[10][20])
?zeta@@YAXP6AHHH@Z@Z
; CHECK: void __cdecl zeta(int __cdecl (*)(int, int))
?zeta@@YAXP6AHHH@Z@Z
; CHECK: void __cdecl zeta(int __cdecl (*)(int, int))
??2@YAPAXI@Z
; CHECK: void *__cdecl operator new(unsigned int)
??3@YAXPAX@Z
; CHECK: void __cdecl operator delete(void *)
??_U@YAPAXI@Z
; CHECK: void *__cdecl operator new[](unsigned int)
??_V@YAXPAX@Z
; CHECK: void __cdecl operator delete[](void *)
?color1@@3PANA
; CHECK: double *color1
?color2@@3QBNB
; CHECK: double const *const color2
; FIXME-EXTRACONST: These tests fails because we print an extra const inside the parens.
; ?color3@@3QAY02$$CBNA
; FIXME-EXTRACONST: double const (*color3)[3]
; ?color4@@3QAY02$$CBNA
; FIXME-EXTRACONST: double const (*color4)[3]
; FIXME-MEMBERPTR: We don't support member pointers yet.
; ?memptr1@@3RESB@@HES1
; FIXME-MEMBERPTR: volatile int B::*memptr2
; ?memptr2@@3PESB@@HES1
; FIXME: volatile int B::*memptr2
; ?memptr3@@3REQB@@HEQ1
; FIXME-MEMBERPTR: int B::* volatile memptr3
; ?funmemptr1@@3RESB@@R6AHXZES1
; FIXME-MEMBERPTR: int __cdecl (* volatile B::* volatile funmemptr1)(void)
; ?funmemptr2@@3PESB@@R6AHXZES1
; FIXME-MEMBERPTR: int __cdecl (* volatile B::*funmemptr2)(void)
; ?funmemptr3@@3REQB@@P6AHXZEQ1
; FIXME-MEMBERPTR: int __cdecl (* B::*volatile funmemptr3)(void)
; ?memptrtofun1@@3R8B@@EAAXXZEQ1
; FIXME-MEMBERPTR: void __cdecl (B::*volatile memptrtofun1)(void)
; ?memptrtofun2@@3P8B@@EAAXXZEQ1
; FIXME-MEMBERPTR: void __cdecl (B::*memptrtofun2)(void)
; ?memptrtofun3@@3P8B@@EAAXXZEQ1
; FIXME-MEMBERPTR: void __cdecl (B::*memptrtofun3)(void)
; ?memptrtofun4@@3R8B@@EAAHXZEQ1
; FIXME-MEMBERPTR: int __cdecl (B::* volatile memptrtofun4)(void)
; ?memptrtofun5@@3P8B@@EAA?CHXZEQ1
; FIXME-MEMBERPTR: int volatile __cdecl (B::*memptrtofun5)(void)
; ?memptrtofun6@@3P8B@@EAA?BHXZEQ1
; FIXME-MEMBERPTR: int const __cdecl (B::*memptrtofun6)(void)
; ?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1
; FIXME-MEMBERPTR: int __cdecl (*(__cdecl B::*volatile memptrtofun7)(void))(void)
; ?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1
; FIXME-MEMBERPTR: int __cdecl (*(__cdecl B::*memptrtofun8)(void))(void)
; ?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1
; FIXME-MEMBERPTR: int __cdecl(*(__cdecl B::*memptrtofun9)(void))(void)
?fooE@@YA?AW4E@@XZ
; CHECK: enum E __cdecl fooE(void)
?fooE@@YA?AW4E@@XZ
; CHECK: enum E __cdecl fooE(void)
?fooX@@YA?AVX@@XZ
; CHECK: class X __cdecl fooX(void)
?fooX@@YA?AVX@@XZ
; CHECK: class X __cdecl fooX(void)
?s0@PR13182@@3PADA
; CHECK: char *PR13182::s0
?s1@PR13182@@3PADA
; CHECK: char *PR13182::s1
?s2@PR13182@@3QBDB
; CHECK: char const *const PR13182::s2
?s3@PR13182@@3QBDB
; CHECK: char const *const PR13182::s3
?s4@PR13182@@3RCDC
; CHECK: char volatile *volatile PR13182::s4
?s5@PR13182@@3SDDD
; CHECK: char const volatile *const volatile PR13182::s5
; undname adds an extra const in here, but it seems like their bug.
?s6@PR13182@@3PBQBDB
; CHECK: char const *const *PR13182::s6
; FIXME-EXTERNC: We don't properly support static locals in extern c functions yet.
; ?local@?1??extern_c_func@@9@4HA
; FIXME-EXTERNC: int `extern_c_func'::`2'::local
; ?local@?1??extern_c_func@@9@4HA
; FIXME-EXTERNC: int `extern_c_func'::`2'::local
??2OverloadedNewDelete@@SAPAXI@Z
; CHECK: static void *__cdecl OverloadedNewDelete::operator new(unsigned int)
??_UOverloadedNewDelete@@SAPAXI@Z
; CHECK: static void *__cdecl OverloadedNewDelete::operator new[](unsigned int)
??3OverloadedNewDelete@@SAXPAX@Z
; CHECK: static void __cdecl OverloadedNewDelete::operator delete(void *)
??_VOverloadedNewDelete@@SAXPAX@Z
; CHECK: static void __cdecl OverloadedNewDelete::operator delete[](void *)
??HOverloadedNewDelete@@QAEHH@Z
; CHECK: int __thiscall OverloadedNewDelete::operator+(int)
??2OverloadedNewDelete@@SAPEAX_K@Z
; CHECK: static void *__cdecl OverloadedNewDelete::operator new(unsigned __int64)
??_UOverloadedNewDelete@@SAPEAX_K@Z
; CHECK: static void *__cdecl OverloadedNewDelete::operator new[](unsigned __int64)
??3OverloadedNewDelete@@SAXPEAX@Z
; CHECK: static void __cdecl OverloadedNewDelete::operator delete(void *)
??_VOverloadedNewDelete@@SAXPEAX@Z
; CHECK: static void __cdecl OverloadedNewDelete::operator delete[](void *)
??HOverloadedNewDelete@@QEAAHH@Z
; CHECK: int __cdecl OverloadedNewDelete::operator+(int)
??2TypedefNewDelete@@SAPAXI@Z
; CHECK: static void *__cdecl TypedefNewDelete::operator new(unsigned int)
??_UTypedefNewDelete@@SAPAXI@Z
; CHECK: static void *__cdecl TypedefNewDelete::operator new[](unsigned int)
??3TypedefNewDelete@@SAXPAX@Z
; CHECK: static void __cdecl TypedefNewDelete::operator delete(void *)
??_VTypedefNewDelete@@SAXPAX@Z
; CHECK: static void __cdecl TypedefNewDelete::operator delete[](void *)
?vector_func@@YQXXZ
; CHECK: void __vectorcall vector_func(void)
; FIXME-EXTERNC: We don't support extern C funcs currently.
; ??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ
; FIXME-EXTERNC: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void)
; ?overloaded_fn@@$$J0YAXXZ
; FIXME-EXTERNC: extern \"C\" void __cdecl overloaded_fn(void)
?f@UnnamedType@@YAXUT2@S@1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T2)
?f@UnnamedType@@YAXPAUT4@S@1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4 *)
?f@UnnamedType@@YAXUT4@S@1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4)
?f@UnnamedType@@YAXUT5@S@1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T5)
?f@UnnamedType@@YAXUT2@S@1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T2)
?f@UnnamedType@@YAXUT4@S@1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T4)
?f@UnnamedType@@YAXUT5@S@1@@Z
; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::T5)
?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z
; CHECK: void __cdecl Atomic::f(struct __clang::_Atomic<int>)
?f@Complex@@YAXU?$_Complex@H@__clang@@@Z
; CHECK: void __cdecl Complex::f(struct __clang::_Complex<int>)
?f@Float16@@YAXU_Float16@__clang@@@Z
; CHECK: void __cdecl Float16::f(struct __clang::_Float16)
??0?$L@H@NS@@QEAA@XZ
; CHECK: __cdecl NS::L<int>::L<int>(void)
??0Bar@Foo@@QEAA@XZ
; CHECK: __cdecl Foo::Bar::Bar(void)
??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ
; CHECK: __thiscall PR26029::L<class PR26029::H<int *>>::L<class PR26029::H<int *>>(void)

View File

@ -0,0 +1,17 @@
; See clang/test/CodeGenCXX/mangle-windows.cpp
; These tests are based on clang/test/CodeGenCXX/mangle-ms.cpp
; RUN: llvm-undname < %s | FileCheck %s
; CHECK-NOT: Invalid mangled name
?bar@Foo@@SGXXZ
; CHECK: static void __stdcall Foo::bar(void)
?bar@Foo@@QAGXXZ
; CHECK: void __stdcall Foo::bar(void)
?f2@@YIXXZ
; CHECK: void __fastcall f2(void)
?f1@@YGXXZ
; CHECK: void __stdcall f1(void)

View File

@ -50,6 +50,7 @@ subdirectories =
llvm-rtdyld
llvm-size
llvm-split
llvm-undname
opt
verify-uselistorder

View File

@ -0,0 +1,8 @@
set(LLVM_LINK_COMPONENTS
Demangle
Support
)
add_llvm_tool(llvm-undname
llvm-undname.cpp
)

View File

@ -0,0 +1,23 @@
;===- ./tools/llvm-undname/LLVMBuild.txt -----------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Tool
name = llvm-undname
parent = Tools
required_libraries = Demangle Support

View File

@ -0,0 +1,79 @@
//===-- llvm-undname.cpp - Microsoft ABI name undecorator
//------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This utility works like the windows undname utility. It converts mangled
// Microsoft symbol names into pretty C/C++ human-readable names.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace llvm;
cl::list<std::string> Symbols(cl::Positional, cl::desc("<input symbols>"),
cl::ZeroOrMore);
static void demangle(const std::string &S) {
int Status;
char *ResultBuf = microsoftDemangle(S.c_str(), nullptr, nullptr, &Status);
if (Status == llvm::demangle_success) {
outs() << ResultBuf << "\n";
outs().flush();
} else {
errs() << "Error: Invalid mangled name\n";
}
std::free(ResultBuf);
};
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv, "llvm-undname\n");
if (Symbols.empty()) {
while (true) {
std::string LineStr;
std::getline(std::cin, LineStr);
if (std::cin.eof())
break;
StringRef Line(LineStr);
Line = Line.trim();
if (Line.empty() || Line.startswith("#") || Line.startswith(";"))
continue;
// If the user is manually typing in these decorated names, don't echo
// them to the terminal a second time. If they're coming from redirected
// input, however, then we should display the input line so that the
// mangled and demangled name can be easily correlated in the output.
if (!sys::Process::StandardInIsUserInput())
outs() << Line << "\n";
demangle(Line);
outs() << "\n";
}
} else {
for (StringRef S : Symbols) {
outs() << S << "\n";
demangle(S);
outs() << "\n";
}
}
return 0;
}