Skip to content

[Syntax Highlighting] Add name and parameters syntax highlighting in Swift backtraces #10710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: swift/release/6.2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions lldb/include/lldb/Core/DemangledNameInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLDB_CORE_DEMANGLEDNAMEINFO_H
#define LLDB_CORE_DEMANGLEDNAMEINFO_H

#include "swift/Demangling/Demangle.h"
#include "llvm/Demangle/ItaniumDemangle.h"
#include "llvm/Demangle/Utility.h"

Expand Down Expand Up @@ -39,7 +40,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)
Expand All @@ -59,10 +60,24 @@ 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 &&
BasenameRange.second > 0;
return BasenameRange.second > BasenameRange.first;
}

/// Returns \c true if this object holds a valid arguments range.
bool hasArguments() const {
return ArgumentsRange.second > ArgumentsRange.first;
}
};

Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/Core/FormatEntity.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct Entry {
FunctionNameWithArgs,
FunctionNameNoArgs,
FunctionMangledName,
FunctionPrefix,
FunctionScope,
FunctionBasename,
FunctionTemplateArguments,
Expand Down
69 changes: 69 additions & 0 deletions lldb/include/lldb/Core/Mangled.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,75 @@ class Mangled {

Stream &operator<<(Stream &s, const Mangled &obj);

using namespace swift::Demangle;
class TrackingNodePrinter : public NodePrinter {
public:
TrackingNodePrinter(DemangleOptions options) : NodePrinter(options) {}

DemangledNameInfo takeInfo() { return std::move(info); }

private:
DemangledNameInfo info;
std::optional<unsigned> parametersDepth;

void startName() {
if (!info.hasBasename())
info.BasenameRange.first = getStreamLength();
}

void endName() {
if (!info.hasBasename())
info.BasenameRange.second = getStreamLength();
}

void startParameters(unsigned depth) {
if (parametersDepth || !info.hasBasename() || info.hasArguments()) {
return;
}
info.ArgumentsRange.first = getStreamLength();
parametersDepth = depth;
}

void endParameters(unsigned depth) {
if (!parametersDepth || *parametersDepth != depth || info.hasArguments()) {
return;
}
info.ArgumentsRange.second = getStreamLength();
}

bool shouldTrackNameRange(NodePointer Node) const {
switch (Node->getKind()) {
case Node::Kind::Function:
case Node::Kind::Constructor:
case Node::Kind::Allocator:
case Node::Kind::ExplicitClosure:
return true;
default:
return false;
}
}

void printFunctionName(bool hasName, llvm::StringRef &OverwriteName,
llvm::StringRef &ExtraName, bool MultiWordName,
int &ExtraIndex, NodePointer Entity,
unsigned int depth) override {
if (shouldTrackNameRange(Entity))
startName();
NodePrinter::printFunctionName(hasName, OverwriteName, ExtraName,
MultiWordName, ExtraIndex, Entity, depth);
if (shouldTrackNameRange(Entity))
endName();
}

void printFunctionParameters(NodePointer LabelList, NodePointer ParameterType,
unsigned depth, bool showTypes) override {
startParameters(depth);
NodePrinter::printFunctionParameters(LabelList, ParameterType, depth,
showTypes);
endParameters(depth);
}
};

} // namespace lldb_private

#endif // LLDB_CORE_MANGLED_H
8 changes: 8 additions & 0 deletions lldb/include/lldb/Core/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,14 @@ class PluginManager {
static bool CreateSettingForCPlusPlusLanguagePlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
llvm::StringRef description, bool is_global_property);

static lldb::OptionValuePropertiesSP
GetSettingForSwiftLanguagePlugin(Debugger &debugger,
llvm::StringRef setting_name);

static bool CreateSettingForSwiftLanguagePlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
llvm::StringRef description, bool is_global_property);
};

} // namespace lldb_private
Expand Down
3 changes: 3 additions & 0 deletions lldb/source/Core/FormatEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,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),
Expand Down Expand Up @@ -362,6 +363,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);
Expand Down Expand Up @@ -1812,6 +1814,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:
Expand Down
15 changes: 13 additions & 2 deletions lldb/source/Core/Mangled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,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(demangled_cstr).length();
info = std::move(OB.NameInfo);

