[LLDB] Set and verify paths of properties from tablegen (#179524)

In #168245, I attempted to dump the available settings to Markdown. That
required a full build of LLDB. However, to build the docs, only the swig
wrappers should need to be compiled. The comment was that we should be
able to use the definitions from the TableGen files.

Currently, the property definitions in don't have information about the
path where they will be available. They only contain a `Definition`
which groups properties, so they can be added to
`OptionValueProperties`.

With this PR, I'm adding the path for each property definition. For
example, `symbols.enable-external-lookup` would have `Name =
enable-external-lookup, Path = symbols`. In LLDB itself, we don't need
this path, we only need it for the documentation. To avoid mismatches
between the actual path and the declared one, I added a debug-only check
when a property group is added to a parent
(`OptionValueProperties::AppendProperty`).

The TableGen emitter for the properties now additionally emits
`g_{definition}_properties_def`, which includes both the array of
properties and the expected path. This constant has to be used to
initialize a `OptionValueProperties`.

I couldn't test this for everything (e.g. IntelPT or ProcessKDP), but
the necessary changes are simple: (1) set the `Path` in the TableGen
file, (2) update `initialize` to use `_def`.
This commit is contained in:
Nerixyz 2026-02-10 19:43:29 +01:00 committed by GitHub
parent d3a70f3b2c
commit cdbe28887b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 134 additions and 58 deletions

View File

@ -3,6 +3,7 @@ class Property<string name, string type> {
string Name = name;
string Type = type;
string Definition;
string Path;
}
// Sets the description for the property that should be displayed to the user.

View File

@ -60,7 +60,9 @@ public:
void Apropos(llvm::StringRef keyword,
std::vector<const Property *> &matching_properties) const;
void Initialize(const PropertyDefinitions &setting_definitions);
void Initialize(const PropertyCollectionDefinition &setting_definitions);
void SetExpectedPath(std::string path);
// Subclass specific functions
@ -174,9 +176,12 @@ protected:
return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr);
}
bool VerifyPath();
std::string m_name;
std::vector<Property> m_properties;
llvm::StringMap<size_t> m_name_to_index;
std::string m_expected_path;
};
} // namespace lldb_private

View File

