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
17using namespace lldb_private;
18
19LLDB_PLUGIN_DEFINE(RegisterTypeBuilderClang)
20
21void RegisterTypeBuilderClang::Initialize() {
22 static llvm::once_flag g_once_flag;
23 llvm::call_once(flag&: g_once_flag, F: []() {
24 PluginManager::RegisterPlugin(name: GetPluginNameStatic(),
25 description: GetPluginDescriptionStatic(), create_callback: CreateInstance);
26 });
27}
28
29void RegisterTypeBuilderClang::Terminate() {}
30
31lldb::RegisterTypeBuilderSP
32RegisterTypeBuilderClang::CreateInstance(Target &target) {
33 return std::make_shared<RegisterTypeBuilderClang>(args&: target);
34}
35
36RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target &target)
37 : m_target(target) {}
38
39CompilerType 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(target&: m_target);
44 assert(type_system);
45
46 std::string register_type_name = "__lldb_register_fields_";
47 register_type_name += name;
48 // See if we have made this type before and can reuse it.
49 CompilerType fields_type =
50 type_system->GetTypeForIdentifier<clang::CXXRecordDecl>(
51 type_name: register_type_name);
52
53 if (!fields_type) {
54 // In most ABI, a change of field type means a change in storage unit.
55 // We want it all in one unit, so we use a field type the same as the
56 // register's size.
57 CompilerType field_uint_type =
58 type_system->GetBuiltinTypeForEncodingAndBitSize(encoding: lldb::eEncodingUint,
59 bit_size: byte_size * 8);
60
61 fields_type = type_system->CreateRecordType(
62 decl_ctx: nullptr, owning_module: OptionalClangModuleID(), access_type: lldb::eAccessPublic,
63 name: register_type_name, kind: llvm::to_underlying(E: clang::TagTypeKind::Struct),
64 language: lldb::eLanguageTypeC);
65 type_system->StartTagDeclarationDefinition(type: fields_type);
66
67 // We assume that RegisterFlags has padded and sorted the fields
68 // already.
69 for (const RegisterFlags::Field &field : flags.GetFields()) {
70 type_system->AddFieldToRecordType(type: fields_type, name: field.GetName(),
71 field_type: field_uint_type, access: lldb::eAccessPublic,
72 bitfield_bit_size: field.GetSizeInBits());
73 }
74
75 type_system->CompleteTagDeclarationDefinition(type: fields_type);
76 // So that the size of the type matches the size of the register.
77 type_system->SetIsPacked(fields_type);
78
79 // This should be true if RegisterFlags padded correctly.
80 assert(*fields_type.GetByteSize(nullptr) == flags.GetSize());
81 }
82
83 return fields_type;
84}
85

source code of lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp