LLDB mainline
RegisterType.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
10
11#include "lldb/Utility/Log.h"
12#include "lldb/Utility/Stream.h"
13#include "llvm/ADT/StringExtras.h"
14#include "llvm/Support/Casting.h"
15#include "llvm/Support/raw_ostream.h"
16
17#include <algorithm>
18#include <atomic>
19#include <cassert>
20#include <cinttypes>
21#include <limits>
22
23using namespace lldb_private;
24
25static std::atomic<uint64_t> g_next_register_type_uid{1};
26
28 : m_kind(kind), m_id(std::move(id)),
29 m_uid(g_next_register_type_uid.fetch_add(1, std::memory_order_relaxed)) {}
30
32 std::string id)
33 : RegisterType(kind, std::move(id)) {}
34
36 std::unordered_set<std::string> &previously_emitted,
37 const RegisterType *user) const {
38 // XML type references use IDs, so definitions must also be unique by ID.
39 if (!previously_emitted.insert(GetID()).second)
40 return;
41
42 // Emit this type's dependencies first.
43 for (auto dep : m_dependencies)
44 dep->ToXML(strm, previously_emitted, this);
45
46 // Finally emit this type.
47 ToXMLElement(strm, user);
48}
49
50void RegisterType::PrintXMLAttributeValue(Stream &strm, llvm::StringRef value) {
51 std::string escaped;
52 llvm::raw_string_ostream escape_strm(escaped);
53 llvm::printHTMLEscaped(value, escape_strm);
54 strm << escaped;
55}
56
58 lldb::Encoding encoding,
59 lldb::Format format,
60 std::optional<uint64_t> byte_size)
61 : RegisterType(eRegisterTypeKindBuiltin, std::move(id)),
62 m_encoding(encoding), m_format(format), m_byte_size(byte_size) {}
63
64void RegisterTypeBuiltin::ToXML(Stream &, std::unordered_set<std::string> &,
65 const RegisterType *) const {}
66
68
70 const RegisterType *element_type,
71 uint32_t count)
73 m_element_type(element_type), m_count(count) {
74 assert(m_element_type && "Vector element type cannot be null");
75 assert(m_count && "Vector element count cannot be zero");
77}
78
79std::optional<uint64_t> RegisterTypeVector::GetByteSize() const {
80 std::optional<uint64_t> element_size = m_element_type->GetByteSize();
81 if (!element_size ||
82 *element_size > std::numeric_limits<uint64_t>::max() / m_count)
83 return std::nullopt;
84 return *element_size * m_count;
85}
86
87bool RegisterTypeVector::IsByteSizeCompatible(uint64_t byte_size) const {
88 if (!byte_size || byte_size % m_count)
89 return false;
90
91 uint64_t element_byte_size = byte_size / m_count;
92 if (std::optional<uint64_t> fixed_size = m_element_type->GetByteSize())
93 return *fixed_size == element_byte_size;
94 if (const auto *vector = llvm::dyn_cast<RegisterTypeVector>(m_element_type))
95 return vector->IsByteSizeCompatible(element_byte_size);
96 if (const auto *union_type =
97 llvm::dyn_cast<RegisterTypeUnion>(m_element_type))
98 return union_type->IsByteSizeCompatible(element_byte_size);
99 return llvm::isa<RegisterTypeBuiltin>(m_element_type);
100}
101
103 LLDB_LOG(log, "ID: \"{0}\" Element type: \"{1}\" Count: {2}", GetID().c_str(),
104 m_element_type->GetID().c_str(), m_count);
105}
106
108 const RegisterType *) const {
109 strm.Indent();
110 strm << "<vector id=\"";
112 strm << "\" type=\"";
114 strm.Printf("\" count=\"%" PRIu32 "\"/>\n", m_count);
115}
116
117RegisterTypeUnion::Field::Field(std::string name, const RegisterType *type)
118 : m_name(std::move(name)), m_type(type) {
119 assert(!m_name.empty() && "Union field name cannot be empty");
120 assert(m_type && "Union field type cannot be null");
121}
122
123RegisterTypeUnion::RegisterTypeUnion(std::string id, std::vector<Field> fields)
125 m_fields(std::move(fields)) {
126 assert(!m_fields.empty() && "Union must have at least one field");
127
128 std::vector<const RegisterType *> dependencies;
129 dependencies.reserve(m_fields.size());
130 for (const Field &field : m_fields)
131 dependencies.push_back(field.GetType());
132 SetDependencies(std::move(dependencies));
133}
134
135std::optional<uint64_t> RegisterTypeUnion::GetByteSize() const {
136 uint64_t byte_size = 0;
137 for (const Field &field : m_fields) {
138 std::optional<uint64_t> field_size = field.GetType()->GetByteSize();
139 if (!field_size)
140 return std::nullopt;
141 byte_size = std::max(byte_size, *field_size);
142 }
143 return byte_size;
144}
145
146bool RegisterTypeUnion::IsByteSizeCompatible(uint64_t byte_size) const {
147 if (!byte_size)
148 return false;
149
150 // Unlike a vector, a union describes alternative views that only need to
151 // fit within the containing register.
152 if (std::optional<uint64_t> fixed_size = GetByteSize())
153 return *fixed_size <= byte_size;
154
155 // Target-dependent fields are validated when their CompilerTypes are built.
156 // Fixed-size fields must still fit in the register that contains the union.
157 return std::all_of(
158 m_fields.begin(), m_fields.end(), [byte_size](const Field &field) {
159 std::optional<uint64_t> field_size = field.GetType()->GetByteSize();
160 if (field_size)
161 return *field_size <= byte_size;
162 if (const auto *union_type =
163 llvm::dyn_cast<RegisterTypeUnion>(field.GetType()))
164 return union_type->IsByteSizeCompatible(byte_size);
165 return true;
166 });
167}
168
170 std::vector<llvm::StringRef> field_names;
171 field_names.reserve(m_fields.size());
172 for (const Field &field : m_fields)
173 field_names.push_back(field.GetName());
174 LLDB_LOG(log, "ID: \"{0}\" Fields: {1} [{2}]", GetID(), m_fields.size(),
175 llvm::join(field_names, ", "));
176}
177
179 strm.Indent();
180 strm << "<union id=\"";
182 strm << "\">\n";
183 strm.IndentMore();
184 for (const Field &field : m_fields) {
185 strm.Indent();
186 strm << "<field name=\"";
187 PrintXMLAttributeValue(strm, field.GetName());
188 strm << "\" type=\"";
189 PrintXMLAttributeValue(strm, field.GetType()->GetID());
190 strm << "\"/>\n";
191 }
192 strm.IndentLess();
193 strm.Indent("</union>\n");
194}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
static std::atomic< uint64_t > g_next_register_type_uid
void ToXMLElement(Stream &strm, const RegisterType *user=nullptr) const override
Output the register type as an XML element.
RegisterTypeBuiltin(std::string id, lldb::Encoding encoding, lldb::Format format, std::optional< uint64_t > byte_size)
A missing byte size means the size depends on the target.
const lldb::Encoding m_encoding
const std::optional< uint64_t > m_byte_size
void ToXML(Stream &strm, std::unordered_set< std::string > &previously_emitted, const RegisterType *user=nullptr) const override
Output XML that describes this type, to be inserted into a target XML file.
RegisterTypeComposite(RegisterTypeKind kind, std::string id)
Field(std::string name, const RegisterType *type)
void ToXMLElement(Stream &strm, const RegisterType *user=nullptr) const override
Output the register type as an XML element.
std::optional< uint64_t > GetByteSize() const override
Return this type's fixed size in bytes, if it has one.
bool IsByteSizeCompatible(uint64_t byte_size) const
const std::vector< Field > m_fields
RegisterTypeUnion(std::string id, std::vector< Field > fields)
RegisterTypeVector(std::string id, const RegisterType *element_type, uint32_t count)
bool IsByteSizeCompatible(uint64_t byte_size) const
void ToXMLElement(Stream &strm, const RegisterType *user=nullptr) const override
Output the register type as an XML element.
std::optional< uint64_t > GetByteSize() const override
Return this type's fixed size in bytes, if it has one.
const RegisterType * m_element_type
RegisterType(RegisterTypeKind kind, std::string id)
virtual void ToXMLElement(Stream &strm, const RegisterType *user=nullptr) const =0
Output the register type as an XML element.
const std::string & GetID() const
const RegisterTypeKind m_kind
std::vector< const RegisterType * > m_dependencies
void SetDependencies(std::vector< const RegisterType * > dependencies)
const std::string m_id
static void PrintXMLAttributeValue(Stream &strm, llvm::StringRef value)
Print a string escaped for use as an XML attribute value.
virtual void ToXML(Stream &strm, std::unordered_set< std::string > &previously_emitted, const RegisterType *user=nullptr) const
Output XML that describes this type, to be inserted into a target XML file.
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition Stream.cpp:157
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition Stream.cpp:204
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition Stream.cpp:201
A class that represents a running process on the host machine.
Format
Display format definitions.
Encoding
Register encoding definitions.