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::unordered_set<std::string> &previously_emitted,
33 const RegisterType *user) const {
34 // XML type references use IDs, so definitions must also be unique by ID.
35 if (!previously_emitted.insert(GetID()).second)
36 return;
37
38 // Emit this type's dependencies first.
39 for (auto dep : m_dependencies)
40 dep->ToXML(strm, previously_emitted, this);
41
42 // Finally emit this type.
43 ToXMLElement(strm, user);
44}
45
46void RegisterType::PrintXMLAttributeValue(Stream &strm, llvm::StringRef value) {
47 std::string escaped;
48 llvm::raw_string_ostream escape_strm(escaped);
49 llvm::printHTMLEscaped(value, escape_strm);
50 strm << escaped;
51}
52
54 lldb::Encoding encoding,
55 lldb::Format format,
56 std::optional<uint64_t> byte_size)
57 : RegisterType(eRegisterTypeKindBuiltin, std::move(id)),
58 m_encoding(encoding), m_format(format), m_byte_size(byte_size) {}
59
60void RegisterTypeBuiltin::ToXML(Stream &, std::unordered_set<std::string> &,
61 const RegisterType *) const {}
62
64
66 const RegisterType *element_type,
67 uint32_t count)
68 : RegisterType(eRegisterTypeKindVector, std::move(id)),
69 m_element_type(element_type), m_count(count) {
70 assert(m_element_type && "Vector element type cannot be null");
71 assert(m_count && "Vector element count cannot be zero");
73}
74
75std::optional<uint64_t> RegisterTypeVector::GetByteSize() const {
76 std::optional<uint64_t> element_size = m_element_type->GetByteSize();
77 if (!element_size ||
78 *element_size > std::numeric_limits<uint64_t>::max() / m_count)
79 return std::nullopt;
80 return *element_size * m_count;
81}
82
83bool RegisterTypeVector::IsByteSizeCompatible(uint64_t byte_size) const {
84 if (!byte_size || byte_size % m_count)
85 return false;
86
87 uint64_t element_byte_size = byte_size / m_count;
88 if (std::optional<uint64_t> fixed_size = m_element_type->GetByteSize())
89 return *fixed_size == element_byte_size;
90 if (const auto *vector = llvm::dyn_cast<RegisterTypeVector>(m_element_type))
91 return vector->IsByteSizeCompatible(element_byte_size);
92 if (const auto *union_type =
93 llvm::dyn_cast<RegisterTypeUnion>(m_element_type))
94 return union_type->IsByteSizeCompatible(element_byte_size);
95 return llvm::isa<RegisterTypeBuiltin>(m_element_type);
96}
97
99 LLDB_LOG(log, "ID: \"{0}\" Element type: \"{1}\" Count: {2}", GetID().c_str(),
100 m_element_type->GetID().c_str(), m_count);
101}
102
104 const RegisterType *) const {
105 strm.Indent();
106 strm << "<vector id=\"";
108 strm << "\" type=\"";
110 strm.Printf("\" count=\"%" PRIu32 "\"/>\n", m_count);
111}
112
113RegisterTypeUnion::Field::Field(std::string name, const RegisterType *type)
114 : m_name(std::move(name)), m_type(type) {
115 assert(!m_name.empty() && "Union field name cannot be empty");
116 assert(m_type && "Union field type cannot be null");
117}
118
119RegisterTypeUnion::RegisterTypeUnion(std::string id, std::vector<Field> fields)
120 : RegisterType(eRegisterTypeKindUnion, std::move(id)),
121 m_fields(std::move(fields)) {
122 assert(!m_fields.empty() && "Union must have at least one field");
123
124 std::vector<const RegisterType *> dependencies;
125 dependencies.reserve(m_fields.size());
126 for (const Field &field : m_fields)
127 dependencies.push_back(field.GetType());
128 SetDependencies(std::move(dependencies));
129}
130
131std::optional<uint64_t> RegisterTypeUnion::GetByteSize() const {
132 uint64_t byte_size = 0;
133 for (const Field &field : m_fields) {
134 std::optional<uint64_t> field_size = field.GetType()->GetByteSize();
135 if (!field_size)
136 return std::nullopt;
137 byte_size = std::max(byte_size, *field_size);
138 }
139 return byte_size;
140}
141
142bool RegisterTypeUnion::IsByteSizeCompatible(uint64_t byte_size) const {
143 if (!byte_size)
144 return false;
145
146 // Unlike a vector, a union describes alternative views that only need to
147 // fit within the containing register.
148 if (std::optional<uint64_t> fixed_size = GetByteSize())
149 return *fixed_size <= byte_size;
150
151 // Target-dependent fields are validated when their CompilerTypes are built.
152 // Fixed-size fields must still fit in the register that contains the union.
153 return std::all_of(
154 m_fields.begin(), m_fields.end(), [byte_size](const Field &field) {
155 std::optional<uint64_t> field_size = field.GetType()->GetByteSize();
156 if (field_size)
157 return *field_size <= byte_size;
158 if (const auto *union_type =
159 llvm::dyn_cast<RegisterTypeUnion>(field.GetType()))
160 return union_type->IsByteSizeCompatible(byte_size);
161 return true;
162 });
163}
164
166 std::vector<llvm::StringRef> field_names;
167 field_names.reserve(m_fields.size());
168 for (const Field &field : m_fields)
169 field_names.push_back(field.GetName());
170 LLDB_LOG(log, "ID: \"{0}\" Fields: {1} [{2}]", GetID(), m_fields.size(),
171 llvm::join(field_names, ", "));
172}
173
175 strm.Indent();
176 strm << "<union id=\"";
178 strm << "\">\n";
179 strm.IndentMore();
180 for (const Field &field : m_fields) {
181 strm.Indent();
182 strm << "<field name=\"";
183 PrintXMLAttributeValue(strm, field.GetName());
184 strm << "\" type=\"";
185 PrintXMLAttributeValue(strm, field.GetType()->GetID());
186 strm << "\"/>\n";
187 }
188 strm.IndentLess();
189 strm.Indent("</union>\n");
190}
#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.
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.