1 //===-- RegisterTypeBuilderClang.cpp ---------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "clang/AST/DeclCXX.h"
10
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"
16
17 using namespace lldb_private;
18
LLDB_PLUGIN_DEFINE(RegisterTypeBuilderClang)19 LLDB_PLUGIN_DEFINE(RegisterTypeBuilderClang)
20
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);
26 });
27 }
28
Terminate()29 void RegisterTypeBuilderClang::Terminate() {}
30
31 lldb::RegisterTypeBuilderSP
CreateInstance(Target & target)32 RegisterTypeBuilderClang::CreateInstance(Target &target) {
33 return std::make_shared<RegisterTypeBuilderClang>(target);
34 }
35
RegisterTypeBuilderClang(Target & target)36 RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target &target)
37 : m_target(target) {}
38
GetRegisterType(const std::string & name,const lldb_private::RegisterFlags & flags,uint32_t byte_size)39 CompilerType RegisterTypeBuilderClang::GetRegisterType(
40 const std::string &name, const lldb_private::RegisterFlags &flags,
41 uint32_t byte_size) {
42 lldb::TypeSystemClangSP type_system =
43 ScratchTypeSystemClang::GetForTarget(m_target);
44 assert(type_system);
45
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>(
50 register_type_name);
51
52 if (!fields_type) {
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
55 // register's size.
56 CompilerType field_uint_type =
57 type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
58 byte_size * 8);
59
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);
65
66 // We assume that RegisterFlags has padded and sorted the fields
67 // already.
68 for (const RegisterFlags::Field &field : flags.GetFields()) {
69 CompilerType field_type = field_uint_type;
70
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
77 // it is used with.
78 std::string enum_type_name = "__lldb_register_fields_enum_" +
79 enum_type->GetID() + "_" +
80 std::to_string(byte_size);
81
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>(
86 enum_type_name);
87
88 if (field_enum_type)
89 field_type = field_enum_type;
90 else {
91 field_type = type_system->CreateEnumerationType(
92 enum_type_name, type_system->GetTranslationUnitDecl(),
93 OptionalClangModuleID(), Declaration(), field_uint_type, false);
94
95 type_system->StartTagDeclarationDefinition(field_type);
96
97 Declaration decl;
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);
102 }
103
104 type_system->CompleteTagDeclarationDefinition(field_type);
105 }
106 }
107 }
108
109 type_system->AddFieldToRecordType(fields_type, field.GetName(),
110 field_type, lldb::eAccessPublic,
111 field.GetSizeInBits());
112 }
113
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);
117
118 // This should be true if RegisterFlags padded correctly.
119 assert(*fields_type.GetByteSize(nullptr) == flags.GetSize());
120 }
121
122 return fields_type;
123 }
124