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 
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 
29 void RegisterTypeBuilderClang::Terminate() {}
30 
31 lldb::RegisterTypeBuilderSP
32 RegisterTypeBuilderClang::CreateInstance(Target &target) {
33   return std::make_shared<RegisterTypeBuilderClang>(target);
34 }
35 
36 RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target &target)
37     : m_target(target) {}
38 
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_";
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           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(lldb::eEncodingUint,
59                                                          byte_size * 8);
60 
61     fields_type = type_system->CreateRecordType(
62         nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
63         register_type_name, clang::TTK_Struct, 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       type_system->AddFieldToRecordType(fields_type, field.GetName(),
70                                         field_uint_type, lldb::eAccessPublic,
71                                         field.GetSizeInBits());
72     }
73 
74     type_system->CompleteTagDeclarationDefinition(fields_type);
75     // So that the size of the type matches the size of the register.
76     type_system->SetIsPacked(fields_type);
77 
78     // This should be true if RegisterFlags padded correctly.
79     assert(*fields_type.GetByteSize(nullptr) == flags.GetSize());
80   }
81 
82   return fields_type;
83 }
84