Skip to content

Commit c2d7d4e

Browse files
committed
[llvm-cxxfilt] Add --quote option to quote demangled function names
This is useful when looking at LLVM/MLIR assembly produced from C++ sources. For example cir.call @_ZN3aie4tileILi1ELi4EE7programIZ4mainE3$_0EEvOT_(%2, %7) : will be translated to cir.call @"void aie::tile<1, 4>::program<main::$_0>(main::$_0&&)"(%2, %7) : which can be parsed as valid MLIR by the right mlir-lsp-server. If a symbol is already quoted, do not quote it more.
1 parent c04b640 commit c2d7d4e

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

llvm/docs/CommandGuide/llvm-cxxfilt.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ OPTIONS
5252

5353
Do not demangle function parameters or return types.
5454

55+
.. option:: --quote, -q
56+
57+
Add `"` `"` around demangled function symbols, typically to keep LLVM/MLIR
58+
assembly files with `@<symbols>` valid. Do not quote already quoted symbols.
59+
5560
.. option:: --no-strip-underscore, -n
5661

5762
Do not strip a leading underscore. This is the default for all platforms
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Show that llvm-cxxfilt --quote can emit quoted demangled symbols but not
2+
// without double-quoting in the case they are already quoted
3+
4+
RUN: llvm-cxxfilt --quote < %s | FileCheck %s
5+
cir.call @_ZN3aie4tileILi1ELi4EE7programIZ4mainE3$_0EEvOT_(%2, %7) : (!cir.ptr<!ty_aie3A3Atile3C12C_43E>, !cir.ptr<!ty_anon2E0_>) -> () loc(#loc74)
6+
cir.func lambda internal private @_ZZ4mainENK3$_1clEv(%arg0: !cir.ptr<!ty_anon2E1_> loc("example.cpp":31:26)) extra(#fn_attr) {
7+
module @"example.cpp" attributes {cir.global_annotations = #cir<global_annotations [["_ZN3aie6deviceILNS_3$_0E42EE4tileILi1ELi4EEENS_4tileIXT_EXT0_EEEv", #cir.annotation<name = "aie.device.tile", args = [1 : i32, 4 : i32, 42 : i8, 42 : i8]>]]}
8+
9+
CHECK: cir.call @"void aie::tile<1, 4>::program<main::$_0>(main::$_0&&)"(%2, %7)
10+
CHECK-NEXT: cir.func lambda internal private @"main::$_1::operator()() const"(%arg0: !cir.ptr<!ty_anon2E1_>
11+
// \todo Is there a simpler way to escape these [[ leading to "error: invalid variable name" otherwise?
12+
CHECK-NEXT: module @"example.cpp" attributes {cir.global_annotations = #cir<global_annotations {{[[]}}["aie::tile<1, 4> aie::device<(aie::$_0)42>::tile<1, 4>()", #cir.annotation<name = "aie.device.tile", args = [1 : i32, 4 : i32, 42 : i8, 42 : i8]>]]}

llvm/tools/llvm-cxxfilt/Opts.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ multiclass Eq<string name, string help> {
1515
}
1616

1717
def help : FF<"help", "Display this help">;
18+
def quote : FF<"quote", "Quote demangled function names with \" \" if not already quoted. Useful for symbols appearing after an @ in MLIR/LLVM assembly">;
1819
defm strip_underscore : BB<"strip-underscore", "Strip the leading underscore", "Don't strip the leading underscore">;
1920
def types : FF<"types", "Attempt to demangle types as well as function names">;
2021
def no_params : FF<"no-params", "Skip function parameters and return types">;
@@ -27,4 +28,5 @@ def : F<"_", "Alias for --strip-underscore">, Alias<strip_underscore>;
2728
def : F<"h", "Alias for --help">, Alias<help>;
2829
def : F<"n", "Alias for --no-strip-underscore">, Alias<no_strip_underscore>;
2930
def : F<"p", "Alias for --no-params">, Alias<no_params>;
31+
def : F<"q", "Alias for --quote">, Alias<quote>;
3032
def : F<"t", "Alias for --types">, Alias<types>;

llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/TargetParser/Triple.h"
2121
#include <cstdlib>
2222
#include <iostream>
23+
#include <string>
2324

2425
using namespace llvm;
2526

@@ -54,6 +55,7 @@ class CxxfiltOptTable : public opt::GenericOptTable {
5455
} // namespace
5556

5657
static bool ParseParams;
58+
static bool Quote;
5759
static bool StripUnderscore;
5860
static bool Types;
5961

@@ -64,7 +66,15 @@ static void error(const Twine &Message) {
6466
exit(1);
6567
}
6668

67-
static std::string demangle(const std::string &Mangled) {
69+
// Quote Undecorated with "" if asked for and not already followed by a '"'
70+
static std::string optionalQuote(std::string Undecorated,
71+
StringRef Delimiters) {
72+
if (Quote && (Delimiters.empty() || Delimiters[0] != '"'))
73+
return '"' + Undecorated + '"';
74+
return Undecorated;
75+
}
76+
77+
static std::string demangle(const std::string &Mangled, StringRef Delimiters) {
6878
using llvm::itanium_demangle::starts_with;
6979
std::string_view DecoratedStr = Mangled;
7080
bool CanHaveLeadingDot = true;
@@ -76,7 +86,7 @@ static std::string demangle(const std::string &Mangled) {
7686
std::string Result;
7787
if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot,
7888
ParseParams))
79-
return Result;
89+
return optionalQuote(Result, Delimiters);
8090

8191
std::string Prefix;
8292
char *Undecorated = nullptr;
@@ -89,7 +99,8 @@ static std::string demangle(const std::string &Mangled) {
8999
Undecorated = itaniumDemangle(DecoratedStr.substr(6), ParseParams);
90100
}
91101

92-
Result = Undecorated ? Prefix + Undecorated : Mangled;
102+
Result =
103+
Undecorated ? Prefix + optionalQuote(Undecorated, Delimiters) : Mangled;
93104
free(Undecorated);
94105
return Result;
95106
}
@@ -137,9 +148,10 @@ static void demangleLine(llvm::raw_ostream &OS, StringRef Mangled, bool Split) {
137148
SmallVector<std::pair<StringRef, StringRef>, 16> Words;
138149
SplitStringDelims(Mangled, Words, IsLegalItaniumChar);
139150
for (const auto &Word : Words)
140-
Result += ::demangle(std::string(Word.first)) + Word.second.str();
151+
Result +=
152+
::demangle(std::string(Word.first), Word.second) + Word.second.str();
141153
} else
142-
Result = ::demangle(std::string(Mangled));
154+
Result = ::demangle(std::string(Mangled), "");
143155
OS << Result << '\n';
144156
OS.flush();
145157
}
@@ -172,6 +184,8 @@ int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) {
172184

173185
Types = Args.hasArg(OPT_types);
174186

187+
Quote = Args.hasArg(OPT_quote);
188+
175189
std::vector<std::string> Decorated = Args.getAllArgValues(OPT_INPUT);
176190
if (Decorated.empty())
177191
for (std::string Mangled; std::getline(std::cin, Mangled);)

0 commit comments

Comments
 (0)