xref: /llvm-project/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp (revision 208a08c3b7b00c05629c3f18811aac81f17cd81b)
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