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