[llvm] [llvm-cxxfilt] Add --quote option to quote demangled function names (PR #111871)

Ronan Keryell via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 16 14:14:53 PDT 2024


https://github.com/keryell updated https://github.com/llvm/llvm-project/pull/111871

>From c2d7d4e950319208d78f917ea92d6cbf03e72d80 Mon Sep 17 00:00:00 2001
From: Ronan Keryell <ronan.keryell at amd.com>
Date: Wed, 9 Oct 2024 19:39:24 -0700
Subject: [PATCH 1/5] [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.
---
 llvm/docs/CommandGuide/llvm-cxxfilt.rst  |  5 +++++
 llvm/test/tools/llvm-cxxfilt/quote.test  | 12 ++++++++++++
 llvm/tools/llvm-cxxfilt/Opts.td          |  2 ++
 llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp | 24 +++++++++++++++++++-----
 4 files changed, 38 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/tools/llvm-cxxfilt/quote.test

diff --git a/llvm/docs/CommandGuide/llvm-cxxfilt.rst b/llvm/docs/CommandGuide/llvm-cxxfilt.rst
index 0933f0b5bed878..ea90a05bcd4338 100644
--- a/llvm/docs/CommandGuide/llvm-cxxfilt.rst
+++ b/llvm/docs/CommandGuide/llvm-cxxfilt.rst
@@ -52,6 +52,11 @@ OPTIONS
 
   Do not demangle function parameters or return types.
 
+.. option:: --quote, -q
+
+  Add `"` `"` around demangled function symbols, typically to keep LLVM/MLIR
+  assembly files with `@<symbols>` valid. Do not quote already quoted symbols.
+
 .. option:: --no-strip-underscore, -n
 
   Do not strip a leading underscore. This is the default for all platforms
diff --git a/llvm/test/tools/llvm-cxxfilt/quote.test b/llvm/test/tools/llvm-cxxfilt/quote.test
new file mode 100644
index 00000000000000..1420c14efbbfbc
--- /dev/null
+++ b/llvm/test/tools/llvm-cxxfilt/quote.test
@@ -0,0 +1,12 @@
+// Show that llvm-cxxfilt --quote can emit quoted demangled symbols but not
+// without double-quoting in the case they are already quoted
+
+RUN: llvm-cxxfilt --quote < %s | FileCheck %s
+      cir.call @_ZN3aie4tileILi1ELi4EE7programIZ4mainE3$_0EEvOT_(%2, %7) : (!cir.ptr<!ty_aie3A3Atile3C12C_43E>, !cir.ptr<!ty_anon2E0_>) -> () loc(#loc74)
+  cir.func lambda internal private  @_ZZ4mainENK3$_1clEv(%arg0: !cir.ptr<!ty_anon2E1_> loc("example.cpp":31:26)) extra(#fn_attr) {
+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]>]]}
+
+CHECK: cir.call @"void aie::tile<1, 4>::program<main::$_0>(main::$_0&&)"(%2, %7) 
+CHECK-NEXT: cir.func lambda internal private  @"main::$_1::operator()() const"(%arg0: !cir.ptr<!ty_anon2E1_>
+// \todo Is there a simpler way to escape these [[ leading to "error: invalid variable name" otherwise?
+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]>]]}
diff --git a/llvm/tools/llvm-cxxfilt/Opts.td b/llvm/tools/llvm-cxxfilt/Opts.td
index 034cb267aab800..e69082ba05e3a4 100644
--- a/llvm/tools/llvm-cxxfilt/Opts.td
+++ b/llvm/tools/llvm-cxxfilt/Opts.td
@@ -15,6 +15,7 @@ multiclass Eq<string name, string help> {
 }
 
 def help : FF<"help", "Display this help">;
+def quote : FF<"quote", "Quote demangled function names with \" \" if not already quoted. Useful for symbols appearing after an @ in MLIR/LLVM assembly">;
 defm strip_underscore : BB<"strip-underscore", "Strip the leading underscore", "Don't strip the leading underscore">;
 def types : FF<"types", "Attempt to demangle types as well as function names">;
 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>;
 def : F<"h", "Alias for --help">, Alias<help>;
 def : F<"n", "Alias for --no-strip-underscore">, Alias<no_strip_underscore>;
 def : F<"p", "Alias for --no-params">, Alias<no_params>;
