[llvm] b21ea1c - [Demangle] Add support for D types back referencing

Luís Ferreira via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 12 14:01:52 PST 2022


Author: Luís Ferreira
Date: 2022-01-12T21:57:31Z
New Revision: b21ea1c2701d754072b679c27df75c43699a2623

URL: https://github.com/llvm/llvm-project/commit/b21ea1c2701d754072b679c27df75c43699a2623
DIFF: https://github.com/llvm/llvm-project/commit/b21ea1c2701d754072b679c27df75c43699a2623.diff

LOG: [Demangle] Add support for D types back referencing

    This patch adds support for type back referencing, allowing demangling of
    compressed mangled symbols with repetitive types.

    Signed-off-by: Luís Ferreira <contact at lsferreira.net>

Reviewed By: dblaikie

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

Added: 
    

Modified: 
    llvm/lib/Demangle/DLangDemangle.cpp
    llvm/unittests/Demangle/DLangDemangleTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Demangle/DLangDemangle.cpp b/llvm/lib/Demangle/DLangDemangle.cpp
index 086c76557f5b9..9c0ea7a51bf4c 100644
--- a/llvm/lib/Demangle/DLangDemangle.cpp
+++ b/llvm/lib/Demangle/DLangDemangle.cpp
@@ -105,6 +105,17 @@ struct Demangler {
   /// \see https://dlang.org/spec/abi.html#IdentifierBackRef .
   const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled);
 
+  /// Extract and demangle backreferenced type from a given mangled symbol
+  /// and append it to the output string.
+  ///
+  /// \param Mangled mangled symbol to be demangled.
+  ///
+  /// \return the remaining string on success or nullptr on failure.
+  ///
+  /// \see https://dlang.org/spec/abi.html#back_ref .
+  /// \see https://dlang.org/spec/abi.html#TypeBackRef .
+  const char *parseTypeBackref(const char *Mangled);
+
   /// Check whether it is the beginning of a symbol name.
   ///
   /// \param Mangled string to extract the symbol name.
@@ -162,6 +173,8 @@ struct Demangler {
 
   /// The string we are demangling.
   const char *Str;
+  /// The index of the last back reference.
+  int LastBackref;
 };
 
 } // namespace
@@ -276,6 +289,39 @@ const char *Demangler::parseSymbolBackref(OutputBuffer *Demangled,
   return Mangled;
 }
 
+const char *Demangler::parseTypeBackref(const char *Mangled) {
+  // A type back reference always points to a letter.
+  //    TypeBackRef:
+  //        Q NumberBackRef
+  //        ^
+  const char *Backref;
+
+  // If we appear to be moving backwards through the mangle string, then
+  // bail as this may be a recursive back reference.
+  if (Mangled - Str >= LastBackref)
+    return nullptr;
+
+  int SaveRefPos = LastBackref;
+  LastBackref = Mangled - Str;
+
+  // Get position of the back reference.
+  Mangled = decodeBackref(Mangled, Backref);
+
+  // Can't decode back reference.
+  if (Backref == nullptr)
+    return nullptr;
+
+  // TODO: Add support for function type back references.
+  Backref = parseType(Backref);
+
+  LastBackref = SaveRefPos;
+
+  if (Backref == nullptr)
+    return nullptr;
+
+  return Mangled;
+}
+
 bool Demangler::isSymbolName(const char *Mangled) {
   long Ret;
   const char *Qref = Mangled;
@@ -423,7 +469,10 @@ const char *Demangler::parseType(const char *Mangled) {
     return Mangled;
 
     // TODO: Add support for the rest of the basic types.
-    // TODO: Parse back referenced types.
+
+  // Back referenced type.
+  case 'Q':
+    return parseTypeBackref(Mangled);
 
   default: // unhandled.
     return nullptr;
@@ -487,7 +536,8 @@ const char *Demangler::parseLName(OutputBuffer *Demangled, const char *Mangled,
   return Mangled;
 }
 
-Demangler::Demangler(const char *Mangled) : Str(Mangled) {}
+Demangler::Demangler(const char *Mangled)
+    : Str(Mangled), LastBackref(strlen(Mangled)) {}
 
 const char *Demangler::parseMangle(OutputBuffer *Demangled) {
   return parseMangle(Demangled, this->Str);

diff  --git a/llvm/unittests/Demangle/DLangDemangleTest.cpp b/llvm/unittests/Demangle/DLangDemangleTest.cpp
index d76bf36c14598..dd0c699d5c186 100644
--- a/llvm/unittests/Demangle/DLangDemangleTest.cpp
+++ b/llvm/unittests/Demangle/DLangDemangleTest.cpp
@@ -63,4 +63,13 @@ INSTANTIATE_TEST_SUITE_P(
         std::make_pair("_D8demangle3ABCQa1ai",
                        nullptr), // invalid symbol back reference (recursive).
         std::make_pair("_D8demangleQDXXXXXXXXXXXXx",
-                       nullptr))); // overflow back reference position.
+                       nullptr), // overflow back reference position.
+        std::make_pair(
+            "_D8demangle4ABCi1aQd",
+            "demangle.ABCi.a"), // type back reference: `Qd` is a back reference
+                                // for position 4, counting from `d` char, so
+                                // decoding it points to `i`.
+        std::make_pair("_D8demangle3fooQXXXx",
+                       nullptr), // invalid type back reference position.
+        std::make_pair("_D8demangle5recurQa",
+                       nullptr))); // invalid type back reference (recursive).


        


More information about the llvm-commits mailing list