LLDB mainline
RegisterTypeBuilderClang.cpp
Go to the documentation of this file.
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
15#include "llvm/ADT/bit.h"
16
17using namespace lldb_private;
18
20
25
29
32 return std::make_shared<RegisterTypeBuilderClang>(target);
33}
34
37
39 const RegisterTypeBuiltin *builtin_type, uint32_t expected_byte_size,
40 lldb::TypeSystemClangSP type_system) {
41 if (auto type = GetExistingCompilerType(builtin_type, expected_byte_size))
42 return *type;
43
44 CompilerType compiler_type;
45 clang::ASTContext &ast = type_system->getASTContext();
46 // These GDB types have semantics that encoding and byte size cannot express.
47 if (builtin_type->GetID() == "data_ptr" ||
48 builtin_type->GetID() == "code_ptr")
49 compiler_type = type_system->GetType(ast.VoidPtrTy);
50 else if (builtin_type->GetID() == "bool")
51 compiler_type = type_system->GetType(ast.BoolTy);
52 else if (builtin_type->GetID() == "bfloat16")
53 compiler_type = type_system->GetType(ast.BFloat16Ty);
54 else if (std::optional<uint64_t> byte_size = builtin_type->GetByteSize())
55 compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize(
56 builtin_type->GetEncoding(), *byte_size * 8);
57
58 if (!compiler_type.IsValid() ||
59 llvm::expectedToOptional(compiler_type.GetByteSize(nullptr)) !=
60 expected_byte_size)
61 return {};
62
63 m_type_cache.try_emplace(
64 std::make_pair(builtin_type->GetUID(), expected_byte_size),
65 compiler_type);
66 return compiler_type;
67}
68
71 uint32_t register_byte_size,
72 lldb::TypeSystemClangSP type_system) {
73 if (auto maybe_compiler_type =
74 GetExistingCompilerType(enum_type_info, register_byte_size))
75 return *maybe_compiler_type;
76
77 CompilerType register_uint_type =
78 type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
79 register_byte_size * 8);
80 CompilerType enum_type = type_system->CreateEnumerationType(
81 "", type_system->GetTranslationUnitDecl(), OptionalClangModuleID(),
82 Declaration(), register_uint_type, false);
83
84 type_system->StartTagDeclarationDefinition(enum_type);
85
86 Declaration decl;
87 for (const auto &enumerator : enum_type_info->GetEnumerators()) {
88 type_system->AddEnumerationValueToEnumerationType(
89 enum_type, decl, enumerator.m_name.c_str(), enumerator.m_value,
90 register_byte_size * 8);
91 }
92
93 type_system->CompleteTagDeclarationDefinition(enum_type);
94
95 m_type_cache.try_emplace(
96 std::make_pair(enum_type_info->GetUID(), register_byte_size), enum_type);
97 return enum_type;
98}
99
101 const lldb_private::RegisterTypeFlags *flags_info,
102 uint32_t register_byte_size, lldb::TypeSystemClangSP type_system) {
103 if (auto maybe_compiler_type =
104 GetExistingCompilerType(flags_info, register_byte_size))
105 return *maybe_compiler_type;
106
107 // In most ABI, a change of field type means a change in storage unit.
108 // We want it all in one unit, so we use a field type the same as the
109 // register's size.
110 CompilerType field_uint_type =
111 type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
112 register_byte_size * 8);
113
114 CompilerType flags_type = type_system->CreateRecordType(
115 nullptr, OptionalClangModuleID(), "",
116 llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC);
117 type_system->StartTagDeclarationDefinition(flags_type);
118
119 for (auto field : flags_info->GetFields()) {
120 CompilerType field_type = field_uint_type;
121
122 if (const RegisterTypeEnum *enum_type_info = field.GetEnum())
123 if (!enum_type_info->GetEnumerators().empty())
124 field_type =
125 BuildEnumType(enum_type_info, register_byte_size, type_system);
126
127 type_system->AddFieldToRecordType(flags_type, field.GetName(), field_type,
128 field.GetSizeInBits());
129 }
130
131 type_system->CompleteTagDeclarationDefinition(flags_type);
132 // So that the size of the type matches the size of the register.
133 type_system->SetIsPacked(flags_type);
134
135 // This should be true if RegisterTypeFlags padded correctly.
136 assert(
137 llvm::expectedToOptional(flags_type.GetByteSize(nullptr)).value_or(0) ==
138 flags_info->GetSize());
139
140 m_type_cache.try_emplace(
141 std::make_pair(flags_info->GetUID(), register_byte_size), flags_type);
142 return flags_type;
143}
144
147 uint32_t expected_byte_size,
148 lldb::TypeSystemClangSP type_system) {
149 if (!expected_byte_size)
150 return {};
151 if (auto type = GetExistingCompilerType(vector_type, expected_byte_size))
152 return *type;
153
154 std::optional<uint64_t> element_size =
155 vector_type->GetElementType()->GetByteSize();
156 if (!element_size) {
157 if (expected_byte_size % vector_type->GetCount())
158 return {};
159 element_size = expected_byte_size / vector_type->GetCount();
160 }
161 if (*element_size > UINT32_MAX ||
162 expected_byte_size % vector_type->GetCount() ||
163 *element_size != expected_byte_size / vector_type->GetCount())
164 return {};
165
166 CompilerType element_type;
167 const RegisterType *element_register_type = vector_type->GetElementType();
168 switch (element_register_type->getKind()) {
170 element_type =
171 BuildBuiltinType(llvm::cast<RegisterTypeBuiltin>(element_register_type),
172 *element_size, type_system);
173 break;
175 element_type =
176 BuildVectorType(llvm::cast<RegisterTypeVector>(element_register_type),
177 *element_size, type_system);
178 break;
181 return {};
182 }
183 if (!element_type.IsValid())
184 return {};
185
186 const auto *builtin_element =
187 llvm::dyn_cast<RegisterTypeBuiltin>(element_register_type);
188 bool pointer_element =
189 builtin_element && (builtin_element->GetID() == "data_ptr" ||
190 builtin_element->GetID() == "code_ptr");
191 // Preserve vector semantics when Clang can represent the XML shape without
192 // padding. Use an array for pointer, boolean, nested and non-power-of-two
193 // vectors so that their layout matches the XML exactly.
194 bool use_vector = builtin_element && !pointer_element &&
195 builtin_element->GetID() != "bool" &&
196 llvm::has_single_bit(vector_type->GetCount());
197 CompilerType compiler_type = type_system->CreateArrayType(
198 element_type, vector_type->GetCount(), use_vector);
199
200 auto compiler_size =
201 llvm::expectedToOptional(compiler_type.GetByteSize(nullptr));
202 // Target ABI rules can still pad a Clang vector. Fall back to an array when
203 // that gives the exact byte size described by the register XML.
204 if (use_vector && compiler_size != expected_byte_size) {
205 compiler_type = type_system->CreateArrayType(
206 element_type, vector_type->GetCount(), /*is_vector=*/false);
207 compiler_size =
208 llvm::expectedToOptional(compiler_type.GetByteSize(nullptr));
209 }
210 if (compiler_size != expected_byte_size)
211 return {};
212
213 m_type_cache.try_emplace(
214 std::make_pair(vector_type->GetUID(), expected_byte_size), compiler_type);
215 return compiler_type;
216}
217
220 lldb::TypeSystemClangSP type_system =
222 assert(type_system);
223
224 if (m_cached_type_system.lock() != type_system) {
225 m_type_cache.clear();
226 m_cached_type_system = type_system;
227 }
228
229 if (!reg_info.register_type)
230 return CompilerType();
231
232 // Note that we do not check the type cache here because types can be nested.
233 // There is a cache check in each of the Build<subtype> methods, and those
234 // methods may call each other (Flags may use Enums for example).
235
236 switch (reg_info.register_type->getKind()) {
238 return BuildBuiltinType(
239 llvm::cast<RegisterTypeBuiltin>(reg_info.register_type),
240 reg_info.byte_size, type_system);
242 return BuildFlagsType(
243 llvm::dyn_cast<RegisterTypeFlags>(reg_info.register_type),
244 reg_info.byte_size, type_system);
246 return BuildEnumType(
247 llvm::dyn_cast<RegisterTypeEnum>(reg_info.register_type),
248 reg_info.byte_size, type_system);
250 return BuildVectorType(
251 llvm::cast<RegisterTypeVector>(reg_info.register_type),
252 reg_info.byte_size, type_system);
253 }
254}
255
257 const RegisterType *register_type, uint32_t register_byte_size) {
258 auto cached =
259 m_type_cache.find({register_type->GetUID(), register_byte_size});
260 if (cached != m_type_cache.end())
261 return cached->second;
262
263 return {};
264}
#define LLDB_PLUGIN_DEFINE(PluginName)
Generic representation of a type in a programming language.
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
A class that describes the declaration location of a lldb object.
Definition Declaration.h:24
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
CompilerType BuildVectorType(const RegisterTypeVector *vector_type, uint32_t expected_byte_size, lldb::TypeSystemClangSP type_system)
std::optional< CompilerType > GetExistingCompilerType(const RegisterType *register_type, uint32_t register_byte_size)
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)
std::weak_ptr< TypeSystemClang > m_cached_type_system
CompilerType GetRegisterType(const RegisterInfo &reg_info) override
Do not cache the returned CompilerType.
llvm::SmallDenseMap< std::pair< uint64_t, uint32_t >, CompilerType, 8 > m_type_cache
CompilerType BuildBuiltinType(const RegisterTypeBuiltin *builtin_type, uint32_t expected_byte_size, lldb::TypeSystemClangSP type_system)
static lldb::RegisterTypeBuilderSP CreateInstance(Target &target)
A predefined GDB target-description type.
lldb::Encoding GetEncoding() const
std::optional< uint64_t > GetByteSize() const override
Return this type's fixed size in bytes, if it has one.
const Enumerators & GetEnumerators() const
const std::vector< Field > & GetFields() const
A GDB target-description vector type. The element type must outlive it.
const RegisterType * GetElementType() const
RegisterTypeKind getKind() const
virtual std::optional< uint64_t > GetByteSize() const
Return this type's fixed size in bytes, if it has one.
const std::string & GetID() const
uint64_t GetUID() const
Return an identifier unique among all RegisterType instances constructed during the lifetime of the L...
static lldb::TypeSystemClangSP GetForTarget(Target &target, std::optional< IsolatedASTKind > ast_kind=DefaultAST, bool create_on_demand=true)
Returns the scratch TypeSystemClang for the given target.
#define UINT32_MAX
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::RegisterTypeBuilder > RegisterTypeBuilderSP
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eEncodingUint
unsigned integer
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_size
Size in bytes of the register.
const RegisterType * register_type
If not nullptr, a type defined by XML descriptions.