xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/DumpRegisterInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===-- DumpRegisterInfo.cpp ----------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "lldb/Core/DumpRegisterInfo.h"
1006c3fb27SDimitry Andric #include "lldb/Target/RegisterContext.h"
1106c3fb27SDimitry Andric #include "lldb/Target/RegisterFlags.h"
1206c3fb27SDimitry Andric #include "lldb/Utility/Stream.h"
1306c3fb27SDimitry Andric 
1406c3fb27SDimitry Andric using namespace lldb;
1506c3fb27SDimitry Andric using namespace lldb_private;
1606c3fb27SDimitry Andric 
1706c3fb27SDimitry Andric using SetInfo = std::pair<const char *, uint32_t>;
1806c3fb27SDimitry Andric 
1906c3fb27SDimitry Andric void lldb_private::DumpRegisterInfo(Stream &strm, RegisterContext &ctx,
2006c3fb27SDimitry Andric                                     const RegisterInfo &info,
2106c3fb27SDimitry Andric                                     uint32_t terminal_width) {
2206c3fb27SDimitry Andric   std::vector<const char *> invalidates;
2306c3fb27SDimitry Andric   if (info.invalidate_regs) {
2406c3fb27SDimitry Andric     for (uint32_t *inv_regs = info.invalidate_regs;
2506c3fb27SDimitry Andric          *inv_regs != LLDB_INVALID_REGNUM; ++inv_regs) {
2606c3fb27SDimitry Andric       const RegisterInfo *inv_info =
2706c3fb27SDimitry Andric           ctx.GetRegisterInfo(lldb::eRegisterKindLLDB, *inv_regs);
2806c3fb27SDimitry Andric       assert(
2906c3fb27SDimitry Andric           inv_info &&
3006c3fb27SDimitry Andric           "Register invalidate list refers to a register that does not exist.");
3106c3fb27SDimitry Andric       invalidates.push_back(inv_info->name);
3206c3fb27SDimitry Andric     }
3306c3fb27SDimitry Andric   }
3406c3fb27SDimitry Andric 
3506c3fb27SDimitry Andric   // We include the index here so that you can use it with "register read -s".
3606c3fb27SDimitry Andric   std::vector<SetInfo> in_sets;
3706c3fb27SDimitry Andric   for (uint32_t set_idx = 0; set_idx < ctx.GetRegisterSetCount(); ++set_idx) {
3806c3fb27SDimitry Andric     const RegisterSet *set = ctx.GetRegisterSet(set_idx);
3906c3fb27SDimitry Andric     assert(set && "Register set should be valid.");
4006c3fb27SDimitry Andric     for (uint32_t reg_idx = 0; reg_idx < set->num_registers; ++reg_idx) {
4106c3fb27SDimitry Andric       const RegisterInfo *set_reg_info =
4206c3fb27SDimitry Andric           ctx.GetRegisterInfoAtIndex(set->registers[reg_idx]);
4306c3fb27SDimitry Andric       assert(set_reg_info && "Register info should be valid.");
4406c3fb27SDimitry Andric 
4506c3fb27SDimitry Andric       if (set_reg_info == &info) {
4606c3fb27SDimitry Andric         in_sets.push_back({set->name, set_idx});
4706c3fb27SDimitry Andric         break;
4806c3fb27SDimitry Andric       }
4906c3fb27SDimitry Andric     }
5006c3fb27SDimitry Andric   }
5106c3fb27SDimitry Andric 
5206c3fb27SDimitry Andric   std::vector<const char *> read_from;
5306c3fb27SDimitry Andric   if (info.value_regs) {
5406c3fb27SDimitry Andric     for (uint32_t *read_regs = info.value_regs;
5506c3fb27SDimitry Andric          *read_regs != LLDB_INVALID_REGNUM; ++read_regs) {
5606c3fb27SDimitry Andric       const RegisterInfo *read_info =
5706c3fb27SDimitry Andric           ctx.GetRegisterInfo(lldb::eRegisterKindLLDB, *read_regs);
5806c3fb27SDimitry Andric       assert(read_info && "Register value registers list refers to a register "
5906c3fb27SDimitry Andric                           "that does not exist.");
6006c3fb27SDimitry Andric       read_from.push_back(read_info->name);
6106c3fb27SDimitry Andric     }
6206c3fb27SDimitry Andric   }
6306c3fb27SDimitry Andric 
6406c3fb27SDimitry Andric   DoDumpRegisterInfo(strm, info.name, info.alt_name, info.byte_size,
6506c3fb27SDimitry Andric                      invalidates, read_from, in_sets, info.flags_type,
6606c3fb27SDimitry Andric                      terminal_width);
6706c3fb27SDimitry Andric }
6806c3fb27SDimitry Andric 
6906c3fb27SDimitry Andric template <typename ElementType>
7006c3fb27SDimitry Andric static void DumpList(Stream &strm, const char *title,
7106c3fb27SDimitry Andric                      const std::vector<ElementType> &list,
7206c3fb27SDimitry Andric                      std::function<void(Stream &, ElementType)> emitter) {
7306c3fb27SDimitry Andric   if (list.empty())
7406c3fb27SDimitry Andric     return;
7506c3fb27SDimitry Andric 
7606c3fb27SDimitry Andric   strm.EOL();
7706c3fb27SDimitry Andric   strm << title;
7806c3fb27SDimitry Andric   bool first = true;
7906c3fb27SDimitry Andric   for (ElementType elem : list) {
8006c3fb27SDimitry Andric     if (!first)
8106c3fb27SDimitry Andric       strm << ", ";
8206c3fb27SDimitry Andric     first = false;
8306c3fb27SDimitry Andric     emitter(strm, elem);
8406c3fb27SDimitry Andric   }
8506c3fb27SDimitry Andric }
8606c3fb27SDimitry Andric 
8706c3fb27SDimitry Andric void lldb_private::DoDumpRegisterInfo(
8806c3fb27SDimitry Andric     Stream &strm, const char *name, const char *alt_name, uint32_t byte_size,
8906c3fb27SDimitry Andric     const std::vector<const char *> &invalidates,
9006c3fb27SDimitry Andric     const std::vector<const char *> &read_from,
9106c3fb27SDimitry Andric     const std::vector<SetInfo> &in_sets, const RegisterFlags *flags_type,
9206c3fb27SDimitry Andric     uint32_t terminal_width) {
9306c3fb27SDimitry Andric   strm << "       Name: " << name;
9406c3fb27SDimitry Andric   if (alt_name)
9506c3fb27SDimitry Andric     strm << " (" << alt_name << ")";
9606c3fb27SDimitry Andric   strm.EOL();
9706c3fb27SDimitry Andric 
9806c3fb27SDimitry Andric   // Size in bits may seem obvious for the usual 32 or 64 bit registers.
9906c3fb27SDimitry Andric   // When we get to vector registers, then scalable vector registers, it is very
10006c3fb27SDimitry Andric   // useful to know without the user doing extra work.
10106c3fb27SDimitry Andric   strm.Printf("       Size: %d bytes (%d bits)", byte_size, byte_size * 8);
10206c3fb27SDimitry Andric 
10306c3fb27SDimitry Andric   std::function<void(Stream &, const char *)> emit_str =
10406c3fb27SDimitry Andric       [](Stream &strm, const char *s) { strm << s; };
10506c3fb27SDimitry Andric   DumpList(strm, "Invalidates: ", invalidates, emit_str);
10606c3fb27SDimitry Andric   DumpList(strm, "  Read from: ", read_from, emit_str);
10706c3fb27SDimitry Andric 
10806c3fb27SDimitry Andric   std::function<void(Stream &, SetInfo)> emit_set = [](Stream &strm,
10906c3fb27SDimitry Andric                                                        SetInfo info) {
11006c3fb27SDimitry Andric     strm.Printf("%s (index %d)", info.first, info.second);
11106c3fb27SDimitry Andric   };
11206c3fb27SDimitry Andric   DumpList(strm, "    In sets: ", in_sets, emit_set);
11306c3fb27SDimitry Andric 
114*0fca6ea1SDimitry Andric   if (flags_type) {
11506c3fb27SDimitry Andric     strm.Printf("\n\n%s", flags_type->AsTable(terminal_width).c_str());
116*0fca6ea1SDimitry Andric 
117*0fca6ea1SDimitry Andric     std::string enumerators = flags_type->DumpEnums(terminal_width);
118*0fca6ea1SDimitry Andric     if (enumerators.size())
119*0fca6ea1SDimitry Andric       strm << "\n\n" << enumerators;
120*0fca6ea1SDimitry Andric   }
12106c3fb27SDimitry Andric }
122