1 //===-- RegisterTypeBuilderClang.cpp ---------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "clang/AST/DeclCXX.h"
11 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
12 #include "RegisterTypeBuilderClang.h"
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Target/RegisterFlags.h"
15 #include "lldb/lldb-enumerations.h"
17 using namespace lldb_private
;
19 LLDB_PLUGIN_DEFINE(RegisterTypeBuilderClang
)
21 void RegisterTypeBuilderClang::Initialize() {
22 static llvm::once_flag g_once_flag
;
23 llvm::call_once(g_once_flag
, []() {
24 PluginManager::RegisterPlugin(GetPluginNameStatic(),
25 GetPluginDescriptionStatic(), CreateInstance
);
29 void RegisterTypeBuilderClang::Terminate() {}
31 lldb::RegisterTypeBuilderSP
32 RegisterTypeBuilderClang::CreateInstance(Target
&target
) {
33 return std::make_shared
<RegisterTypeBuilderClang
>(target
);
36 RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target
&target
)
39 CompilerType
RegisterTypeBuilderClang::GetRegisterType(
40 const std::string
&name
, const lldb_private::RegisterFlags
&flags
,
42 lldb::TypeSystemClangSP type_system
=
43 ScratchTypeSystemClang::GetForTarget(m_target
);
46 std::string register_type_name
= "__lldb_register_fields_" + name
;
47 // See if we have made this type before and can reuse it.
48 CompilerType fields_type
=
49 type_system
->GetTypeForIdentifier
<clang::CXXRecordDecl
>(
53 // In most ABI, a change of field type means a change in storage unit.
54 // We want it all in one unit, so we use a field type the same as the
56 CompilerType field_uint_type
=
57 type_system
->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint
,
60 fields_type
= type_system
->CreateRecordType(
61 nullptr, OptionalClangModuleID(), lldb::eAccessPublic
,
62 register_type_name
, llvm::to_underlying(clang::TagTypeKind::Struct
),
63 lldb::eLanguageTypeC
);
64 type_system
->StartTagDeclarationDefinition(fields_type
);
66 // We assume that RegisterFlags has padded and sorted the fields
68 for (const RegisterFlags::Field
&field
: flags
.GetFields()) {
69 CompilerType field_type
= field_uint_type
;
71 if (const FieldEnum
*enum_type
= field
.GetEnum()) {
72 const FieldEnum::Enumerators
&enumerators
= enum_type
->GetEnumerators();
73 if (!enumerators
.empty()) {
74 // Enums can be used by many registers and the size of each register
75 // may be different. The register size is used as the underlying size
76 // of the enumerators, so we must make one enum type per register size
78 std::string enum_type_name
= "__lldb_register_fields_enum_" +
79 enum_type
->GetID() + "_" +
80 std::to_string(byte_size
);
82 // Enums can be used by mutiple fields and multiple registers, so we
83 // may have built this one already.
84 CompilerType field_enum_type
=
85 type_system
->GetTypeForIdentifier
<clang::EnumDecl
>(
89 field_type
= field_enum_type
;
91 field_type
= type_system
->CreateEnumerationType(
92 enum_type_name
, type_system
->GetTranslationUnitDecl(),
93 OptionalClangModuleID(), Declaration(), field_uint_type
, false);
95 type_system
->StartTagDeclarationDefinition(field_type
);
98 for (auto enumerator
: enumerators
) {
99 type_system
->AddEnumerationValueToEnumerationType(
100 field_type
, decl
, enumerator
.m_name
.c_str(),
101 enumerator
.m_value
, byte_size
* 8);
104 type_system
->CompleteTagDeclarationDefinition(field_type
);
109 type_system
->AddFieldToRecordType(fields_type
, field
.GetName(),
110 field_type
, lldb::eAccessPublic
,
111 field
.GetSizeInBits());
114 type_system
->CompleteTagDeclarationDefinition(fields_type
);
115 // So that the size of the type matches the size of the register.
116 type_system
->SetIsPacked(fields_type
);
118 // This should be true if RegisterFlags padded correctly.
119 assert(*fields_type
.GetByteSize(nullptr) == flags
.GetSize());