+def : F<"q", "Alias for --quote">, Alias<quote>;
 def : F<"t", "Alias for --types">, Alias<types>;
diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index f90adb6cacb990..f3f11e488d2c3d 100644
--- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -20,6 +20,7 @@
 #include "llvm/TargetParser/Triple.h"
 #include <cstdlib>
 #include <iostream>
+#include <string>
 
 using namespace llvm;
 
@@ -54,6 +55,7 @@ class CxxfiltOptTable : public opt::GenericOptTable {
 } // namespace
 
 static bool ParseParams;
+static bool Quote;
 static bool StripUnderscore;
 static bool Types;
 
@@ -64,7 +66,15 @@ static void error(const Twine &Message) {
   exit(1);
 }
 
-static std::string demangle(const std::string &Mangled) {
+// Quote Undecorated with "" if asked for and not already followed by a '"'
+static std::string optionalQuote(std::string Undecorated,
+                                 StringRef Delimiters) {
+  if (Quote && (Delimiters.empty() || Delimiters[0] != '"'))
+    return '"' + Undecorated + '"';
+  return Undecorated;
+}
+
+static std::string demangle(const std::string &Mangled, StringRef Delimiters) {
   using llvm::itanium_demangle::starts_with;
   std::string_view DecoratedStr = Mangled;
   bool CanHaveLeadingDot = true;
@@ -76,7 +86,7 @@ static std::string demangle(const std::string &Mangled) {
   std::string Result;
   if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot,
                            ParseParams))
-    return Result;
+    return optionalQuote(Result, Delimiters);
 
   std::string Prefix;
   char *Undecorated = nullptr;
@@ -89,7 +99,8 @@ static std::string demangle(const std::string &Mangled) {
     Undecorated = itaniumDemangle(DecoratedStr.substr(6), ParseParams);
   }
 
-  Result = Undecorated ? Prefix + Undecorated : Mangled;
+  Result =
+      Undecorated ? Prefix + optionalQuote(Undecorated, Delimiters) : Mangled;
   free(Undecorated);
   return Result;
 }
@@ -137,9 +148,10 @@ static void demangleLine(llvm::raw_ostream &OS, StringRef Mangled, bool Split) {
     SmallVector<std::pair<StringRef, StringRef>, 16> Words;
     SplitStringDelims(Mangled, Words, IsLegalItaniumChar);
     for (const auto &Word : Words)
-      Result += ::demangle(std::string(Word.first)) + Word.second.str();
+      Result +=
+          ::demangle(std::string(Word.first), Word.second) + Word.second.str();
   } else
-    Result = ::demangle(std::string(Mangled));
+    Result = ::demangle(std::string(Mangled), "");
   OS << Result << '\n';
   OS.flush();
 }
