labath created this revision.
labath added reviewers: sgraenitz, erik.pilkington, JDevlieghere.

Now that llvm demangler supports more generic customization, we can
implement type substitution directly on top of this API. This will allow
us to remove the specialized hooks which were added to the demangler to
support this use case.


https://reviews.llvm.org/D54074

Files:
  source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Index: source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -21,7 +21,7 @@
 
 // Other libraries and framework includes
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Demangle/Demangle.h"
+#include "llvm/Demangle/ItaniumDemangle.h"
 
 // Project includes
 #include "lldb/Core/PluginManager.h"
@@ -274,72 +274,67 @@
   return false;
 }
 
-/// Given a mangled function `mangled`, replace all the primitive function type
-/// arguments of `search` with type `replace`.
-static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
-                                            llvm::StringRef search,
-                                            llvm::StringRef replace) {
-  class PrimitiveParmSubs {
-    llvm::StringRef mangled;
-    llvm::StringRef search;
-    llvm::StringRef replace;
-    ptrdiff_t read_pos;
-    std::string output;
-    std::back_insert_iterator<std::string> writer;
+namespace {
+class NodeAllocator {
+  llvm::BumpPtrAllocator Alloc;
 
-  public:
-    PrimitiveParmSubs(llvm::StringRef m, llvm::StringRef s, llvm::StringRef r)
-        : mangled(m), search(s), replace(r), read_pos(0),
-          writer(std::back_inserter(output)) {}
-
-    void Substitute(llvm::StringRef tail) {
-      assert(tail.data() >= mangled.data() &&
-             tail.data() < mangled.data() + mangled.size() &&
-             "tail must point into range of mangled");
-
-      if (tail.startswith(search)) {
-        auto reader = mangled.begin() + read_pos;
-        ptrdiff_t read_len = tail.data() - (mangled.data() + read_pos);
-
-        // First write the unmatched part of the original. Then write the
-        // replacement string. Finally skip the search string in the original.
-        writer = std::copy(reader, reader + read_len, writer);
-        writer = std::copy(replace.begin(), replace.end(), writer);
-        read_pos += read_len + search.size();
-      }
-    }
+public:
+  void reset() { Alloc.Reset(); }
 
-    ConstString Finalize() {
-      // If we did a substitution, write the remaining part of the original.
-      if (read_pos > 0) {
-        writer = std::copy(mangled.begin() + read_pos, mangled.end(), writer);
-        read_pos = mangled.size();
-      }
+  template <typename T, typename... Args> T *makeNode(Args &&... args) {
+    return new (Alloc.Allocate(sizeof(T), alignof(T)))
+        T(std::forward<Args>(args)...);
+  }
 
-      return ConstString(output);
+  void *allocateNodeArray(size_t sz) {
+    return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
+                          alignof(llvm::itanium_demangle::Node *));
+  }
+};
+
+/// Given a mangled function `Mangled`, replace all the primitive function type
+/// arguments of `Search` with type `Replace`.
+class TypeSubstitutor
+    : public llvm::itanium_demangle::AbstractManglingParser<TypeSubstitutor,
+                                                            NodeAllocator> {
+  const char *Written;
+  llvm::StringRef Search;
+  llvm::StringRef Replace;
+  llvm::SmallString<128> Result;
+  llvm::raw_svector_ostream OS{Result};
+  bool Substituted = false;
+
+  TypeSubstitutor(llvm::StringRef Mangled, llvm::StringRef Search,
+                  llvm::StringRef Replace)
+      : AbstractManglingParser(Mangled.begin(), Mangled.end()),
+        Written(Mangled.begin()), Search(Search), Replace(Replace) {}
+
+public:
+  static ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
+                                llvm::StringRef To) {
+    Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+
+    TypeSubstitutor TS(Mangled, From, To);
+    if (TS.parse() == nullptr) {
+      LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
+      return ConstString();
     }
+    if (!TS.Substituted)
+      return ConstString();
+    TS.OS << llvm::StringRef(TS.Written, TS.First - TS.Written);
+    LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, TS.OS.str());
+    return ConstString(TS.OS.str());
+  }
 
-    static void Callback(void *context, const char *match) {
-      ((PrimitiveParmSubs *)context)->Substitute(llvm::StringRef(match));
+  llvm::itanium_demangle::Node *parseType() {
+    if (llvm::StringRef(First, Last - First).startswith(Search)) {
+      OS << llvm::StringRef(Written, First - Written) << Replace;
+      Written = First + Search.size();
+      Substituted = true;
     }
-  };
-
-  // The demangler will call back for each instance of a primitive type,
-  // allowing us to perform substitution
-  PrimitiveParmSubs parmSubs(mangled, search, replace);
-  assert(mangled.data()[mangled.size()] == '\0' && "Expect C-String");
-  bool err = llvm::itaniumFindTypesInMangledName(mangled.data(), &parmSubs,
-                                                 PrimitiveParmSubs::Callback);
-  ConstString result = parmSubs.Finalize();
-
-  if (Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)) {
-    if (err)
-      LLDB_LOG(log, "Failed to substitute mangling in {0}", mangled);
-    else if (result)
-      LLDB_LOG(log, "Substituted mangling {0} -> {1}", mangled, result);
+    return AbstractManglingParser::parseType();
   }
-
-  return result;
+};
 }
 
 uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
@@ -373,18 +368,18 @@
   // char, 'h'-unsigned char.  If we're looking for symbols with a signed char
   // parameter, try finding matches which have the general case 'c'.
   if (ConstString char_fixup =
-          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "a", "c"))
+          TypeSubstitutor::substitute(mangled_name.GetStringRef(), "a", "c"))
     alternates.insert(char_fixup);
 
   // long long parameter mangling 'x', may actually just be a long 'l' argument
   if (ConstString long_fixup =
-          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "x", "l"))
+          TypeSubstitutor::substitute(mangled_name.GetStringRef(), "x", "l"))
     alternates.insert(long_fixup);
 
   // unsigned long long parameter mangling 'y', may actually just be unsigned
   // long 'm' argument
   if (ConstString ulong_fixup =
-          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "y", "m"))
+          TypeSubstitutor::substitute(mangled_name.GetStringRef(), "y", "m"))
     alternates.insert(ulong_fixup);
 
   return alternates.size() - start_size;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to