assert(demangled_cstr &&
Expand Down Expand Up @@ -351,8 +353,17 @@ ConstString Mangled::GetDemangledNameImpl(bool force, // BEGIN SWIFT
const char *mangled_name = m_mangled.GetCString();
Log *log = GetLog(LLDBLog::Demangle);
LLDB_LOGF(log, "demangle swift: %s", mangled_name);
std::string demangled(SwiftLanguageRuntime::DemangleSymbolAsString(
mangled_name, SwiftLanguageRuntime::eTypeName, sc));
auto demangled_data = SwiftLanguageRuntime::TrackedDemangleSymbolAsString(
mangled_name, SwiftLanguageRuntime::eSimplified, sc);
std::string demangled = demangled_data.first;
DemangledNameInfo info = demangled_data.second;
info.PrefixRange.second =
std::min(info.BasenameRange.first, info.ArgumentsRange.first);
info.SuffixRange.first =
std::max(info.BasenameRange.second, info.ArgumentsRange.second);
info.SuffixRange.second = demangled.length();
m_demangled_info.emplace(info);

// Don't cache the demangled name the function isn't available yet.
if (!sc || !sc->function) {
LLDB_LOGF(log, "demangle swift: %s -> \"%s\" (not cached)", mangled_name,
Expand Down
15 changes: 15 additions & 0 deletions lldb/source/Core/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,7 @@ static constexpr llvm::StringLiteral kJITLoaderPluginName("jit-loader");
static constexpr llvm::StringLiteral
kStructuredDataPluginName("structured-data");
static constexpr llvm::StringLiteral kCPlusPlusLanguagePlugin("cplusplus");
static constexpr llvm::StringLiteral kSwiftLanguagePlugin("swift");

lldb::OptionValuePropertiesSP
PluginManager::GetSettingForDynamicLoaderPlugin(Debugger &debugger,
Expand Down Expand Up @@ -1937,3 +1938,17 @@ bool PluginManager::CreateSettingForCPlusPlusLanguagePlugin(
"Settings for CPlusPlus language plug-ins",
properties_sp, description, is_global_property);
}

lldb::OptionValuePropertiesSP
PluginManager::GetSettingForSwiftLanguagePlugin(
Debugger &debugger, llvm::StringRef setting_name) {
return GetSettingForPlugin(debugger, setting_name, kSwiftLanguagePlugin);
}

bool PluginManager::CreateSettingForSwiftLanguagePlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
llvm::StringRef description, bool is_global_property) {
return CreateSettingForPlugin(debugger, kSwiftLanguagePlugin,
"Settings for Swift language plug-ins",
properties_sp, description, is_global_property);
}
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,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) {
Expand Down
12 changes: 12 additions & 0 deletions lldb/source/Plugins/Language/Swift/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
lldb_tablegen(LanguageSwiftProperties.inc -gen-lldb-property-defs
SOURCE LanguageSwiftProperties.td
TARGET LLDBPluginLanguageSwiftPropertiesGen)

lldb_tablegen(LanguageSwiftPropertiesEnum.inc -gen-lldb-property-enum-defs
SOURCE LanguageSwiftProperties.td
TARGET LLDBPluginLanguageSwiftPropertiesEnumGen)

set(LLVM_NO_RTTI 1)

add_lldb_library(lldbPluginSwiftLanguage PLUGIN
Expand Down Expand Up @@ -36,3 +44,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT SWIFT_COMPILER_MSVC_LIKE)
target_compile_options(lldbPluginSwiftLanguage PRIVATE
-Wno-dollar-in-identifier-extension)
endif()

add_dependencies(lldbPluginSwiftLanguage
LLDBPluginLanguageSwiftPropertiesGen
LLDBPluginLanguageSwiftPropertiesEnumGen)
12 changes: 12 additions & 0 deletions lldb/source/Plugins/Language/Swift/LanguageSwiftProperties.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
include "../../../../include/lldb/Core/PropertiesBase.td"

let Definition = "language_swift" in {
def FunctionNameFormat
: Property<"function-name-format", "FormatEntity">,
Global,
DefaultStringValue<
"${function.prefix}${ansi.fg.yellow}${function.basename}${ansi."
"normal}${function.formatted-arguments}${function.suffix}">,
Desc<"Swift specific frame format string to use when displaying stack "
"frame information for threads.">;
}
Loading