@@ -172,6 +184,8 @@ int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) {
 
   Types = Args.hasArg(OPT_types);
 
+  Quote = Args.hasArg(OPT_quote);
+
   std::vector<std::string> Decorated = Args.getAllArgValues(OPT_INPUT);
   if (Decorated.empty())
     for (std::string Mangled; std::getline(std::cin, Mangled);)

>From d3553f3f1be0f92ea3b78885a52b4755dafdf44a Mon Sep 17 00:00:00 2001
From: Ronan Keryell <ronan.keryell at amd.com>
Date: Sat, 12 Oct 2024 04:35:53 -0700
Subject: [PATCH 2/5] [llvm-cxxfilt] Apply PR review feedback

Thanks @jh7370
---
 llvm/docs/CommandGuide/llvm-cxxfilt.rst  |  6 ++---
 llvm/test/tools/llvm-cxxfilt/quote.test  | 28 ++++++++++++++----------
 llvm/tools/llvm-cxxfilt/Opts.td          |  3 +--
 llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp |  1 -
 4 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/llvm/docs/CommandGuide/llvm-cxxfilt.rst b/llvm/docs/CommandGuide/llvm-cxxfilt.rst
index ea90a05bcd4338..d0178805589eaf 100644
--- a/llvm/docs/CommandGuide/llvm-cxxfilt.rst
+++ b/llvm/docs/CommandGuide/llvm-cxxfilt.rst
@@ -52,10 +52,10 @@ OPTIONS
 
   Do not demangle function parameters or return types.
 
-.. option:: --quote, -q
+.. option:: --quote
 
-  Add `"` `"` around demangled function symbols, typically to keep LLVM/MLIR
-  assembly files with `@<symbols>` valid. Do not quote already quoted symbols.
+  Add `"` `"` around demangled function symbols.
+  Do not quote already quoted symbols.
 
 .. option:: --no-strip-underscore, -n
 
diff --git a/llvm/test/tools/llvm-cxxfilt/quote.test b/llvm/test/tools/llvm-cxxfilt/quote.test
index 1420c14efbbfbc..255031fc10c49f 100644
--- a/llvm/test/tools/llvm-cxxfilt/quote.test
+++ b/llvm/test/tools/llvm-cxxfilt/quote.test
@@ -1,12 +1,18 @@
-// Show that llvm-cxxfilt --quote can emit quoted demangled symbols but not
-// without double-quoting in the case they are already quoted
+// Show that llvm-cxxfilt --quote can emit quoted demangled symbols (even at the
+// end of a line) but not without double-quoting in the case they are already
+// quoted.
+RUN: echo _Z3barv '"_Z3barv"' > %t
+RUN: echo '"_Z3barv"' _Z3barv >> %t
+// This is not mangled, thus it should not be quoted
+RUN: echo 'log()' >> %t
+RUN: llvm-cxxfilt --quote < %t | FileCheck --match-full-lines --check-prefix=CHECK-FILE %s
+CHECK-FILE: "bar()" "bar()"
+CHECK-FILE-NEXT: "bar()" "bar()"
+CHECK-FILE-NEXT: log()
 
-RUN: llvm-cxxfilt --quote < %s | FileCheck %s
-      cir.call @_ZN3aie4tileILi1ELi4EE7programIZ4mainE3$_0EEvOT_(%2, %7) : (!cir.ptr<!ty_aie3A3Atile3C12C_43E>, !cir.ptr<!ty_anon2E0_>) -> () loc(#loc74)
-  cir.func lambda internal private  @_ZZ4mainENK3$_1clEv(%arg0: !cir.ptr<!ty_anon2E1_> loc("example.cpp":31:26)) extra(#fn_attr) {
-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]>]]}
-
-CHECK: cir.call @"void aie::tile<1, 4>::program<main::$_0>(main::$_0&&)"(%2, %7) 
-CHECK-NEXT: cir.func lambda internal private  @"main::$_1::operator()() const"(%arg0: !cir.ptr<!ty_anon2E1_>
-// \todo Is there a simpler way to escape these [[ leading to "error: invalid variable name" otherwise?
-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]>]]}
+// Check it works with cli symbols too. Since a quoted mangled name is not a
+// mangled name, it should be unchanged
+RUN: llvm-cxxfilt --quote _Z3firv '"_Z3barv"' 'saw()' | FileCheck --match-full-lines --check-prefix=CHECK-CLI %s
+CHECK-CLI: "fir()"
+CHECK-CLI: "_Z3barv"
+CHECK-CLI: saw()
diff --git a/llvm/tools/llvm-cxxfilt/Opts.td b/llvm/tools/llvm-cxxfilt/Opts.td
index e69082ba05e3a4..a40bc75354a133 100644
--- a/llvm/tools/llvm-cxxfilt/Opts.td
+++ b/llvm/tools/llvm-cxxfilt/Opts.td
@@ -15,7 +15,7 @@ multiclass Eq<string name, string help> {
 }
 
 def help : FF<"help", "Display this help">;
-def quote : FF<"quote", "Quote demangled function names with \" \" if not already quoted. Useful for symbols appearing after an @ in MLIR/LLVM assembly">;
+def quote : FF<"quote", "Quote demangled function names with \" \" if not already quoted">;
 defm strip_underscore : BB<"strip-underscore", "Strip the leading underscore", "Don't strip the leading underscore">;
 def types : FF<"types", "Attempt to demangle types as well as function names">;
 def no_params : FF<"no-params", "Skip function parameters and return types">;
