13#include "llvm/ADT/StringExtras.h" 
   24  assert(
m_start <= 
m_end && 
"Start bit must be <= end bit.");
 
 
   42    for (
const auto &enumerator : 
m_enum_type->GetEnumerators()) {
 
   44      assert(enumerator.m_value <= max_value &&
 
   45             "Enumerator value exceeds maximum value for this field");
 
 
   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.");
 
   78  return lhs_start - rhs_end - 1;
 
 
   82  return end - start + 1;
 
 
   90  uint64_t max = std::numeric_limits<uint64_t>::max();
 
   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);
 
 
  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 << 
"\" ";
 
  418    strm << 
" type=\"" << enum_type->GetID() << 
"\"";
 
 
  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.
const FieldEnum * GetEnum() const
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