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#include "llvm/Support/ErrorHandling.h"
17
18#include <algorithm>
19
20using namespace lldb_private;
21
23
28
32
35 return std::make_shared<RegisterTypeBuilderClang>(target);
36}
37
40
42 const RegisterTypeBuiltin *builtin_type, uint32_t expected_byte_size,
43 lldb::TypeSystemClangSP type_system) {
44 if (auto type = GetExistingCompilerType(builtin_type, expected_byte_size))
45 return *type;
46
47 CompilerType compiler_type;
48 clang::ASTContext &ast = type_system->getASTContext();
49 // These GDB types have semantics that encoding and byte size cannot express.
50 if (builtin_type->GetID() == "data_ptr" ||
51 builtin_type->GetID() == "code_ptr")
52 compiler_type = type_system->GetType(ast.VoidPtrTy);
53 else if (builtin_type->GetID() == "bool")
54 compiler_type = type_system->GetType(ast.BoolTy);
55 else if (builtin_type->GetID() == "bfloat16")
56 compiler_type = type_system->GetType(ast.BFloat16Ty);
57 else if (std::optional<uint64_t> byte_size = builtin_type->GetByteSize())
58 compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize(
59 builtin_type->GetEncoding(), *byte_size * 8);
60
61 if (!compiler_type.IsValid() ||
62 llvm::expectedToOptional(compiler_type.GetByteSize(nullptr)) !=
63 expected_byte_size)
64 return {};
65
66 m_type_cache.try_emplace(
67 std::make_pair(builtin_type->GetUID(), expected_byte_size),
68 compiler_type);
69 return compiler_type;
70}
71
74 uint32_t register_byte_size,
75 lldb::TypeSystemClangSP type_system) {
76 if (auto maybe_compiler_type =
77 GetExistingCompilerType(enum_type_info, register_byte_size))
78 return *maybe_compiler_type;
79
80 CompilerType register_uint_type =
81 type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
82 register_byte_size * 8);
83 CompilerType enum_type = type_system->CreateEnumerationType(
84 "", type_system->GetTranslationUnitDecl(), OptionalClangModuleID(),
85 Declaration(), register_uint_type, false);
86
87 type_system->StartTagDeclarationDefinition(enum_type);
88
89 Declaration decl;
90 for (const auto &enumerator : enum_type_info->GetEnumerators()) {
91 type_system->AddEnumerationValueToEnumerationType(
92 enum_type, decl, enumerator.m_name.c_str(), enumerator.m_value,
93 register_byte_size * 8);
94 }
95
96 type_system->CompleteTagDeclarationDefinition(enum_type);
97
98 m_type_cache.try_emplace(
99 std::make_pair(enum_type_info->GetUID(), register_byte_size), enum_type);
100 return enum_type;
101}
102
104 const lldb_private::RegisterTypeFlags *flags_info,
105 uint32_t register_byte_size, lldb::TypeSystemClangSP type_system) {
106 if (auto maybe_compiler_type =
107 GetExistingCompilerType(flags_info, register_byte_size))
108 return *maybe_compiler_type;
109
110 // In most ABI, a change of field type means a change in storage unit.
111 // We want it all in one unit, so we use a field type the same as the
112 // register's size.
113 CompilerType field_uint_type =
114 type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
115 register_byte_size * 8);
116
117 CompilerType flags_type = type_system->CreateRecordType(
118 nullptr, OptionalClangModuleID(), "",
119 llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC);
120 type_system->StartTagDeclarationDefinition(flags_type);
121
122 for (auto field : flags_info->GetFields()) {
123 CompilerType field_type = field_uint_type;
124
125 if (const RegisterTypeEnum *enum_type_info = field.GetEnum())
126 if (!enum_type_info->GetEnumerators().empty())
127 field_type =
128 BuildEnumType(enum_type_info, register_byte_size, type_system);
129
130 type_system->AddFieldToRecordType(flags_type, field.GetName(), field_type,
131 field.GetSizeInBits());
132 }
133
134 type_system->CompleteTagDeclarationDefinition(flags_type);
135 // So that the size of the type matches the size of the register.
136 type_system->SetIsPacked(flags_type);
137
138 // This should be true if RegisterTypeFlags padded correctly.
139 assert(
140 llvm::expectedToOptional(flags_type.GetByteSize(nullptr)).value_or(0) ==
141 flags_info->GetSize());
142
143 m_type_cache.try_emplace(
144 std::make_pair(flags_info->GetUID(), register_byte_size), flags_type);
145 return flags_type;
146}
147
150 uint32_t expected_byte_size,
151 lldb::TypeSystemClangSP type_system) {
152 if (!expected_byte_size)
153 return {};
154 if (auto type = GetExistingCompilerType(vector_type, expected_byte_size))
155 return *type;
156
157 std::optional<uint32_t> element_size =
158 GetExpectedByteSize(vector_type->GetElementType(), type_system);
159 if (!element_size || *element_size > UINT32_MAX / vector_type->GetCount() ||
160 *element_size * vector_type->GetCount() != expected_byte_size)
161 return {};
162
163 const RegisterType *element_register_type = vector_type->GetElementType();
164 CompilerType element_type =
165 BuildType(element_register_type, *element_size, type_system);
166 if (!element_type.IsValid())
167 return {};
168
169 const auto *builtin_element =
170 llvm::dyn_cast<RegisterTypeBuiltin>(element_register_type);
171 bool pointer_element =
172 builtin_element && (builtin_element->GetID() == "data_ptr" ||
173 builtin_element->GetID() == "code_ptr");
174 // Preserve vector semantics when Clang can represent the XML shape without
175 // padding. Use an array for pointer, boolean, nested and non-power-of-two
176 // vectors so that their layout matches the XML exactly.
177 bool use_vector = builtin_element && !pointer_element &&
178 builtin_element->GetID() != "bool" &&
179 llvm::has_single_bit(vector_type->GetCount());
180 CompilerType compiler_type = type_system->CreateArrayType(
181 element_type, vector_type->GetCount(), use_vector);
182
183 auto compiler_size =
184 llvm::expectedToOptional(compiler_type.GetByteSize(nullptr));
185 // Target ABI rules can still pad a Clang vector. Fall back to an array when
186 // that gives the exact byte size described by the register XML.
187 if (use_vector && compiler_size != expected_byte_size) {
188 compiler_type = type_system->CreateArrayType(
189 element_type, vector_type->GetCount(), /*is_vector=*/false);
190 compiler_size =
191 llvm::expectedToOptional(compiler_type.GetByteSize(nullptr));
192 }
193 if (compiler_size != expected_byte_size)
194 return {};
195
196 m_type_cache.try_emplace(
197 std::make_pair(vector_type->GetUID(), expected_byte_size), compiler_type);
198 return compiler_type;
199}
200
203 uint32_t available_byte_size,
204 lldb::TypeSystemClangSP type_system) {
205 std::optional<uint32_t> byte_size =
206 GetExpectedByteSize(union_type, type_system);
207 if (!byte_size || *byte_size > available_byte_size)
208 return {};
209 uint32_t expected_byte_size = *byte_size;
210 if (!expected_byte_size)
211 return {};
212 if (auto type = GetExistingCompilerType(union_type, expected_byte_size))
213 return *type;
214
215 std::vector<std::pair<llvm::StringRef, CompilerType>> fields;
216 fields.reserve(union_type->GetFields().size());
217 // XML parsing restricts union fields to builtins, vectors, and unions.
218 // BuildType recursively constructs the vector and union cases.
219 for (const RegisterTypeUnion::Field &field : union_type->GetFields()) {
220 std::optional<uint32_t> field_size =
221 GetExpectedByteSize(field.GetType(), type_system);
222 if (!field_size || *field_size > expected_byte_size)
223 return {};
224
225 CompilerType field_type =
226 BuildType(field.GetType(), *field_size, type_system);
227 if (!field_type.IsValid())
228 return {};
229 fields.emplace_back(field.GetName(), field_type);
230 }
231
232 // XML type IDs are scoped to a feature and need not be unique or valid
233 // Clang identifiers. Keep the ID on RegisterTypeUnion for XML lookup and use
234 // the process-wide UID and instantiated size for a unique scratch AST tag.
235 std::string type_name = "__lldb_register_union_" +
236 std::to_string(union_type->GetUID()) + "_" +
237 std::to_string(expected_byte_size);
238 CompilerType compiler_type = type_system->CreateRecordType(
239 nullptr, OptionalClangModuleID(), type_name,
240 llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC);
241 type_system->StartTagDeclarationDefinition(compiler_type);
242 for (const auto &[field_name, field_type] : fields)
243 type_system->AddFieldToRecordType(compiler_type, field_name, field_type,
244 /*bitfield_bit_size=*/0);
245 type_system->CompleteTagDeclarationDefinition(compiler_type);
246 type_system->SetIsPacked(compiler_type);
247
248 if (llvm::expectedToOptional(compiler_type.GetByteSize(nullptr)) !=
249 expected_byte_size)
250 return {};
251
252 m_type_cache.try_emplace(
253 std::make_pair(union_type->GetUID(), expected_byte_size), compiler_type);
254 return compiler_type;
255}
256
259 uint32_t expected_byte_size,
260 lldb::TypeSystemClangSP type_system) {
261 switch (register_type->getKind()) {
263 return BuildBuiltinType(llvm::cast<RegisterTypeBuiltin>(register_type),
264 expected_byte_size, type_system);
266 return BuildVectorType(llvm::cast<RegisterTypeVector>(register_type),
267 expected_byte_size, type_system);
269 return BuildUnionType(llvm::cast<RegisterTypeUnion>(register_type),
270 expected_byte_size, type_system);
273 return {};
274 }
275}
276
278 const RegisterType *register_type, lldb::TypeSystemClangSP type_system) {
279 if (std::optional<uint64_t> fixed_size = register_type->GetByteSize()) {
280 if (*fixed_size <= UINT32_MAX)
281 return static_cast<uint32_t>(*fixed_size);
282 return std::nullopt;
283 }
284
285 switch (register_type->getKind()) {
287 const auto *builtin_type = llvm::cast<RegisterTypeBuiltin>(register_type);
288 if (builtin_type->GetID() != "data_ptr" &&
289 builtin_type->GetID() != "code_ptr")
290 return std::nullopt;
291 std::optional<uint64_t> pointer_size = llvm::expectedToOptional(
292 type_system->GetType(type_system->getASTContext().VoidPtrTy)
293 .GetByteSize(nullptr));
294 if (!pointer_size || *pointer_size > UINT32_MAX)
295 return std::nullopt;
296 return static_cast<uint32_t>(*pointer_size);
297 }
299 const auto *vector_type = llvm::cast<RegisterTypeVector>(register_type);
300 std::optional<uint32_t> element_size =
301 GetExpectedByteSize(vector_type->GetElementType(), type_system);
302 if (!element_size || *element_size > UINT32_MAX / vector_type->GetCount())
303 return std::nullopt;
304 return *element_size * vector_type->GetCount();
305 }
307 uint32_t byte_size = 0;
308 for (const RegisterTypeUnion::Field &field :
309 llvm::cast<RegisterTypeUnion>(register_type)->GetFields()) {
310 std::optional<uint32_t> field_size =
311 GetExpectedByteSize(field.GetType(), type_system);
312 if (!field_size)
313 return std::nullopt;
314 byte_size = std::max(byte_size, *field_size);
315 }
316 return byte_size;
317 }
320 // Enum and flags use dedicated top-level builders. They are not supported
321 // when recursively building vector or union members.
322 return std::nullopt;
323 }
324}
325
328 lldb::TypeSystemClangSP type_system =
330 assert(type_system);
331
332 if (m_cached_type_system.lock() != type_system) {
333 m_type_cache.clear();
334 m_cached_type_system = type_system;
335 }
336
337 if (!reg_info.register_type)
338 return CompilerType();
339
340 // Note that we do not check the type cache here because types can be nested.
341 // There is a cache check in each of the Build<subtype> methods, and those
342 // methods may call each other (Flags may use Enums for example).
343
344 switch (reg_info.register_type->getKind()) {
346 return BuildType(reg_info.register_type, reg_info.byte_size, type_system);
348 return BuildFlagsType(
349 llvm::dyn_cast<RegisterTypeFlags>(reg_info.register_type),
350 reg_info.byte_size, type_system);
352 return BuildEnumType(
353 llvm::dyn_cast<RegisterTypeEnum>(reg_info.register_type),
354 reg_info.byte_size, type_system);
356 return BuildType(reg_info.register_type, reg_info.byte_size, type_system);
358 return BuildType(reg_info.register_type, reg_info.byte_size, type_system);
359 }
360 llvm_unreachable("Unhandled RegisterType kind");
361}
362
364 const RegisterType *register_type, uint32_t register_byte_size) {
365 auto cached =
366 m_type_cache.find({register_type->GetUID(), register_byte_size});
367 if (cached != m_type_cache.end())
368 return cached->second;
369
370 return {};
371}
#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)
CompilerType BuildType(const RegisterType *register_type, uint32_t expected_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)
CompilerType BuildUnionType(const RegisterTypeUnion *union_type, uint32_t available_byte_size, lldb::TypeSystemClangSP type_system)
std::optional< uint32_t > GetExpectedByteSize(const RegisterType *register_type, lldb::TypeSystemClangSP type_system)
Return the target-resolved byte size of register_type.
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 union type.
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.