summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Language/CPlusPlus
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2018-11-06 15:41:37 +0000
committerPavel Labath <pavel@labath.sk>2018-11-06 15:41:37 +0000
commite0d2733bf63f08989947f2a6a227d7301c6b11a3 (patch)
tree1bf2dac097e3f9d38a92b8275f80348c2dbb203a /lldb/source/Plugins/Language/CPlusPlus
parentbe985e33f0c5ddc39ab5a898a716ed038c2e06bb (diff)
downloadbcm5719-llvm-e0d2733bf63f08989947f2a6a227d7301c6b11a3.tar.gz
bcm5719-llvm-e0d2733bf63f08989947f2a6a227d7301c6b11a3.zip
CPlusPlusLanguage: Use new demangler API to implement type substitution
Summary: 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. Reviewers: sgraenitz, erik.pilkington, JDevlieghere Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D54074 llvm-svn: 346233
Diffstat (limited to 'lldb/source/Plugins/Language/CPlusPlus')
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp142
1 files changed, 80 insertions, 62 deletions
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index badfb948ed9..e0fd384519c 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/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"
@@ -279,72 +279,89 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier(
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> {
+ /// Input character until which we have constructed the respective output
+ /// already
+ const char *Written;
+
+ llvm::StringRef Search;
+ llvm::StringRef Replace;
+ llvm::SmallString<128> Result;
+
+ /// Whether we have performed any substitutions.
+ bool Substituted;
+
+ void reset(llvm::StringRef Mangled, llvm::StringRef Search,
+ llvm::StringRef Replace) {
+ AbstractManglingParser::reset(Mangled.begin(), Mangled.end());
+ Written = Mangled.begin();
+ this->Search = Search;
+ this->Replace = Replace;
+ Result.clear();
+ Substituted = false;
+ }
- static void Callback(void *context, const char *match) {
- ((PrimitiveParmSubs *)context)->Substitute(llvm::StringRef(match));
+ void appendUnchangedInput() {
+ Result += llvm::StringRef(Written, First - Written);
+ Written = First;
+ }
+
+public:
+ TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {}
+
+ ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
+ llvm::StringRef To) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+
+ reset(Mangled, From, To);
+ if (parse() == nullptr) {
+ LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
+ return ConstString();
}
- };
+ if (!Substituted)
+ return ConstString();
- // 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);
+ // Append any trailing unmodified input.
+ appendUnchangedInput();
+ LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
+ return ConstString(Result);
}
- return result;
+ llvm::itanium_demangle::Node *parseType() {
+ if (llvm::StringRef(First, numLeft()).startswith(Search)) {
+ // We found a match. Append unmodified input up to this point.
+ appendUnchangedInput();
+
+ // And then perform the replacement.
+ Result += Replace;
+ Written += Search.size();
+ Substituted = true;
+ }
+ return AbstractManglingParser::parseType();
+ }
+};
}
uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
@@ -373,23 +390,24 @@ uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
alternates.insert(ConstString(fixed_scratch));
}
+ TypeSubstitutor TS;
// `char` is implementation defined as either `signed` or `unsigned`. As a
// result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
// 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"))
+ TS.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"))
+ TS.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"))
+ TS.substitute(mangled_name.GetStringRef(), "y", "m"))
alternates.insert(ulong_fixup);
return alternates.size() - start_size;
OpenPOWER on IntegriCloud