Skip to content

Commit 983233f

Browse files
David SpickettDavidSpickett
authored andcommitted
[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.
1 parent 231fd4c commit 983233f

6 files changed

Lines changed: 127 additions & 101 deletions

File tree

lldb/include/lldb/Target/RegisterTypeBuilder.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ class RegisterTypeBuilder : public PluginInterface {
1919
~RegisterTypeBuilder() override = default;
2020

2121
virtual CompilerType
22-
GetRegisterType(const std::string &name,
23-
const lldb_private::RegisterType &type_info,
24-
uint32_t byte_size) = 0;
22+
GetRegisterType(const lldb_private::RegisterType &type_info,
23+
uint32_t register_byte_size) = 0;
2524

2625
protected:
2726
RegisterTypeBuilder() = default;

lldb/include/lldb/Target/Target.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,9 +1564,8 @@ class Target : public std::enable_shared_from_this<Target>,
15641564
/// if none can be found.
15651565
llvm::Expected<lldb_private::Address> GetEntryPointAddress();
15661566

1567-
CompilerType GetRegisterType(const std::string &name,
1568-
const lldb_private::RegisterType &type_info,
1569-
uint32_t byte_size);
1567+
CompilerType GetRegisterType(const lldb_private::RegisterType &type_info,
1568+
uint32_t register_byte_size);
15701569

15711570
/// Sends a breakpoint notification event.
15721571
void NotifyBreakpointChanged(Breakpoint &bp,

lldb/source/Core/DumpRegisterValue.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ void lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream &s,
129129
(reg_info.byte_size != 4 && reg_info.byte_size != 8))
130130
return;
131131

132-
CompilerType register_compiler_type = target_sp->GetRegisterType(
133-
reg_info.name, *reg_info.register_type, reg_info.byte_size);
132+
CompilerType register_compiler_type =
133+
target_sp->GetRegisterType(*reg_info.register_type, reg_info.byte_size);
134134
if (!register_compiler_type.IsValid())
135135
return;
136136

lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp

Lines changed: 107 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
#include "clang/AST/DeclCXX.h"
1010

11-
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
1211
#include "RegisterTypeBuilderClang.h"
1312
#include "lldb/Core/PluginManager.h"
14-
#include "lldb/Utility/RegisterTypeFlags.h"
1513
#include "lldb/lldb-enumerations.h"
1614

1715
using namespace lldb_private;
@@ -35,94 +33,117 @@ RegisterTypeBuilderClang::CreateInstance(Target &target) {
3533
RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target &target)
3634
: m_target(target) {}
3735

36+
static std::string MakeTypeName(const RegisterType &type_info,
37+
uint32_t register_byte_size) {
38+
std::string type_name = "__lldb_register_fields_";
39+
switch (type_info.getKind()) {
40+
case RegisterType::eRegisterTypeKindFlags:
41+
type_name += "flags_";
42+
break;
43+
case RegisterType::eRegisterTypeKindEnum:
44+
// Enums can be used by many registers and the size of each register
45+
// may be different. The register size is used as the underlying size
46+
// of the enumerators, so we must make one enum type per register size
47+
// it is used with.
48+
type_name += "enum_" + std::to_string(register_byte_size) + "_";
49+
break;
50+
}
51+
52+
return type_name + type_info.GetID();
53+
}
54+
55+
CompilerType
56+
RegisterTypeBuilderClang::BuildEnumType(const RegisterTypeEnum &enum_type_info,
57+
uint32_t register_byte_size,
58+
lldb::TypeSystemClangSP type_system) {
59+
std::string enum_type_name = MakeTypeName(enum_type_info, register_byte_size);
60+
61+
// Reuse existing type if we can.
62+
if (CompilerType enum_type =
63+
type_system->GetTypeForIdentifier<clang::EnumDecl>(
64+
type_system->getASTContext(), enum_type_name))
65+
return enum_type;
66+
67+
CompilerType register_uint_type =
68+
type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
69+
register_byte_size * 8);
70+
CompilerType enum_type = type_system->CreateEnumerationType(
71+
enum_type_name, type_system->GetTranslationUnitDecl(),
72+
OptionalClangModuleID(), Declaration(), register_uint_type, false);
73+
74+
type_system->StartTagDeclarationDefinition(enum_type);
75+
76+
Declaration decl;
77+
for (const auto &enumerator : enum_type_info.GetEnumerators()) {
78+
type_system->AddEnumerationValueToEnumerationType(
79+
enum_type, decl, enumerator.m_name.c_str(), enumerator.m_value,
80+
register_byte_size * 8);
81+
}
82+
83+
type_system->CompleteTagDeclarationDefinition(enum_type);
84+
85+
return enum_type;
86+
}
87+
88+
CompilerType RegisterTypeBuilderClang::BuildFlagsType(
89+
const lldb_private::RegisterTypeFlags &flags_info,
90+
uint32_t register_byte_size, lldb::TypeSystemClangSP type_system) {
91+
std::string register_type_name = MakeTypeName(flags_info, register_byte_size);
92+
93+
// Reuse existing type if we can.
94+
if (CompilerType flags_type =
95+
type_system->GetTypeForIdentifier<clang::CXXRecordDecl>(
96+
type_system->getASTContext(), register_type_name))
97+
return flags_type;
98+
99+
// In most ABI, a change of field type means a change in storage unit.
100+
// We want it all in one unit, so we use a field type the same as the
101+
// register's size.
102+
CompilerType field_uint_type =
103+
type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
104+
register_byte_size * 8);
105+
106+
CompilerType flags_type = type_system->CreateRecordType(
107+
nullptr, OptionalClangModuleID(), register_type_name,
108+
llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC);
109+
type_system->StartTagDeclarationDefinition(flags_type);
110+
111+
for (auto field : flags_info.GetFields()) {
112+
CompilerType field_type = field_uint_type;
113+
114+
if (const RegisterTypeEnum *enum_type_info = field.GetEnum())
115+
if (!enum_type_info->GetEnumerators().empty())
116+
field_type =
117+
BuildEnumType(*enum_type_info, register_byte_size, type_system);
118+
119+
type_system->AddFieldToRecordType(flags_type, field.GetName(), field_type,
120+
field.GetSizeInBits());
121+
}
122+
123+
type_system->CompleteTagDeclarationDefinition(flags_type);
124+
// So that the size of the type matches the size of the register.
125+
type_system->SetIsPacked(flags_type);
126+
127+
// This should be true if RegisterTypeFlags padded correctly.
128+
assert(
129+
llvm::expectedToOptional(flags_type.GetByteSize(nullptr)).value_or(0) ==
130+
flags_info.GetSize());
131+
132+
return flags_type;
133+
}
134+
38135
CompilerType RegisterTypeBuilderClang::GetRegisterType(
39-
const std::string &name, const lldb_private::RegisterType &type_info,
40-
uint32_t byte_size) {
136+
const lldb_private::RegisterType &type_info, uint32_t register_byte_size) {
41137
lldb::TypeSystemClangSP type_system =
42138
ScratchTypeSystemClang::GetForTarget(m_target);
43139
assert(type_system);
44140

45-
std::string register_type_name = "__lldb_register_fields_" + name;
46-
// For now we can only build sets of flags.
47-
const RegisterTypeFlags *flags =
48-
llvm::dyn_cast<RegisterTypeFlags>(&type_info);
49-
if (!flags)
50-
return {};
51-
52-
// See if we have made this type before and can reuse it.
53-
CompilerType fields_type =
54-
type_system->GetTypeForIdentifier<clang::CXXRecordDecl>(
55-
type_system->getASTContext(), register_type_name);
56-
57-
if (!fields_type) {
58-
// In most ABI, a change of field type means a change in storage unit.
59-
// We want it all in one unit, so we use a field type the same as the
60-
// register's size.
61-
CompilerType field_uint_type =
62-
type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
63-
byte_size * 8);
64-
65-
fields_type = type_system->CreateRecordType(
66-
nullptr, OptionalClangModuleID(), register_type_name,
67-
llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC);
68-
type_system->StartTagDeclarationDefinition(fields_type);
69-
70-
// We assume that RegisterTypeFlags has padded and sorted the fields
71-
// already.
72-
for (const RegisterTypeFlags::Field &field : flags->GetFields()) {
73-
CompilerType field_type = field_uint_type;
74-
75-
if (const RegisterTypeEnum *enum_type = field.GetEnum()) {
76-
const RegisterTypeEnum::Enumerators &enumerators =
77-
enum_type->GetEnumerators();
78-
if (!enumerators.empty()) {
79-
// Enums can be used by many registers and the size of each register
80-
// may be different. The register size is used as the underlying size
81-
// of the enumerators, so we must make one enum type per register size
82-
// it is used with.
83-
std::string enum_type_name = "__lldb_register_fields_enum_" +
84-
enum_type->GetID() + "_" +
85-
std::to_string(byte_size);
86-
87-
// Enums can be used by mutiple fields and multiple registers, so we
88-
// may have built this one already.
89-
CompilerType field_enum_type =
90-
type_system->GetTypeForIdentifier<clang::EnumDecl>(
91-
type_system->getASTContext(), enum_type_name);
92-
93-
if (field_enum_type)
94-
field_type = field_enum_type;
95-
else {
96-
field_type = type_system->CreateEnumerationType(
97-
enum_type_name, type_system->GetTranslationUnitDecl(),
98-
OptionalClangModuleID(), Declaration(), field_uint_type, false);
99-
100-
type_system->StartTagDeclarationDefinition(field_type);
101-
102-
Declaration decl;
103-
for (auto enumerator : enumerators) {
104-
type_system->AddEnumerationValueToEnumerationType(
105-
field_type, decl, enumerator.m_name.c_str(),
106-
enumerator.m_value, byte_size * 8);
107-
}
108-
109-
type_system->CompleteTagDeclarationDefinition(field_type);
110-
}
111-
}
112-
}
113-
114-
type_system->AddFieldToRecordType(fields_type, field.GetName(),
115-
field_type, field.GetSizeInBits());
116-
}
117-
118-
type_system->CompleteTagDeclarationDefinition(fields_type);
119-
// So that the size of the type matches the size of the register.
120-
type_system->SetIsPacked(fields_type);
121-
122-
// This should be true if RegisterTypeFlags padded correctly.
123-
assert(llvm::expectedToOptional(fields_type.GetByteSize(nullptr))
124-
.value_or(0) == flags->GetSize());
141+
switch (type_info.getKind()) {
142+
case RegisterType::eRegisterTypeKindFlags:
143+
return BuildFlagsType(*llvm::dyn_cast<RegisterTypeFlags>(&type_info),
144+
register_byte_size, type_system);
145+
case RegisterType::eRegisterTypeKindEnum:
146+
return BuildEnumType(*llvm::dyn_cast<RegisterTypeEnum>(&type_info),
147+
register_byte_size, type_system);
125148
}
126-
127-
return fields_type;
128149
}

lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#ifndef LLDB_SOURCE_PLUGINS_REGISTERTYPEBUILDER_REGISTERTYPEBUILDERCLANG_H
1010
#define LLDB_SOURCE_PLUGINS_REGISTERTYPEBUILDER_REGISTERTYPEBUILDERCLANG_H
1111

12+
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
1213
#include "lldb/Target/RegisterTypeBuilder.h"
1314
#include "lldb/Target/Target.h"
15+
#include "lldb/Utility/RegisterTypeFlags.h"
1416

1517
namespace lldb_private {
1618
class RegisterTypeBuilderClang : public RegisterTypeBuilder {
@@ -28,11 +30,18 @@ class RegisterTypeBuilderClang : public RegisterTypeBuilder {
2830
}
2931
static lldb::RegisterTypeBuilderSP CreateInstance(Target &target);
3032

31-
CompilerType GetRegisterType(const std::string &name,
32-
const lldb_private::RegisterType &type_info,
33-
uint32_t byte_size) override;
33+
CompilerType GetRegisterType(const lldb_private::RegisterType &type_info,
34+
uint32_t register_byte_size) override;
3435

3536
private:
37+
CompilerType BuildEnumType(const RegisterTypeEnum &enum_type_info,
38+
uint32_t register_byte_size,
39+
lldb::TypeSystemClangSP type_system);
40+
41+
CompilerType BuildFlagsType(const RegisterTypeFlags &flags_info,
42+
uint32_t register_byte_size,
43+
lldb::TypeSystemClangSP type_system);
44+
3645
Target &m_target;
3746
};
3847
} // namespace lldb_private

lldb/source/Target/Target.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2730,14 +2730,12 @@ Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language,
27302730
}
27312731

27322732
CompilerType
2733-
Target::GetRegisterType(const std::string &name,
2734-
const lldb_private::RegisterType &type_info,
2733+
Target::GetRegisterType(const lldb_private::RegisterType &type_info,
27352734
uint32_t byte_size) {
27362735
if (!m_register_type_builder_sp)
27372736
m_register_type_builder_sp = PluginManager::GetRegisterTypeBuilder(*this);
27382737
assert(m_register_type_builder_sp);
2739-
return m_register_type_builder_sp->GetRegisterType(name, type_info,
2740-
byte_size);
2738+
return m_register_type_builder_sp->GetRegisterType(type_info, byte_size);
27412739
}
27422740

27432741
std::vector<lldb::TypeSystemSP>

0 commit comments

Comments
 (0)