[Demangling] Refactor Demangler range tracking (#140762)

This PR is a subset of the commits made in
https://github.com/swiftlang/llvm-project/pull/10710.

The most notable change is the addition of `PrefixRange` and
`SuffixRange` which are a catch-all to track anything after or before a
function's demangled name. In the case of Swift, this allows to add
support for name highlighting without having to track the range of the
scope and specifiers of a function (this will come in another PR).
This commit is contained in:
Charles Zablit
2025-05-28 13:53:02 +01:00
committed by GitHub
parent 9aebf4c399
commit b8997c07d9
7 changed files with 47 additions and 4 deletions

View File

@@ -91,7 +91,9 @@ A complete list of currently supported format string variables is listed below:
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.basename`` | The basename of the current function depending on the frame's language. E.g., for C++ the basename for ``void ns::foo<float>::bar<int>(int) const`` is ``bar``. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.scope`` | The scope qualifiers of the current function depending on the frame's language. E.g., for C++ the scope for ``void ns::foo<float>::bar<int>(int) const`` is ``ns::foo<float>``. |
| ``function.prefix`` | Any prefix added to the demangled function name of the current function. This depends on the frame's language. E.g., for C++ the prefix will always be empty. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.scope`` | The scope qualifiers of the current function depending on the frame's language. E.g., for C++ the scope for ``void ns::foo<float>::bar<int>(int) const`` is ``ns::foo<float>``. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.template-arguments`` | The template arguments of the current function depending on the frame's language. E.g., for C++ the template arguments for ``void ns::foo<float>::bar<int>(int) const`` are ``<float>``. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -325,6 +327,7 @@ _____________________
The function names displayed in backtraces/``frame info``/``thread info`` are the demangled names of functions. On some platforms (like ones using Itanium the mangling scheme), LLDB supports decomposing these names into fine-grained components. These are currently:
- ``${function.return-left}``
- ``${function.prefix}``
- ``${function.scope}``
- ``${function.basename}``
- ``${function.template-arguments}``

View File

@@ -39,7 +39,7 @@ struct DemangledNameInfo {
/// \endcode
std::pair<size_t, size_t> ScopeRange;
/// Indicates the [start, end) of the function argument lits.
/// Indicates the [start, end) of the function argument list.
/// E.g.,
/// \code{.cpp}
/// int (*getFunc<float>(float, double))(int, int)
@@ -59,6 +59,16 @@ struct DemangledNameInfo {
/// \endcode
std::pair<size_t, size_t> QualifiersRange;
/// Indicates the [start, end) of the function's prefix. This is a
/// catch-all range for anything that is not tracked by the rest of
/// the pairs.
std::pair<size_t, size_t> PrefixRange;
/// Indicates the [start, end) of the function's suffix. This is a
/// catch-all range for anything that is not tracked by the rest of
/// the pairs.
std::pair<size_t, size_t> SuffixRange;
/// Returns \c true if this object holds a valid basename range.
bool hasBasename() const {
return BasenameRange.second > BasenameRange.first &&

View File

@@ -88,6 +88,7 @@ struct Entry {
FunctionNameWithArgs,
FunctionNameNoArgs,
FunctionMangledName,
FunctionPrefix,
FunctionScope,
FunctionBasename,
FunctionTemplateArguments,

View File

@@ -124,6 +124,7 @@ constexpr Definition g_function_child_entries[] = {
Definition("initial-function", EntryType::FunctionInitial),
Definition("changed", EntryType::FunctionChanged),
Definition("is-optimized", EntryType::FunctionIsOptimized),
Definition("prefix", EntryType::FunctionPrefix),
Definition("scope", EntryType::FunctionScope),
Definition("basename", EntryType::FunctionBasename),
Definition("template-arguments", EntryType::FunctionTemplateArguments),
@@ -385,6 +386,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
ENUM_TO_CSTR(FunctionNameWithArgs);
ENUM_TO_CSTR(FunctionNameNoArgs);
ENUM_TO_CSTR(FunctionMangledName);
ENUM_TO_CSTR(FunctionPrefix);
ENUM_TO_CSTR(FunctionScope);
ENUM_TO_CSTR(FunctionBasename);
ENUM_TO_CSTR(FunctionTemplateArguments);
@@ -1835,6 +1837,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return true;
}
case Entry::Type::FunctionPrefix:
case Entry::Type::FunctionScope:
case Entry::Type::FunctionBasename:
case Entry::Type::FunctionTemplateArguments:

View File

@@ -172,6 +172,8 @@ GetItaniumDemangledStr(const char *M) {
TrackingOutputBuffer OB(demangled_cstr, demangled_size);
demangled_cstr = ipd.finishDemangle(&OB);
OB.NameInfo.SuffixRange.first = OB.NameInfo.QualifiersRange.second;
OB.NameInfo.SuffixRange.second = std::string_view(OB).size();
info = std::move(OB.NameInfo);
assert(demangled_cstr &&

View File

@@ -401,8 +401,8 @@ GetDemangledFunctionSuffix(const SymbolContext &sc) {
if (!info->hasBasename())
return std::nullopt;
return demangled_name.slice(info->QualifiersRange.second,
llvm::StringRef::npos);
return demangled_name.slice(info->SuffixRange.first,
info->SuffixRange.second);
}
static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {

View File

@@ -0,0 +1,24 @@
# Check that we have an appropriate fallback for ${function.prefix} in languages that
# don't implement this frame format variable (in this case Objective-C).
#
# RUN: split-file %s %t
# RUN: %clang_host -g -gdwarf %t/main.m -o %t.objc.out
# RUN: %lldb -x -b -s %t/commands.input %t.objc.out -o exit 2>&1 \
# RUN: | FileCheck %s
#--- main.m
int func() {}
int bar() { func(); }
int main() { return bar(); }
#--- commands.input
settings set -f frame-format "custom-frame '${function.prefix}'\n"
break set -n bar
run
bt
# CHECK: bt
# CHECK-NOT: custom-frame