@@ -28,5 +28,4 @@ def : F<"_", "Alias for --strip-underscore">, Alias<strip_underscore>;
 def : F<"h", "Alias for --help">, Alias<help>;
 def : F<"n", "Alias for --no-strip-underscore">, Alias<no_strip_underscore>;
 def : F<"p", "Alias for --no-params">, Alias<no_params>;
-def : F<"q", "Alias for --quote">, Alias<quote>;
 def : F<"t", "Alias for --types">, Alias<types>;
diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index f3f11e488d2c3d..07783c4554bc33 100644
--- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -20,7 +20,6 @@
 #include "llvm/TargetParser/Triple.h"
 #include <cstdlib>
 #include <iostream>
-#include <string>
 
 using namespace llvm;
 

>From 0ca719515a4ec33161315e6384ea2566a7a12d09 Mon Sep 17 00:00:00 2001
From: Ronan Keryell <ronan.keryell at amd.com>
Date: Tue, 15 Oct 2024 11:29:38 -0700
Subject: [PATCH 3/5] [llvm-cxxfilt] Make --quote to work with "import thunk
 for" prefix

---
 llvm/test/tools/llvm-cxxfilt/quote.test  | 3 +++
 llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/llvm/test/tools/llvm-cxxfilt/quote.test b/llvm/test/tools/llvm-cxxfilt/quote.test
index 255031fc10c49f..a7265724442c8c 100644
--- a/llvm/test/tools/llvm-cxxfilt/quote.test
+++ b/llvm/test/tools/llvm-cxxfilt/quote.test
@@ -5,10 +5,13 @@ RUN: echo _Z3barv '"_Z3barv"' > %t
 RUN: echo '"_Z3barv"' _Z3barv >> %t
 // This is not mangled, thus it should not be quoted
 RUN: echo 'log()' >> %t
+// Check that an "import thunk for" prefix can be quoted along the demangled name
+RUN: echo __imp__ZSt6futureIvE >> %t
 RUN: llvm-cxxfilt --quote < %t | FileCheck --match-full-lines --check-prefix=CHECK-FILE %s
 CHECK-FILE: "bar()" "bar()"
 CHECK-FILE-NEXT: "bar()" "bar()"
 CHECK-FILE-NEXT: log()
+CHECK-FILE-NEXT: "import thunk for std::future<void>"
 
 // Check it works with cli symbols too. Since a quoted mangled name is not a
 // mangled name, it should be unchanged
diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index 07783c4554bc33..1a113763501bd9 100644
--- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -66,7 +66,7 @@ static void error(const Twine &Message) {
 }
 
 // Quote Undecorated with "" if asked for and not already followed by a '"'
