[llvm-branch-commits] [lldb] [lldb] Refactor RegisterTypeBuilder (PR #213897)
David Spickett via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Aug 6 05:53:59 PDT 2026
https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/213897
>From 9a1514b009db15062c9fe35735557631d74d5219 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Fri, 6 Sep 2024 13:17:43 +0000
Subject: [PATCH] [lldb] Refactor RegisterTypeBuilder
This prepares it for emitting union types. Major changes:
* Entry function is now a dispatcher to builder functions for each type.
* Name mangling is standardised.
* The register name parameter is no longer needed and so was removed.
---
.../include/lldb/Target/RegisterTypeBuilder.h | 5 +-
lldb/include/lldb/Target/Target.h | 5 +-
lldb/source/Core/DumpRegisterValue.cpp | 4 +-
.../RegisterTypeBuilderClang.cpp | 193 ++++++++++--------
.../RegisterTypeBuilderClang.h | 15 +-
lldb/source/Target/Target.cpp | 6 +-
6 files changed, 127 insertions(+), 101 deletions(-)
diff --git a/lldb/include/lldb/Target/RegisterTypeBuilder.h b/lldb/include/lldb/Target/RegisterTypeBuilder.h
index c24d218962e39..5a37109661da0 100644
--- a/lldb/include/lldb/Target/RegisterTypeBuilder.h
+++ b/lldb/include/lldb/Target/RegisterTypeBuilder.h
@@ -19,9 +19,8 @@ class RegisterTypeBuilder : public PluginInterface {
~RegisterTypeBuilder() override = default;
virtual CompilerType
- GetRegisterType(const std::string &name,
- const lldb_private::RegisterType &type_info,
- uint32_t byte_size) = 0;
+ GetRegisterType(const lldb_private::RegisterType &type_info,
+ uint32_t register_byte_size) = 0;
protected:
RegisterTypeBuilder() = default;
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 39602421cfd96..3e1914513bad4 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1564,9 +1564,8 @@ class Target : public std::enable_shared_from_this<Target>,
/// if none can be found.
llvm::Expected<lldb_private::Address> GetEntryPointAddress();
- CompilerType GetRegisterType(const std::string &name,
- const lldb_private::RegisterType &type_info,
- uint32_t byte_size);
+ CompilerType GetRegisterType(const lldb_private::RegisterType &type_info,
+ uint32_t register_byte_size);
/// Sends a breakpoint notification event.
void NotifyBreakpointChanged(Breakpoint &bp,
diff --git a/lldb/source/Core/DumpRegisterValue.cpp b/lldb/source/Core/DumpRegisterValue.cpp
index 7096cfec5e11c..4ecaf0f08a693 100644
--- a/lldb/source/Core/DumpRegisterValue.cpp
+++ b/lldb/source/Core/DumpRegisterValue.cpp
@@ -129,8 +129,8 @@ void lldb_private::DumpRegisterValue(const RegisterValue ®_val, Stream &s,
(reg_info.byte_size != 4 && reg_info.byte_size != 8))
return;
- CompilerType register_compiler_type = target_sp->GetRegisterType(
- reg_info.name, *reg_info.register_type, reg_info.byte_size);
+ CompilerType register_compiler_type =
+ target_sp->GetRegisterType(*reg_info.register_type, reg_info.byte_size);
if (!register_compiler_type.IsValid())
return;
diff --git a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp
index d63c7e2e71bc1..9577a21077805 100644
--- a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp
+++ b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp
@@ -8,10 +8,8 @@
#include "clang/AST/DeclCXX.h"
-#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "RegisterTypeBuilderClang.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Utility/RegisterTypeFlags.h"
#include "lldb/lldb-enumerations.h"
using namespace lldb_private;
@@ -35,94 +33,117 @@ RegisterTypeBuilderClang::CreateInstance(Target &target) {
RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target &target)
: m_target(target) {}
+static std::string MakeTypeName(const RegisterType &type_info,
+ uint32_t register_byte_size) {
+ std::string type_name = "__lldb_register_fields_";
+ switch (type_info.getKind()) {
+ case RegisterType::eRegisterTypeKindFlags:
+ type_name += "flags_";
+ break;
+ case RegisterType::eRegisterTypeKindEnum:
+ // Enums can be used by many registers and the size of each register
+ // may be different. The register size is used as the underlying size
+ // of the enumerators, so we must make one enum type per register size
+ // it is used with.
+ type_name += "enum_" + std::to_string(register_byte_size) + "_";
+ break;
+ }
+
+ return type_name + type_info.GetID();
+}
+
+CompilerType
+RegisterTypeBuilderClang::BuildEnumType(const RegisterTypeEnum &enum_type_info,
+ uint32_t register_byte_size,
+ lldb::TypeSystemClangSP type_system) {
+ std::string enum_type_name = MakeTypeName(enum_type_info, register_byte_size);
+
+ // Reuse existing type if we can.
+ if (CompilerType enum_type =
+ type_system->GetTypeForIdentifier<clang::EnumDecl>(
+ type_system->getASTContext(), enum_type_name))
+ return enum_type;
+
+ CompilerType register_uint_type =
+ type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
+ register_byte_size * 8);
+ CompilerType enum_type = type_system->CreateEnumerationType(
+ enum_type_name, type_system->GetTranslationUnitDecl(),
+ OptionalClangModuleID(), Declaration(), register_uint_type, false);
+
+ type_system->StartTagDeclarationDefinition(enum_type);
+
+ Declaration decl;
+ for (const auto &enumerator : enum_type_info.GetEnumerators()) {
+ type_system->AddEnumerationValueToEnumerationType(
+ enum_type, decl, enumerator.m_name.c_str(), enumerator.m_value,
+ register_byte_size * 8);
+ }
+
+ type_system->CompleteTagDeclarationDefinition(enum_type);
+
+ return enum_type;
+}
+
+CompilerType RegisterTypeBuilderClang::BuildFlagsType(
+ const lldb_private::RegisterTypeFlags &flags_info,
+ uint32_t register_byte_size, lldb::TypeSystemClangSP type_system) {
+ std::string register_type_name = MakeTypeName(flags_info, register_byte_size);
+
+ // Reuse existing type if we can.
+ if (CompilerType flags_type =
+ type_system->GetTypeForIdentifier<clang::CXXRecordDecl>(
+ type_system->getASTContext(), register_type_name))
+ return flags_type;
+
+ // In most ABI, a change of field type means a change in storage unit.
+ // We want it all in one unit, so we use a field type the same as the
+ // register's size.
+ CompilerType field_uint_type =
+ type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
+ register_byte_size * 8);
+
+ CompilerType flags_type = type_system->CreateRecordType(
+ nullptr, OptionalClangModuleID(), register_type_name,
+ llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC);
+ type_system->StartTagDeclarationDefinition(flags_type);
+
+ for (auto field : flags_info.GetFields()) {
+ CompilerType field_type = field_uint_type;
+
+ if (const RegisterTypeEnum *enum_type_info = field.GetEnum())
+ if (!enum_type_info->GetEnumerators().empty())
+ field_type =
+ BuildEnumType(*enum_type_info, register_byte_size, type_system);
+
+ type_system->AddFieldToRecordType(flags_type, field.GetName(), field_type,
+ field.GetSizeInBits());
+ }
+
+ type_system->CompleteTagDeclarationDefinition(flags_type);
+ // So that the size of the type matches the size of the register.
+ type_system->SetIsPacked(flags_type);
+
+ // This should be true if RegisterTypeFlags padded correctly.
+ assert(
+ llvm::expectedToOptional(flags_type.GetByteSize(nullptr)).value_or(0) ==
+ flags_info.GetSize());
+
+ return flags_type;
+}
+
CompilerType RegisterTypeBuilderClang::GetRegisterType(
- const std::string &name, const lldb_private::RegisterType &type_info,
- uint32_t byte_size) {
+ const lldb_private::RegisterType &type_info, uint32_t register_byte_size) {
lldb::TypeSystemClangSP type_system =
ScratchTypeSystemClang::GetForTarget(m_target);
assert(type_system);
- std::string register_type_name = "__lldb_register_fields_" + name;
- // For now we can only build sets of flags.
- const RegisterTypeFlags *flags =
- llvm::dyn_cast<RegisterTypeFlags>(&type_info);
- if (!flags)
- return {};
-
- // See if we have made this type before and can reuse it.
- CompilerType fields_type =
- type_system->GetTypeForIdentifier<clang::CXXRecordDecl>(
- type_system->getASTContext(), register_type_name);
-
- if (!fields_type) {
- // In most ABI, a change of field type means a change in storage unit.
- // We want it all in one unit, so we use a field type the same as the
- // register's size.
- CompilerType field_uint_type =
- type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
- byte_size * 8);
-
- fields_type = type_system->CreateRecordType(
- nullptr, OptionalClangModuleID(), register_type_name,
- llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC);
- type_system->StartTagDeclarationDefinition(fields_type);
-
- // We assume that RegisterTypeFlags has padded and sorted the fields
- // already.
- for (const RegisterTypeFlags::Field &field : flags->GetFields()) {
- CompilerType field_type = field_uint_type;
-
- if (const RegisterTypeEnum *enum_type = field.GetEnum()) {
- const RegisterTypeEnum::Enumerators &enumerators =
- enum_type->GetEnumerators();
- if (!enumerators.empty()) {
- // Enums can be used by many registers and the size of each register
- // may be different. The register size is used as the underlying size
- // of the enumerators, so we must make one enum type per register size
- // it is used with.
- std::string enum_type_name = "__lldb_register_fields_enum_" +
- enum_type->GetID() + "_" +
- std::to_string(byte_size);
-
- // Enums can be used by mutiple fields and multiple registers, so we
- // may have built this one already.
- CompilerType field_enum_type =
- type_system->GetTypeForIdentifier<clang::EnumDecl>(
- type_system->getASTContext(), enum_type_name);
-
- if (field_enum_type)
- field_type = field_enum_type;
- else {
- field_type = type_system->CreateEnumerationType(
- enum_type_name, type_system->GetTranslationUnitDecl(),
- OptionalClangModuleID(), Declaration(), field_uint_type, false);
-
- type_system->StartTagDeclarationDefinition(field_type);
-
- Declaration decl;
- for (auto enumerator : enumerators) {
- type_system->AddEnumerationValueToEnumerationType(
- field_type, decl, enumerator.m_name.c_str(),
- enumerator.m_value, byte_size * 8);
- }
-
- type_system->CompleteTagDeclarationDefinition(field_type);
- }
- }
- }
-
- type_system->AddFieldToRecordType(fields_type, field.GetName(),
- field_type, field.GetSizeInBits());
- }
-
- type_system->CompleteTagDeclarationDefinition(fields_type);
- // So that the size of the type matches the size of the register.
- type_system->SetIsPacked(fields_type);
-
- // This should be true if RegisterTypeFlags padded correctly.
- assert(llvm::expectedToOptional(fields_type.GetByteSize(nullptr))
- .value_or(0) == flags->GetSize());
+ switch (type_info.getKind()) {
+ case RegisterType::eRegisterTypeKindFlags:
+ return BuildFlagsType(*llvm::dyn_cast<RegisterTypeFlags>(&type_info),
+ register_byte_size, type_system);
+ case RegisterType::eRegisterTypeKindEnum:
+ return BuildEnumType(*llvm::dyn_cast<RegisterTypeEnum>(&type_info),
+ register_byte_size, type_system);
}
-
- return fields_type;
}
diff --git a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h
index f00fdc1a5587d..47fff0699b03c 100644
--- a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h
+++ b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h
@@ -9,8 +9,10 @@
#ifndef LLDB_SOURCE_PLUGINS_REGISTERTYPEBUILDER_REGISTERTYPEBUILDERCLANG_H
#define LLDB_SOURCE_PLUGINS_REGISTERTYPEBUILDER_REGISTERTYPEBUILDERCLANG_H
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Target/RegisterTypeBuilder.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/RegisterTypeFlags.h"
namespace lldb_private {
class RegisterTypeBuilderClang : public RegisterTypeBuilder {
@@ -28,11 +30,18 @@ class RegisterTypeBuilderClang : public RegisterTypeBuilder {
}
static lldb::RegisterTypeBuilderSP CreateInstance(Target &target);
- CompilerType GetRegisterType(const std::string &name,
- const lldb_private::RegisterType &type_info,
- uint32_t byte_size) override;
+ CompilerType GetRegisterType(const lldb_private::RegisterType &type_info,
+ uint32_t register_byte_size) override;
private:
+ CompilerType BuildEnumType(const RegisterTypeEnum &enum_type_info,
+ uint32_t register_byte_size,
+ lldb::TypeSystemClangSP type_system);
+
+ CompilerType BuildFlagsType(const RegisterTypeFlags &flags_info,
+ uint32_t register_byte_size,
+ lldb::TypeSystemClangSP type_system);
+
Target &m_target;
};
} // namespace lldb_private
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index b83d67bbf045e..f55ca3908ea34 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2740,14 +2740,12 @@ Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language,
}
CompilerType
-Target::GetRegisterType(const std::string &name,
- const lldb_private::RegisterType &type_info,
+Target::GetRegisterType(const lldb_private::RegisterType &type_info,
uint32_t byte_size) {
if (!m_register_type_builder_sp)
m_register_type_builder_sp = PluginManager::GetRegisterTypeBuilder(*this);
assert(m_register_type_builder_sp);
- return m_register_type_builder_sp->GetRegisterType(name, type_info,
- byte_size);
+ return m_register_type_builder_sp->GetRegisterType(type_info, byte_size);
}
std::vector<lldb::TypeSystemSP>
More information about the llvm-branch-commits
mailing list