@ -30,7 +30,10 @@ struct PropertyDefinition {
const char *description;
};
using PropertyDefinitions = llvm::ArrayRef<PropertyDefinition>;
struct PropertyCollectionDefinition {
llvm::ArrayRef<PropertyDefinition> definitions;
llvm::StringRef expected_path;
};
class Property {
public:

View File

@ -1,6 +1,6 @@
include "../../include/lldb/Core/PropertiesBase.td"
let Definition = "modulelist" in {
let Definition = "modulelist", Path = "symbols" in {
def EnableExternalLookup: Property<"enable-external-lookup", "Boolean">,
Global,
DefaultTrue,
@ -53,7 +53,7 @@ let Definition = "modulelist" in {
}
#ifndef NDEBUG
let Definition = "testing" in {
let Definition = "testing", Path = "testing" in {
def InjectVarLocListError
: Property<"inject-variable-location-error", "Boolean">,
Global,
@ -62,7 +62,7 @@ let Definition = "testing" in {
}
#endif
let Definition = "debugger" in {
let Definition = "debugger", Path = "" in {
def AutoConfirm: Property<"auto-confirm", "Boolean">,
Global,
DefaultFalse,

View File

@ -215,7 +215,7 @@ enum {
#ifndef NDEBUG
TestingProperties::TestingProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>("testing");
m_collection_sp->Initialize(g_testing_properties);
m_collection_sp->Initialize(g_testing_properties_def);
}
bool TestingProperties::GetInjectVarLocListError() const {
@ -1016,7 +1016,7 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
m_forward_listener_sp(), m_clear_once() {
// Initialize the debugger properties as early as possible as other parts of
// LLDB will start querying them during construction.
m_collection_sp->Initialize(g_debugger_properties);
m_collection_sp->Initialize(g_debugger_properties_def);
m_collection_sp->AppendProperty(
"target", "Settings specify to debugging targets.", true,
Target::GetGlobalProperties().GetValueProperties());

View File

@ -80,7 +80,7 @@ enum {
ModuleListProperties::ModuleListProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>("symbols");
m_collection_sp->Initialize(g_modulelist_properties);
m_collection_sp->Initialize(g_modulelist_properties_def);
m_collection_sp->SetValueChangedCallback(ePropertySymLinkPaths,
[this] { UpdateSymlinkMappings(); });

View File

@ -2019,6 +2019,7 @@ GetDebuggerPropertyForPlugins(Debugger &debugger, llvm::StringRef plugin_type_na
if (!plugin_properties_sp && can_create) {
plugin_properties_sp =
std::make_shared<OptionValueProperties>(g_property_name);
plugin_properties_sp->SetExpectedPath("plugin");
parent_properties_sp->AppendProperty(g_property_name,
"Settings specify to plugins.", true,
plugin_properties_sp);
@ -2030,6 +2031,8 @@ GetDebuggerPropertyForPlugins(Debugger &debugger, llvm::StringRef plugin_type_na
if (!plugin_type_properties_sp && can_create) {
plugin_type_properties_sp =
std::make_shared<OptionValueProperties>(plugin_type_name);
plugin_type_properties_sp->SetExpectedPath(
("plugin." + plugin_type_name).str());
plugin_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
true, plugin_type_properties_sp);
}
@ -2054,6 +2057,7 @@ static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle(
if (!plugin_properties_sp && can_create) {
plugin_properties_sp =
std::make_shared<OptionValueProperties>(plugin_type_name);
plugin_properties_sp->SetExpectedPath(plugin_type_name.str());
parent_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
true, plugin_properties_sp);
}
@ -2064,6 +2068,8 @@ static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle(
if (!plugin_type_properties_sp && can_create) {
plugin_type_properties_sp =
std::make_shared<OptionValueProperties>(g_property_name);
plugin_type_properties_sp->SetExpectedPath(
(plugin_type_name + ".plugin").str());
plugin_properties_sp->AppendProperty(g_property_name,
"Settings specific to plugins",
true, plugin_type_properties_sp);

View File

@ -148,7 +148,7 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger,
SetEventName(eBroadcastBitQuitCommandReceived, "quit");
SetSynchronous(synchronous_execution);
CheckInWithManager();
m_collection_sp->Initialize(g_interpreter_properties);
m_collection_sp->Initialize(g_interpreter_properties_def);
}
bool CommandInterpreter::GetExpandRegexAliases() const {

View File

@ -1,6 +1,6 @@
include "../../include/lldb/Core/PropertiesBase.td"
let Definition = "interpreter" in {
let Definition = "interpreter", Path = "interpreter" in {
def ExpandRegexAliases: Property<"expand-regex-aliases", "Boolean">,
Global,
DefaultFalse,

View File

@ -23,14 +23,21 @@ using namespace lldb_private;
OptionValueProperties::OptionValueProperties(llvm::StringRef name)
: m_name(name.str()) {}
void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
for (const auto &definition : defs) {
void OptionValueProperties::Initialize(
const PropertyCollectionDefinition &defs) {
for (const auto &definition : defs.definitions) {
Property property(definition);
assert(property.IsValid());
m_name_to_index.insert({property.GetName(), m_properties.size()});
property.GetValue()->SetParent(shared_from_this());
m_properties.push_back(property);
}
SetExpectedPath(defs.expected_path.str());
}
void OptionValueProperties::SetExpectedPath(std::string path) {
assert(m_expected_path.empty() || m_expected_path == path);
m_expected_path = path;
}
void OptionValueProperties::SetValueChangedCallback(
@ -47,6 +54,15 @@ void OptionValueProperties::AppendProperty(llvm::StringRef name,
m_name_to_index.insert({name, m_properties.size()});
m_properties.push_back(property);
value_sp->SetParent(shared_from_this());
#ifndef NDEBUG
OptionValueProperties *properties = value_sp->GetAsProperties();
if (properties) {
assert(value_sp->GetName() == name);
assert(properties->VerifyPath() &&
"Mismatch between parents from TableGen and actual parents");
}
#endif
}
lldb::OptionValueSP
@ -489,3 +505,24 @@ OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
}
return lldb::OptionValuePropertiesSP();
}
bool OptionValueProperties::VerifyPath() {
OptionValueSP parent = GetParent();
if (!parent) {
// Only the top level value should have an empty path.
return m_expected_path.empty();
}
OptionValueProperties *parent_properties = parent->GetAsProperties();
if (!parent_properties)
return false;
auto [prefix, expected_name] = llvm::StringRef(m_expected_path).rsplit('.');
if (expected_name.empty()) {
// There is no dot, so the parent should be the top-level (core properties).
return parent_properties->m_expected_path.empty() && GetName() == prefix;
}
return parent_properties->m_expected_path == prefix &&
GetName() == expected_name;
}

View File

@ -106,7 +106,7 @@ public:
DynamicLoaderDarwinKernelProperties() : Properties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_dynamicloaderdarwinkernel_properties);
m_collection_sp->Initialize(g_dynamicloaderdarwinkernel_properties_def);
}
~DynamicLoaderDarwinKernelProperties() override = default;

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "dynamicloaderdarwinkernel" in {
let Definition = "dynamicloaderdarwinkernel", Path = "plugin.dynamic-loader.darwin-kernel" in {
def LoadKexts: Property<"load-kexts", "Boolean">,
Global,
DefaultTrue,

View File

@ -95,7 +95,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_jitloadergdb_properties);
m_collection_sp->Initialize(g_jitloadergdb_properties_def);
}
EnableJITLoaderGDB GetEnable() const {

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "jitloadergdb" in {
let Definition = "jitloadergdb", Path = "plugin.jit-loader.gdb" in {
def Enable: Property<"enable", "Enum">,
Global,
DefaultEnumValue<"eEnableJITLoaderGDBDefault">,

View File

@ -2612,7 +2612,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_language_cplusplus_properties);
m_collection_sp->Initialize(g_language_cplusplus_properties_def);
}
FormatEntity::Entry GetFunctionNameFormat() const {

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "language_cplusplus" in {
let Definition = "language_cplusplus", Path = "plugin.cplusplus.display" in {
def FunctionNameFormat: Property<"function-name-format", "FormatEntity">,
Global,
DefaultStringValue<"${function.return-left}${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.template-arguments}${function.formatted-arguments}${function.return-right}${function.qualifiers}${function.suffix}">,

View File

@ -86,7 +86,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_objectfilepecoff_properties);
m_collection_sp->Initialize(g_objectfilepecoff_properties_def);
}
llvm::Triple::EnvironmentType ABI() const {

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "objectfilepecoff" in {
let Definition = "objectfilepecoff", Path = "plugin.object-file.pe-coff" in {
def ABI: Property<"abi", "Enum">,
Global,
DefaultEnumValue<"llvm::Triple::UnknownEnvironment">,

View File

@ -45,7 +45,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(
PlatformAndroid::GetPluginNameStatic(false));
m_collection_sp->Initialize(g_android_properties);
m_collection_sp->Initialize(g_android_properties_def);
}
};

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "android" in {
let Definition = "android", Path = "platform.plugin.remote-android" in {
def PlatformPackageName: Property<"package-name", "String">,
Global,
DefaultStringValue<"">,

View File

@ -135,7 +135,7 @@ public:
PlatformDarwinProperties() : Properties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_platformdarwin_properties);
m_collection_sp->Initialize(g_platformdarwin_properties_def);
}
~PlatformDarwinProperties() override = default;

View File

@ -196,7 +196,7 @@ public:
PlatformDarwinKernelProperties() : Properties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_platformdarwinkernel_properties);
m_collection_sp->Initialize(g_platformdarwinkernel_properties_def);
}
~PlatformDarwinKernelProperties() override = default;

View File

@ -1,12 +1,12 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "platformdarwinkernel" in {
let Definition = "platformdarwinkernel", Path = "platform.plugin.darwin-kernel" in {
def KextDirectories: Property<"kext-directories", "FileSpecList">,
DefaultStringValue<"">,
Desc<"Directories/KDKs to search for kexts in when starting a kernel debug session.">;
}
let Definition = "platformdarwin" in {
let Definition = "platformdarwin", Path = "platform.plugin.darwin" in {
def IgnoredExceptions: Property<"ignored-exceptions", "String">,
DefaultStringValue<"">,
Desc<"List the mach exceptions to ignore, separated by '|' "

View File

@ -37,7 +37,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(
PlatformQemuUser::GetPluginNameStatic());
m_collection_sp->Initialize(g_platformqemuuser_properties);
m_collection_sp->Initialize(g_platformqemuuser_properties_def);
}
llvm::StringRef GetArchitecture() {

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "platformqemuuser" in {
let Definition = "platformqemuuser", Path = "platform.plugin.qemu-user" in {
def Architecture: Property<"architecture", "String">,
Global,
DefaultStringValue<"">,

View File

@ -41,7 +41,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(
PlatformWasm::GetPluginNameStatic());
m_collection_sp->Initialize(g_platformwasm_properties);
m_collection_sp->Initialize(g_platformwasm_properties_def);
}
FileSpec GetRuntimePath() const {

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "platformwasm" in {
let Definition = "platformwasm", Path = "platform.plugin.wasm" in {
def RuntimePath : Property<"runtime-path", "FileSpec">,
Global,
DefaultStringValue<"">,

View File

@ -70,7 +70,7 @@ public:
PluginProperties() : Properties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_processkdp_properties);
m_collection_sp->Initialize(g_processkdp_properties_def);
}
~PluginProperties() override = default;

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "processkdp" in {
let Definition = "processkdp", Parent = "plugin.process.kdp" in {
def KDPPacketTimeout: Property<"packet-timeout", "UInt64">,
Global,
DefaultUnsignedValue<5>,

View File

@ -146,7 +146,7 @@ public:
PluginProperties() : Properties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_processgdbremote_properties);
m_collection_sp->Initialize(g_processgdbremote_properties_def);
}
~PluginProperties() override = default;

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "processgdbremote" in {
let Definition = "processgdbremote", Path = "plugin.process.gdb-remote" in {
def PacketTimeout: Property<"packet-timeout", "UInt64">,
Global,
#ifdef LLDB_SANITIZED

View File

@ -126,7 +126,7 @@ public:
StructuredDataDarwinLogProperties() : Properties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_darwinlog_properties);
m_collection_sp->Initialize(g_darwinlog_properties_def);
}
~StructuredDataDarwinLogProperties() override = default;

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "darwinlog" in {
let Definition = "darwinlog", Path = "plugin.structured-data.darwin-log" in {
def EnableOnStartup: Property<"enable-on-startup", "Boolean">,
Global,
DefaultFalse,

View File

@ -132,7 +132,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_symbolfiledwarf_properties);
m_collection_sp->Initialize(g_symbolfiledwarf_properties_def);
}
bool IgnoreFileIndexes() const {

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "symbolfiledwarf" in {
let Definition = "symbolfiledwarf", Path = "plugin.symbol-file.dwarf" in {
def IgnoreIndexes: Property<"ignore-file-indexes", "Boolean">,
Global,
DefaultFalse,

View File

@ -123,7 +123,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_symbolfilepdb_properties);
m_collection_sp->Initialize(g_symbolfilepdb_properties_def);
}
bool UseNativeReader() const {

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "symbolfilepdb" in {
let Definition = "symbolfilepdb", Path = "plugin.symbol-file.pdb" in {
def Reader: Property<"reader", "Enum">,
Global,
DefaultEnumValue<"ePDBReaderDefault">,

View File

@ -40,7 +40,7 @@ public:
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_symbollocatordebuginfod_properties);
m_collection_sp->Initialize(g_symbollocatordebuginfod_properties_def);
// We need to read the default value first to read the environment variable.
llvm::SmallVector<llvm::StringRef> urls = llvm::getDefaultDebuginfodUrls();

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "symbollocatordebuginfod" in {
let Definition = "symbollocatordebuginfod", Path = "plugin.symbol-locator.debuginfod" in {
def ServerURLs : Property<"server-urls", "Array">,
ElementType<"String">,
Desc<"An ordered list of Debuginfod server URLs to query for symbols. This defaults to the contents of the DEBUGINFOD_URLS environment variable.">;

View File

@ -54,7 +54,7 @@ llvm::StringRef TraceIntelPT::PluginProperties::GetSettingName() {
TraceIntelPT::PluginProperties::PluginProperties() : Properties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_traceintelpt_properties);
m_collection_sp->Initialize(g_traceintelpt_properties_def);
}
uint64_t

View File

@ -1,6 +1,6 @@
include "../../../../include/lldb/Core/PropertiesBase.td"
let Definition = "traceintelpt" in {
let Definition = "traceintelpt", Parent = "plugin.trace.intel-pt" in {
def InfiniteDecodingLoopVerificationThreshold:
Property<"infinite-decoding-loop-verification-threshold", "UInt64">,
Global,

View File

@ -49,7 +49,7 @@ llvm::StringRef LanguageProperties::GetSettingName() {
LanguageProperties::LanguageProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_language_properties);
m_collection_sp->Initialize(g_language_properties_def);
}
bool LanguageProperties::GetEnableFilterForLineBreakpoints() const {

View File

@ -79,7 +79,7 @@ llvm::StringRef PlatformProperties::GetSettingName() {
PlatformProperties::PlatformProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
m_collection_sp->Initialize(g_platform_properties);
m_collection_sp->Initialize(g_platform_properties_def);
auto module_cache_dir = GetModuleCacheDirectory();
if (module_cache_dir)

View File

@ -147,7 +147,7 @@ public:
ProcessExperimentalProperties::ProcessExperimentalProperties()
: Properties(OptionValuePropertiesSP(
new ProcessExperimentalOptionValueProperties())) {
m_collection_sp->Initialize(g_process_experimental_properties);
m_collection_sp->Initialize(g_process_experimental_properties_def);
}
ProcessProperties::ProcessProperties(lldb_private::Process *process)
@ -157,7 +157,7 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process)
if (process == nullptr) {
// Global process properties, set them up one time
m_collection_sp = std::make_shared<ProcessOptionValueProperties>("process");
m_collection_sp->Initialize(g_process_properties);
m_collection_sp->Initialize(g_process_properties_def);
m_collection_sp->AppendProperty(
"thread", "Settings specific to threads.", true,
Thread::GetGlobalProperties().GetValueProperties());

View File

@ -4460,7 +4460,7 @@ public:
TargetExperimentalProperties::TargetExperimentalProperties()
: Properties(OptionValuePropertiesSP(
new TargetExperimentalOptionValueProperties())) {
m_collection_sp->Initialize(g_target_experimental_properties);
m_collection_sp->Initialize(g_target_experimental_properties_def);
}
// TargetProperties
@ -4509,7 +4509,7 @@ TargetProperties::TargetProperties(Target *target)
true, m_experimental_properties_up->GetValueProperties());
} else {
m_collection_sp = std::make_shared<TargetOptionValueProperties>("target");
m_collection_sp->Initialize(g_target_properties);
m_collection_sp->Initialize(g_target_properties_def);
m_experimental_properties_up =
std::make_unique<TargetExperimentalProperties>();
m_collection_sp->AppendProperty(

View File

@ -1,6 +1,6 @@
include "../../include/lldb/Core/PropertiesBase.td"
let Definition = "target_experimental" in {
let Definition = "target_experimental", Path = "target.experimental" in {
def InjectLocalVars : Property<"inject-local-vars", "Boolean">,
Global, DefaultTrue,
Desc<"If true, inject local variables explicitly into the expression text. This will fix symbol resolution when there are name collisions between ivars and local variables. But it can make expressions run much more slowly.">;
@ -9,7 +9,7 @@ let Definition = "target_experimental" in {
Desc<"If true, use the DIL implementation for frame variable evaluation.">;
}
let Definition = "target" in {
let Definition = "target", Path = "target" in {
def DefaultArch: Property<"default-arch", "Arch">,
Global,
DefaultStringValue<"">,
@ -222,14 +222,14 @@ let Definition = "target" in {
Desc<"Enable loading of modules in parallel for the dynamic loader.">;
}
let Definition = "process_experimental" in {
let Definition = "process_experimental", Path = "target.process.experimental" in {
def OSPluginReportsAllThreads: Property<"os-plugin-reports-all-threads", "Boolean">,
Global,
DefaultTrue,
Desc<"Set to False if your Python OS Plugin doesn't report all threads on each stop.">;
}
let Definition = "process" in {
let Definition = "process", Path = "target.process" in {
def DisableMemCache: Property<"disable-memory-cache", "Boolean">,
DefaultFalse,
Desc<"Disable reading and caching of memory in fixed-size units.">;
@ -304,7 +304,7 @@ let Definition = "process" in {
Desc<"If true, memory cache modifications (which happen often during expressions evaluation) will bump process state ID (and invalidate all synthetic children). Disabling this option helps to avoid synthetic children reevaluation when pretty printers heavily use expressions. The downside of disabled setting is that convenience variables won't reevaluate synthetic children automatically.">;
}
let Definition = "platform" in {
let Definition = "platform", Path = "platform" in {
def UseModuleCache: Property<"use-module-cache", "Boolean">,
Global,
DefaultTrue,
@ -315,7 +315,7 @@ let Definition = "platform" in {
Desc<"Root directory for cached modules.">;
}
let Definition = "thread" in {
let Definition = "thread", Path = "target.process.thread" in {
def StepInAvoidsNoDebug: Property<"step-in-avoid-nodebug", "Boolean">,
Global,
DefaultTrue,
@ -344,7 +344,7 @@ let Definition = "thread" in {
Desc<"The time in milliseconds to wait for single thread ThreadPlan to move forward before resuming all threads to resolve any potential deadlock. Specify value 0 to disable timeout.">;
}
let Definition = "language" in {
let Definition = "language", Path = "language" in {
def EnableFilterForLineBreakpoints: Property<"enable-filter-for-line-breakpoints", "Boolean">,
DefaultTrue,
Desc<"If true, allow Language plugins to filter locations when setting breakpoints by line number or regex.">;

View File

@ -107,7 +107,7 @@ public:
ThreadProperties::ThreadProperties(bool is_global) : Properties() {
if (is_global) {
m_collection_sp = std::make_shared<ThreadOptionValueProperties>("thread");
m_collection_sp->Initialize(g_thread_properties);
m_collection_sp->Initialize(g_thread_properties_def);
} else
m_collection_sp =
OptionValueProperties::CreateLocalCopy(Thread::GetGlobalProperties());

View File

@ -16,6 +16,7 @@
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <optional>
#include <vector>
using namespace llvm;
@ -124,6 +125,19 @@ static void emitProperty(const Record *Property, raw_ostream &OS) {
OS << "},\n";
}
static std::optional<StringRef>
getPropertyPath(const std::vector<const Record *> &PropertyRecords) {
std::optional<StringRef> Path;
for (const Record *R : PropertyRecords) {
StringRef P = R->getValueAsString("Path");
if (!Path)
Path.emplace(P);
assert(*Path == P &&
"All records with one definition should have the same path");
}
return Path;
}
/// Emits all property initializers to the raw_ostream.
static void emityProperties(std::string PropertyName,
const std::vector<const Record *> &PropertyRecords,
@ -133,6 +147,8 @@ static void emityProperties(std::string PropertyName,
std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
llvm::replace(NeededMacro, ' ', '_');
std::optional<StringRef> Path = getPropertyPath(PropertyRecords);
// All options are in one file, so we need put them behind macros and ask the
// user to define the macro for the options that are needed.
OS << "// Property definitions for " << PropertyName << "\n";
@ -142,6 +158,14 @@ static void emityProperties(std::string PropertyName,
for (const Record *R : PropertyRecords)
emitProperty(R, OS);
OS << "};\n";
OS << "static constexpr PropertyCollectionDefinition g_" << PropertyName
<< "_properties_def = {\n";
OS << "/*properties=*/g_" << PropertyName << "_properties,\n";
if (Path)
OS << "/*expected_path=*/\"" << *Path << "\",\n";
OS << "};\n";
// We undefine the macro for the user like Clang's include files are doing it.
OS << "#undef " << NeededMacro << "\n";
OS << "#endif // " << PropertyName << " Property\n\n";