-static std::string optionalQuote(std::string Undecorated,
+static std::string optionalQuote(const std::string &Undecorated,
                                  StringRef Delimiters) {
   if (Quote && (Delimiters.empty() || Delimiters[0] != '"'))
     return '"' + Undecorated + '"';
@@ -99,7 +99,7 @@ static std::string demangle(const std::string &Mangled, StringRef Delimiters) {
   }
 
   Result =
-      Undecorated ? Prefix + optionalQuote(Undecorated, Delimiters) : Mangled;
+      Undecorated ? optionalQuote(Prefix + Undecorated, Delimiters) : Mangled;
   free(Undecorated);
   return Result;
 }

>From ecd1d779107eae95aa22c3f2adc473eae72f624f Mon Sep 17 00:00:00 2001
From: Ronan Keryell <ronan.keryell at amd.com>
Date: Wed, 16 Oct 2024 11:58:27 -0700
Subject: [PATCH 4/5] Commit suggestion on
 llvm/test/tools/llvm-cxxfilt/quote.test

Co-authored-by: James Henderson <46713263+jh7370 at users.noreply.github.com>
---
 llvm/test/tools/llvm-cxxfilt/quote.test | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/test/tools/llvm-cxxfilt/quote.test b/llvm/test/tools/llvm-cxxfilt/quote.test
index a7265724442c8c..2e9bfe779b9020 100644
--- a/llvm/test/tools/llvm-cxxfilt/quote.test
+++ b/llvm/test/tools/llvm-cxxfilt/quote.test
@@ -1,6 +1,4 @@
-// Show that llvm-cxxfilt --quote can emit quoted demangled symbols (even at the
-// end of a line) but not without double-quoting in the case they are already
-// quoted.
+// Show that llvm-cxxfilt --quote adds quotes around demangled symbols, unless the symbol is already quoted.
 RUN: echo _Z3barv '"_Z3barv"' > %t
 RUN: echo '"_Z3barv"' _Z3barv >> %t
 // This is not mangled, thus it should not be quoted

>From 2e070dbc587a4e1d0f6bbcaf1c3970f532803c5d Mon Sep 17 00:00:00 2001
From: Ronan Keryell <ronan.keryell at amd.com>
Date: Wed, 16 Oct 2024 14:03:17 -0700
Subject: [PATCH 5/5] [llvm-cxxfilt][NFC] Use split-file to avoid echo abuse

Apply reviews from @jh7370.
---
 llvm/docs/CommandGuide/llvm-cxxfilt.rst |  4 ++--
 llvm/test/tools/llvm-cxxfilt/quote.test | 29 +++++++++++++++----------
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/llvm/docs/CommandGuide/llvm-cxxfilt.rst b/llvm/docs/CommandGuide/llvm-cxxfilt.rst
index d0178805589eaf..e4ef531b0a2ee7 100644
--- a/llvm/docs/CommandGuide/llvm-cxxfilt.rst
+++ b/llvm/docs/CommandGuide/llvm-cxxfilt.rst
@@ -54,8 +54,8 @@ OPTIONS
 
 .. option:: --quote
 
-  Add `"` `"` around demangled function symbols.
-  Do not quote already quoted symbols.
+  Add `"` `"` around demangled function symbols. Do not quote already quoted
+  symbols.
 
 .. option:: --no-strip-underscore, -n
 
diff --git a/llvm/test/tools/llvm-cxxfilt/quote.test b/llvm/test/tools/llvm-cxxfilt/quote.test
index 2e9bfe779b9020..7153c5bbd4d4d0 100644
--- a/llvm/test/tools/llvm-cxxfilt/quote.test
+++ b/llvm/test/tools/llvm-cxxfilt/quote.test
@@ -1,19 +1,24 @@
 // Show that llvm-cxxfilt --quote adds quotes around demangled symbols, unless the symbol is already quoted.
-RUN: echo _Z3barv '"_Z3barv"' > %t
-RUN: echo '"_Z3barv"' _Z3barv >> %t
-// This is not mangled, thus it should not be quoted
-RUN: echo 'log()' >> %t
-// Check that an "import thunk for" prefix can be quoted along the demangled name
-RUN: echo __imp__ZSt6futureIvE >> %t
-RUN: llvm-cxxfilt --quote < %t | FileCheck --match-full-lines --check-prefix=CHECK-FILE %s
+
+RUN: split-file %s %t
+
+RUN: llvm-cxxfilt --quote < %t/symbols-in-file.test | FileCheck --match-full-lines --check-prefix=CHECK-FILE %s
 CHECK-FILE: "bar()" "bar()"
 CHECK-FILE-NEXT: "bar()" "bar()"
-CHECK-FILE-NEXT: log()
-CHECK-FILE-NEXT: "import thunk for std::future<void>"
+CHECK-FILE: log()
+CHECK-FILE: "import thunk for std::future<void>"
 
-// Check it works with cli symbols too. Since a quoted mangled name is not a
+// Check it works with CLI symbols too. Since a quoted mangled name is not a
 // mangled name, it should be unchanged
 RUN: llvm-cxxfilt --quote _Z3firv '"_Z3barv"' 'saw()' | FileCheck --match-full-lines --check-prefix=CHECK-CLI %s
 CHECK-CLI: "fir()"
-CHECK-CLI: "_Z3barv"
-CHECK-CLI: saw()
+CHECK-CLI-NEXT: "_Z3barv"
+CHECK-CLI-NEXT: saw()
+
+//--- symbols-in-file.test
+_Z3barv "_Z3barv"
+"_Z3barv" _Z3barv
+// This is not mangled, thus it should not be quoted
+log()
+// Check that an "import thunk for" prefix can be quoted along the demangled name
+__imp__ZSt6futureIvE



More information about the llvm-commits mailing list