13#include "llvm/ADT/StringExtras.h"
22 : m_name(std::move(name)), m_start(start), m_end(end),
23 m_enum_type(nullptr) {
24 assert(
m_start <=
m_end &&
"Start bit must be <= end bit.");
28 : m_name(std::move(name)), m_start(bit_position), m_end(bit_position),
29 m_enum_type(nullptr) {}
33 : m_name(std::move(name)), m_start(start), m_end(end),
34 m_enum_type(enum_type) {
44 assert(enumerator.m_value <= max_value &&
45 "Enumerator value exceeds maximum value for this field");
51 LLDB_LOG(log,
" Name: \"{0}\" Start: {1} End: {2}", m_name.c_str(), m_start,
56 unsigned overlap_start = std::max(GetStart(), other.
GetStart());
57 unsigned overlap_end = std::min(GetEnd(), other.
GetEnd());
58 return overlap_start <= overlap_end;
63 "Cannot get padding distance for overlapping fields.");
64 assert((other < (*
this)) &&
"Expected fields in MSB to LSB order.");
70 unsigned lhs_start = GetStart();
75 rhs_end = GetStart() + GetSizeInBits() - 1;
78 return lhs_start - rhs_end - 1;
82 return end - start + 1;
86 return GetSizeInBits(m_start, m_end);
90 uint64_t max = std::numeric_limits<uint64_t>::max();
91 unsigned bits = GetSizeInBits(start, end);
95 assert(bits <= 64 && "Cannot handle field with size > 64
bits");
97 max = ((uint64_t)1 << bits) - 1;
102uint64_t RegisterFlags::Field::GetMaxValue() const {
103 return GetMaxValue(m_start, m_end);
106uint64_t RegisterFlags::Field::GetMask() const {
107 return GetMaxValue() << m_start;
110void RegisterFlags::SetFields(const std::vector<Field> &fields) {
111 // We expect that these are unsorted but do not overlap.
112 // They could fill the register but may have gaps.
113 std::vector<Field> provided_fields = fields;
116 m_fields.reserve(provided_fields.size());
118 // ProcessGDBRemote should have sorted these in descending order already.
119 assert(std::is_sorted(provided_fields.rbegin(), provided_fields.rend()));
121 // Build a new list of fields that includes anonymous (empty name) fields
122 // wherever there is a gap. This will simplify processing later.
123 std::optional<Field> previous_field;
124 unsigned register_msb = (m_size * 8) - 1;
125 for (auto field : provided_fields) {
126 if (previous_field) {
127 unsigned padding = previous_field->PaddingDistance(field);
129 // -1 to end just before the previous field.
130 unsigned end = previous_field->GetStart() - 1;
131 // +1 because if you want to pad 1 bit you want to start and end
133 m_fields.push_back(Field("", field.GetEnd() + 1, end));
136 // This is the first field. Check that it starts at the register's MSB.
137 if (field.GetEnd() != register_msb)
138 m_fields.push_back(Field("", field.GetEnd() + 1, register_msb));
140 m_fields.push_back(field);
141 previous_field = field;
144 // The last field may not extend all the way to bit 0.
145 if (previous_field && previous_field->GetStart() != 0)
146 m_fields.push_back(Field("", 0, previous_field->GetStart() - 1));
149RegisterFlags::RegisterFlags(std::string id, unsigned size,
150 const std::vector<Field> &fields)
151 : m_id(std::move(id)), m_size(size) {
155void RegisterFlags::DumpToLog(Log *log) const {
156 LLDB_LOG(log, "ID: \
"{0}\" Size: {1}",
m_id.c_str(),
m_size);
158 field.DumpToLog(log);
162 unsigned column_width) {
163 unsigned pad = column_width - content.
GetString().size();
167 pad_l = std::string(pad / 2,
' ');
168 pad_r = std::string((pad / 2) + (pad % 2),
' ');
177static void EmitTable(std::string &out, std::array<std::string, 3> &table) {
179 for (std::string &line : table)
182 out += std::accumulate(table.begin() + 1, table.end(), table.front(),
183 [](std::string lhs,
const auto &rhs) {
184 return std::move(lhs) +
"\n" + rhs;
191 std::array<std::string, 3> lines;
192 uint32_t current_width = 0;
196 if (field.GetEnd() == field.GetStart())
197 position.
Printf(
" %d ", field.GetEnd());
199 position.
Printf(
" %d-%d ", field.GetEnd(), field.GetStart());
202 name.
Printf(
" %s ", field.GetName().c_str());
204 unsigned column_width = position.
GetString().size();
205 unsigned name_width = name.
GetString().size();
206 if (name_width > column_width)
207 column_width = name_width;
214 if (current_width && ((current_width + column_width + 1) >= max_width)) {
219 for (std::string &line : lines)
225 lines[0] += aligned_position.
GetString();
227 grid <<
'|' << std::string(column_width,
'-');
233 current_width += column_width + 1;
247 size_t current_width, uint32_t max_width,
249 for (
auto it = enumerators.cbegin(); it != enumerators.cend(); ++it) {
252 if (current_width != indent)
253 enumerator_strm <<
' ';
255 enumerator_strm.
Printf(
"%" PRIu64
" = %s", it->m_value, it->m_name.c_str());
258 if (std::next(it) != enumerators.cend())
259 enumerator_strm <<
",";
261 llvm::StringRef enumerator_string = enumerator_strm.
GetString();
274 if ((current_width + enumerator_string.size() > max_width) &&
275 current_width != indent) {
276 current_width = indent;
277 strm <<
'\n' << std::string(indent,
' ');
280 enumerator_string = enumerator_string.drop_front();
283 current_width += enumerator_string.size();
284 strm << enumerator_string;
290 bool printed_enumerators_once =
false;
292 for (
const auto &field :
m_fields) {
293 const FieldEnum *enum_type = field.GetEnum();
298 if (enumerators.empty())
302 if (printed_enumerators_once)
305 printed_enumerators_once =
true;
307 std::string name_string = field.GetName() +
": ";
308 size_t indent = name_string.size();
309 size_t current_width = indent;
321 if (
const FieldEnum *enum_type = field.GetEnum()) {
322 const std::string &
id = enum_type->GetID();
323 if (!seen.contains(
id)) {
324 enum_type->ToXML(strm,
GetSize());
339 strm <<
"<enum id=\"" <<
GetID() <<
"\" ";
342 strm.
Printf(
"size=\"%d\"", size);
345 if (enumerators.empty()) {
352 for (
const auto &enumerator : enumerators) {
354 enumerator.ToXML(strm);
362 std::string escaped_name;
363 llvm::raw_string_ostream escape_strm(escaped_name);
364 llvm::printHTMLEscaped(m_name, escape_strm);
365 strm.
Printf(
"<evalue name=\"%s\" value=\"%" PRIu64
"\"/>",
366 escaped_name.c_str(), m_value);
370 LLDB_LOG(log,
" Name: \"{0}\" Value: {1}", m_name.c_str(), m_value);
375 for (
const auto &enumerator : GetEnumerators())
376 enumerator.DumpToLog(log);
385 strm <<
"<flags id=\"" <<
GetID() <<
"\" ";
390 if (field.GetName().empty())
399 strm.
Indent(
"</flags>\n");
408 strm <<
"<field name=\"";
410 std::string escaped_name;
411 llvm::raw_string_ostream escape_strm(escaped_name);
412 llvm::printHTMLEscaped(
GetName(), escape_strm);
413 strm << escaped_name <<
"\" ";
415 strm.
Printf(
"start=\"%d\" end=\"%d\"", GetStart(), GetEnd());
417 if (
const FieldEnum *enum_type = GetEnum())
418 strm <<
" type=\"" << enum_type->GetID() <<
"\"";
424 :
m_id(
id), m_enumerators(enumerators) {
427 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 void DumpEnumerators(StreamString &strm, size_t indent, size_t current_width, uint32_t max_width, const FieldEnum::Enumerators &enumerators)
static StreamString FormatCell(const StreamString &content, unsigned column_width)
static void EmitTable(std::string &out, std::array< std::string, 3 > &table)
static llvm::StringRef GetName(XcodeSDK::Type type)
Enumerators m_enumerators
FieldEnum(std::string id, const Enumerators &enumerators)
std::vector< Enumerator > Enumerators
const Enumerators & GetEnumerators() const
void DumpToLog(Log *log) const
void ToXML(Stream &strm, unsigned size) const
bool Overlaps(const Field &other) const
const FieldEnum * m_enum_type
unsigned PaddingDistance(const Field &other) const
Return the number of bits between this field and the other, that are not covered by either field.
Field(std::string name, unsigned start, unsigned end)
Where start is the least significant bit and end is the most significant bit.
uint64_t GetMaxValue() const
The maximum unsigned value that could be contained in this field.
unsigned GetStart() const
void DumpToLog(Log *log) const
unsigned GetSizeInBits() const
Get size of the field in bits. Will always be at least 1.
unsigned m_start
Start/end bit positions.
void ToXML(Stream &strm) const
Output XML that describes this field, to be inserted into a target XML file.
std::vector< Field > m_fields
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...
const unsigned m_size
Size in bytes.
void EnumsToXML(Stream &strm, llvm::StringSet<> &seen) const
Enum types must be defined before use, and GDBRemoteCommunicationServerLLGS view of the register type...
const std::string & GetID() const
void ToXML(Stream &strm) const
Output XML that describes this set of flags.
std::string AsTable(uint32_t max_width) const
Produce a text table showing the layout of all the fields.
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 ToXML(Stream &strm) const
void DumpToLog(Log *log) const