Skip to content

[lldb] Add new per-language frame-format variables for formatting function names #131836

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

Closed
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
166 changes: 166 additions & 0 deletions lldb/include/lldb/Core/DemangledNameInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//===-- DemangledNameInfo.h -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_CORE_DEMANGLEDNAMEINFO_H
#define LLDB_CORE_DEMANGLEDNAMEINFO_H

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

#include <cstddef>
#include <utility>

namespace lldb_private {

/// Stores information about where certain portions of a demangled
/// function name begin and end.
struct DemangledNameInfo {
/// A [start, end) pair for the function basename.
/// The basename is the name without scope qualifiers
/// and without template parameters. E.g.,
/// \code{.cpp}
/// void foo::bar<int>::someFunc<float>(int) const &&
/// ^ ^
/// start end
/// \endcode
std::pair<size_t, size_t> BasenameRange;

/// A [start, end) pair for the function scope qualifiers.
/// E.g., for
/// \code{.cpp}
/// void foo::bar<int>::qux<float>(int) const &&
/// ^ ^
/// start end
/// \endcode
std::pair<size_t, size_t> ScopeRange;

/// Indicates the [start, end) of the function argument lits.
/// E.g.,
/// \code{.cpp}
/// int (*getFunc<float>(float, double))(int, int)
/// ^ ^
/// start end
/// \endcode
std::pair<size_t, size_t> ArgumentsRange;

/// Indicates the [start, end) of the function qualifiers
/// (e.g., CV-qualifiers, reference qualifiers, requires clauses).
///
/// E.g.,
/// \code{.cpp}
/// void foo::bar<int>::qux<float>(int) const &&
/// ^ ^
/// start end
/// \endcode
std::pair<size_t, size_t> QualifiersRange;

/// Returns \c true if this object holds a valid basename range.
bool hasBasename() const {
return BasenameRange.second > BasenameRange.first &&
BasenameRange.second > 0;
}

friend bool operator==(const DemangledNameInfo &lhs,
const DemangledNameInfo &rhs) {
return std::tie(lhs.BasenameRange, lhs.ArgumentsRange, lhs.ScopeRange,
lhs.QualifiersRange) ==
std::tie(rhs.BasenameRange, rhs.ArgumentsRange, rhs.ScopeRange,
lhs.QualifiersRange);
}

friend bool operator!=(const DemangledNameInfo &lhs,
const DemangledNameInfo &rhs) {
return !(lhs == rhs);
}
};

/// An OutputBuffer which keeps a record of where certain parts of a
/// demangled name begin/end (e.g., basename, scope, argument list, etc.).
/// The tracking occurs during printing of the Itanium demangle tree.
///
/// Usage:
/// \code{.cpp}
///
/// Node *N = mangling_parser.parseType();
///
/// TrackingOutputBuffer buffer;
/// N->printLeft(OB);
///
/// assert (buffer.NameInfo.hasBasename());
///
/// \endcode
struct TrackingOutputBuffer : public llvm::itanium_demangle::OutputBuffer {
using OutputBuffer::OutputBuffer;

/// Holds information about the demangled name that is
/// being printed into this buffer.
DemangledNameInfo NameInfo;

void printLeft(const llvm::itanium_demangle::Node &N) override;
void printRight(const llvm::itanium_demangle::Node &N) override;

private:
void printLeftImpl(const llvm::itanium_demangle::FunctionType &N);
void printRightImpl(const llvm::itanium_demangle::FunctionType &N);

void printLeftImpl(const llvm::itanium_demangle::FunctionEncoding &N);
void printRightImpl(const llvm::itanium_demangle::FunctionEncoding &N);

void printLeftImpl(const llvm::itanium_demangle::NestedName &N);
void printLeftImpl(const llvm::itanium_demangle::NameWithTemplateArgs &N);

/// Called whenever we start printing a function type in the Itanium
/// mangling scheme. Examples include \ref FunctionEncoding, \ref
/// FunctionType, etc.
///
/// \returns A ScopedOverride which will update the nesting depth of
/// currently printed function types on destruction.
[[nodiscard]] llvm::itanium_demangle::ScopedOverride<unsigned>
enterFunctionTypePrinting();

/// Returns \c true if we're not printing any nested function types,
/// just a \ref FunctionEncoding in the Itanium mangling scheme.
bool isPrintingTopLevelFunctionType() const;

/// If this object \ref shouldTrack, then update the end of
/// the basename range to the current \c OB position.
void updateBasenameEnd();

/// If this object \ref shouldTrack, then update the beginning
/// of the scope range to the current \c OB position.
void updateScopeStart();

/// If this object \ref shouldTrack, then update the end of
/// the scope range to the current \c OB position.
void updateScopeEnd();

/// Returns \c true if the members of this object can be
/// updated. E.g., when we're printing nested template
/// arguments, we don't need to be tracking basename
/// locations.
bool shouldTrack() const;

/// Helpers called to track beginning and end of the function
/// arguments.
void finalizeArgumentEnd();
void finalizeStart();
void finalizeEnd();
void finalizeQualifiersStart();
void finalizeQualifiersEnd();

/// Helper used in the finalize APIs.
bool canFinalize() const;

/// Incremented each time we start printing a function type node
/// in the Itanium mangling scheme (e.g., \ref FunctionEncoding
/// or \ref FunctionType).
unsigned FunctionPrintingDepth = 0;
};
} // namespace lldb_private

