13#include "llvm/ADT/MapVector.h"
14#include "llvm/ADT/StringExtras.h"
15#include "llvm/Support/Casting.h"
27 assert(
m_start <=
m_end &&
"Start bit must be <= end bit.");
45 for (
const auto &enumerator :
m_enum_type->GetEnumerators()) {
47 assert(enumerator.m_value <= max_value &&
48 "Enumerator value exceeds maximum value for this field");
60 unsigned overlap_end = std::min(
GetEnd(), other.
GetEnd());
61 return overlap_start <= overlap_end;
66 "Cannot get padding distance for overlapping fields.");
67 assert((other < (*
this)) &&
"Expected fields in MSB to LSB order.");
81 return lhs_start - rhs_end - 1;
85 return end - start + 1;
93 uint64_t max = std::numeric_limits<uint64_t>::max();
100 max = ((uint64_t)1 << bits) - 1;
105uint64_t RegisterTypeFlags::Field::GetMaxValue() const {
106 return GetMaxValue(m_start, m_end);
109uint64_t RegisterTypeFlags::Field::GetMask() const {
110 return GetMaxValue() << m_start;
113void RegisterTypeFlags::SetFields(const std::vector<Field> &fields) {
114 // We expect that these are unsorted but do not overlap.
115 // They could fill the register but may have gaps.
116 std::vector<Field> provided_fields = fields;
119 m_fields.reserve(provided_fields.size());
121 // ProcessGDBRemote should have sorted these in descending order already.
122 assert(std::is_sorted(provided_fields.rbegin(), provided_fields.rend()));
124 // Build a new list of fields that includes anonymous (empty name) fields
125 // wherever there is a gap. This will simplify processing later.
126 std::optional<Field> previous_field;
127 unsigned register_msb = (m_size * 8) - 1;
128 for (auto field : provided_fields) {
129 if (previous_field) {
130 unsigned padding = previous_field->PaddingDistance(field);
132 // -1 to end just before the previous field.
133 unsigned end = previous_field->GetStart() - 1;
134 // +1 because if you want to pad 1 bit you want to start and end
136 m_fields.push_back(Field("", field.GetEnd() + 1, end));
139 // This is the first field. Check that it starts at the register's MSB.
140 if (field.GetEnd() != register_msb)
141 m_fields.push_back(Field("", field.GetEnd() + 1, register_msb));
143 m_fields.push_back(field);
144 previous_field = field;
147 // The last field may not extend all the way to bit 0.
148 if (previous_field && previous_field->GetStart() != 0)
149 m_fields.push_back(Field("", 0, previous_field->GetStart() - 1));
151 std::vector<const RegisterType *> dependencies;
152 for (const auto &field : m_fields)
153 if (auto enum_type = field.GetEnum())
154 dependencies.push_back(dynamic_cast<const RegisterType *>(enum_type));
155 SetDependencies(std::move(dependencies));
158RegisterTypeFlags::RegisterTypeFlags(std::string id, unsigned size,
159 const std::vector<Field> &fields)
160 : RegisterType(RegisterType::eRegisterTypeKindFlags, id), m_size(size) {
164void RegisterTypeFlags::DumpToLog(Log *log) const {
165 LLDB_LOG(log, "ID: \
"{0}\" Size: {1}",
GetID().c_str(),
m_size);
167 field.DumpToLog(log);
171 unsigned column_width) {
172 unsigned pad = column_width - content.
GetString().size();
176 pad_l = std::string(pad / 2,
' ');
177 pad_r = std::string((pad / 2) + (pad % 2),
' ');
186static void EmitTable(std::string &out, std::array<std::string, 3> &table) {
188 for (std::string &line : table)
191 out += std::accumulate(table.begin() + 1, table.end(), table.front(),
192 [](std::string lhs,
const auto &rhs) {
193 return std::move(lhs) +
"\n" + rhs;
200 std::array<std::string, 3> lines;
201 uint32_t current_width = 0;
205 if (field.GetEnd() == field.GetStart())
206 position.
Printf(
" %d ", field.GetEnd());
208 position.
Printf(
" %d-%d ", field.GetEnd(), field.GetStart());
211 name.
Printf(
" %s ", field.GetName().c_str());
213 unsigned column_width = position.
GetString().size();
214 unsigned name_width = name.
GetString().size();
215 if (name_width > column_width)
216 column_width = name_width;
223 if (current_width && ((current_width + column_width + 1) >= max_width)) {
228 for (std::string &line : lines)
234 lines[0] += aligned_position.
GetString();
236 grid <<
'|' << std::string(column_width,
'-');
242 current_width += column_width + 1;
256 size_t current_width, uint32_t max_width,
258 for (
auto it = enumerators.cbegin(); it != enumerators.cend(); ++it) {
261 if (current_width != indent)
262 enumerator_strm <<
' ';
264 enumerator_strm.
Printf(
"%" PRIu64
" = %s", it->m_value, it->m_name.c_str());
267 if (std::next(it) != enumerators.cend())
268 enumerator_strm <<
",";
270 llvm::StringRef enumerator_string = enumerator_strm.
GetString();
283 if ((current_width + enumerator_string.size() > max_width) &&
284 current_width != indent) {
285 current_width = indent;
286 strm <<
'\n' << std::string(indent,
' ');
289 enumerator_string = enumerator_string.drop_front();
292 current_width += enumerator_string.size();
293 strm << enumerator_string;
300 llvm::MapVector<const RegisterTypeEnum *, std::vector<std::string>> enum_uses;
303 enum_uses[enum_type].push_back(field.GetName());
306 bool printed_one_enumerator =
false;
308 for (
const auto &[enum_type, field_names] : enum_uses) {
310 if (printed_one_enumerator)
313 printed_one_enumerator =
true;
315 std::string name_string = llvm::join(field_names,
", ") +
": ";
316 size_t indent = name_string.size();
317 size_t current_width = indent;
322 enum_type->GetEnumerators());
338 strm <<
"<enum id=\"" <<
GetID() <<
"\"";
343 llvm::dyn_cast_if_present<RegisterTypeFlags>(user)) {
346 strm.
Printf(
" size=\"%d\"", flags_type->GetSize());
350 if (enumerators.empty()) {
357 for (
const auto &enumerator : enumerators) {
359 enumerator.ToXMLElement(strm);
367 std::string escaped_name;
368 llvm::raw_string_ostream escape_strm(escaped_name);
369 llvm::printHTMLEscaped(
m_name, escape_strm);
370 strm.
Printf(
"<evalue name=\"%s\" value=\"%" PRIu64
"\"/>",
371 escaped_name.c_str(),
m_value);
381 enumerator.DumpToLog(log);
392 strm <<
"<flags id=\"" <<
GetID() <<
"\" ";
397 if (field.GetName().empty())
402 field.ToXMLElement(strm);
406 strm.
Indent(
"</flags>\n");
415 strm <<
"<field name=\"";
417 std::string escaped_name;
418 llvm::raw_string_ostream escape_strm(escaped_name);
419 llvm::printHTMLEscaped(
GetName(), escape_strm);
420 strm << escaped_name <<
"\" ";
425 strm <<
" type=\"" << enum_type->GetID() <<
"\"";
436 assert(enumerator.m_name.size() &&
"Enumerator name cannot be empty");
static bool Overlaps(const Entry *region_one, const Entry *region_two)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
static StreamString FormatCell(const StreamString &content, unsigned column_width)
static void DumpEnumerators(StreamString &strm, size_t indent, size_t current_width, uint32_t max_width, const RegisterTypeEnum::Enumerators &enumerators)
static void EmitTable(std::string &out, std::array< std::string, 3 > &table)
static llvm::StringRef GetName(XcodeSDK::Type type)
std::vector< Enumerator > Enumerators
const Enumerators & GetEnumerators() const
RegisterTypeEnum(std::string id, const Enumerators &enumerators)
virtual void ToXMLElement(Stream &strm, const RegisterType *user=nullptr) const override
Output the register type as an XML element.
Enumerators m_enumerators
void DumpToLog(Log *log) const
unsigned PaddingDistance(const Field &other) const
Return the number of bits between this field and the other, that are not covered by either field.
const RegisterTypeEnum * m_enum_type
unsigned GetStart() const
void DumpToLog(Log *log) const
unsigned m_start
Start/end bit positions.
bool Overlaps(const Field &other) const
unsigned GetSizeInBits() const
Get size of the field in bits. Will always be at least 1.
uint64_t GetMaxValue() const
The maximum unsigned value that could be contained in this field.
void ToXMLElement(Stream &strm) const
Field(std::string name, unsigned start, unsigned end)
Where start is the least significant bit and end is the most significant bit.
const RegisterTypeEnum * GetEnum() const
std::string DumpEnums(uint32_t max_width) const
Make a string where each line contains the name of a field that has enum values, and lists what those...
std::vector< Field > m_fields
std::string AsTable(uint32_t max_width) const
Produce a text table showing the layout of all the fields.
virtual void ToXMLElement(Stream &strm, const RegisterType *user=nullptr) const override
Output the register type as an XML element.
const unsigned m_size
Size in bytes.
const std::string & GetID() const
RegisterType(RegisterTypeKind kind, std::string id)
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
void IndentMore(unsigned amount=2)
Increment the current indentation level.
#define UNUSED_IF_ASSERT_DISABLED(x)
A class that represents a running process on the host machine.
static uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
void ToXMLElement(Stream &strm) const
void DumpToLog(Log *log) const