#endif // LLDB_CORE_DEMANGLEDNAMEINFO_H
7 changes: 7 additions & 0 deletions lldb/include/lldb/Core/FormatEntity.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ struct Entry {
FunctionNameWithArgs,
FunctionNameNoArgs,
FunctionMangledName,
FunctionScope,
FunctionBasename,
FunctionTemplateArguments,
FunctionFormattedArguments,
FunctionReturnLeft,
FunctionReturnRight,
FunctionQualifiers,
FunctionAddrOffset,
FunctionAddrOffsetConcrete,
FunctionLineOffset,
Expand Down
26 changes: 23 additions & 3 deletions lldb/include/lldb/Core/Mangled.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
#ifndef LLDB_CORE_MANGLED_H
#define LLDB_CORE_MANGLED_H

#include "lldb/Core/DemangledNameInfo.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"
#include "lldb/Utility/ConstString.h"
#include "llvm/ADT/StringRef.h"

#include <cstddef>
Expand Down Expand Up @@ -134,9 +135,15 @@ class Mangled {
/// A const reference to the display demangled name string object.
ConstString GetDisplayDemangledName() const;

void SetDemangledName(ConstString name) { m_demangled = name; }
void SetDemangledName(ConstString name) {
m_demangled = name;
m_demangled_info.reset();
}

void SetMangledName(ConstString name) { m_mangled = name; }
void SetMangledName(ConstString name) {
m_mangled = name;
m_demangled_info.reset();
}

/// Mangled name get accessor.
///
Expand Down Expand Up @@ -277,13 +284,26 @@ class Mangled {
/// table offsets in the cache data.
void Encode(DataEncoder &encoder, ConstStringTable &strtab) const;

/// Retrieve \c DemangledNameInfo of the demangled name held by this object.
const std::optional<DemangledNameInfo> &GetDemangledInfo() const;

private:
/// If \c force is \c false, this function will re-use the previously
/// demangled name (if any). If \c force is \c true (or the mangled name
/// on this object was not previously demangled), demangle and cache the
/// name.
ConstString GetDemangledNameImpl(bool force) const;

/// The mangled version of the name.
ConstString m_mangled;

/// Mutable so we can get it on demand with
/// a const version of this object.
mutable ConstString m_demangled;

/// If available, holds information about where in \c m_demangled certain
/// parts of the name (e.g., basename, arguments, etc.) begin and end.
mutable std::optional<DemangledNameInfo> m_demangled_info = std::nullopt;
};

Stream &operator<<(Stream &s, const Mangled &obj);
Expand Down
14 changes: 12 additions & 2 deletions lldb/include/lldb/Core/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,10 @@ class PluginManager {
GetOperatingSystemCreateCallbackForPluginName(llvm::StringRef name);

// Language
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
LanguageCreateInstance create_callback);
static bool
RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
LanguageCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback = nullptr);

static bool UnregisterPlugin(LanguageCreateInstance create_callback);

Expand Down Expand Up @@ -613,6 +615,14 @@ class PluginManager {
static bool CreateSettingForStructuredDataPlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
llvm::StringRef description, bool is_global_property);

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

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

} // namespace lldb_private
Expand Down
3 changes: 1 addition & 2 deletions lldb/include/lldb/Symbol/SymbolContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,7 @@ class SymbolContext {
/// mangling preference. If this object represents an inlined function,
/// returns the name of the inlined function. Returns nullptr if no function
/// name could be determined.
const char *GetPossiblyInlinedFunctionName(
Mangled::NamePreference mangling_preference) const;
Mangled GetPossiblyInlinedFunctionName() const;

// Member variables
lldb::TargetSP target_sp; ///< The Target for a given query
Expand Down
12 changes: 12 additions & 0 deletions lldb/include/lldb/Target/Language.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <set>
#include <vector>

#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Highlighter.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
Expand Down Expand Up @@ -371,6 +372,13 @@ class Language : public PluginInterface {
FunctionNameRepresentation representation,
Stream &s);

virtual bool HandleFrameFormatVariable(const SymbolContext &sc,
const ExecutionContext *exe_ctx,
FormatEntity::Entry::Type type,
Stream &s) {
return false;
}

virtual ConstString
GetDemangledFunctionNameWithoutArguments(Mangled mangled) const {
if (ConstString demangled = mangled.GetDemangledName())
Expand Down Expand Up @@ -487,6 +495,10 @@ class Language : public PluginInterface {
/// Python uses \b except. Defaults to \b catch.
virtual llvm::StringRef GetCatchKeyword() const { return "catch"; }

virtual const FormatEntity::Entry *GetFunctionNameFormat() const {
return nullptr;
}

protected:
// Classes that inherit from Language can see and modify these

Expand Down
1 change: 1 addition & 0 deletions lldb/source/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_lldb_library(lldbCore NO_PLUGIN_DEPENDENCIES
Debugger.cpp
DebuggerEvents.cpp
Declaration.cpp
DemangledNameInfo.cpp
Disassembler.cpp
DumpDataExtractor.cpp
DumpRegisterValue.cpp
Expand Down
Loading
Loading