1214054f7SMichał Górny //===-- DynamicRegisterInfo.cpp -------------------------------------------===//
2214054f7SMichał Górny //
3214054f7SMichał Górny // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4214054f7SMichał Górny // See https://llvm.org/LICENSE.txt for license information.
5214054f7SMichał Górny // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6214054f7SMichał Górny //
7214054f7SMichał Górny //===----------------------------------------------------------------------===//
8214054f7SMichał Górny
9214054f7SMichał Górny #include "lldb/Target/DynamicRegisterInfo.h"
10214054f7SMichał Górny #include "lldb/Core/StreamFile.h"
11214054f7SMichał Górny #include "lldb/DataFormatters/FormatManager.h"
12214054f7SMichał Górny #include "lldb/Interpreter/OptionArgParser.h"
13214054f7SMichał Górny #include "lldb/Utility/ArchSpec.h"
14c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
15214054f7SMichał Górny #include "lldb/Utility/Log.h"
16214054f7SMichał Górny #include "lldb/Utility/RegularExpression.h"
17214054f7SMichał Górny #include "lldb/Utility/StringExtractor.h"
18214054f7SMichał Górny #include "lldb/Utility/StructuredData.h"
19214054f7SMichał Górny
20214054f7SMichał Górny using namespace lldb;
21214054f7SMichał Górny using namespace lldb_private;
22214054f7SMichał Górny
DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary & dict,const lldb_private::ArchSpec & arch)23214054f7SMichał Górny DynamicRegisterInfo::DynamicRegisterInfo(
24214054f7SMichał Górny const lldb_private::StructuredData::Dictionary &dict,
25214054f7SMichał Górny const lldb_private::ArchSpec &arch) {
26214054f7SMichał Górny SetRegisterInfo(dict, arch);
27214054f7SMichał Górny }
28214054f7SMichał Górny
DynamicRegisterInfo(DynamicRegisterInfo && info)29214054f7SMichał Górny DynamicRegisterInfo::DynamicRegisterInfo(DynamicRegisterInfo &&info) {
30214054f7SMichał Górny MoveFrom(std::move(info));
31214054f7SMichał Górny }
32214054f7SMichał Górny
33214054f7SMichał Górny DynamicRegisterInfo &
operator =(DynamicRegisterInfo && info)34214054f7SMichał Górny DynamicRegisterInfo::operator=(DynamicRegisterInfo &&info) {
35214054f7SMichał Górny MoveFrom(std::move(info));
36214054f7SMichał Górny return *this;
37214054f7SMichał Górny }
38214054f7SMichał Górny
MoveFrom(DynamicRegisterInfo && info)39214054f7SMichał Górny void DynamicRegisterInfo::MoveFrom(DynamicRegisterInfo &&info) {
40214054f7SMichał Górny m_regs = std::move(info.m_regs);
41214054f7SMichał Górny m_sets = std::move(info.m_sets);
42214054f7SMichał Górny m_set_reg_nums = std::move(info.m_set_reg_nums);
43214054f7SMichał Górny m_set_names = std::move(info.m_set_names);
44214054f7SMichał Górny m_value_regs_map = std::move(info.m_value_regs_map);
45214054f7SMichał Górny m_invalidate_regs_map = std::move(info.m_invalidate_regs_map);
46214054f7SMichał Górny
47214054f7SMichał Górny m_reg_data_byte_size = info.m_reg_data_byte_size;
48214054f7SMichał Górny m_finalized = info.m_finalized;
49214054f7SMichał Górny
50214054f7SMichał Górny if (m_finalized) {
51214054f7SMichał Górny const size_t num_sets = m_sets.size();
52214054f7SMichał Górny for (size_t set = 0; set < num_sets; ++set)
53214054f7SMichał Górny m_sets[set].registers = m_set_reg_nums[set].data();
54214054f7SMichał Górny }
55214054f7SMichał Górny
56214054f7SMichał Górny info.Clear();
57214054f7SMichał Górny }
58214054f7SMichał Górny
ByteOffsetFromSlice(uint32_t index,llvm::StringRef slice_str,lldb::ByteOrder byte_order)59214054f7SMichał Górny llvm::Expected<uint32_t> DynamicRegisterInfo::ByteOffsetFromSlice(
60214054f7SMichał Górny uint32_t index, llvm::StringRef slice_str, lldb::ByteOrder byte_order) {
61214054f7SMichał Górny // Slices use the following format:
62214054f7SMichał Górny // REGNAME[MSBIT:LSBIT]
63214054f7SMichał Górny // REGNAME - name of the register to grab a slice of
64214054f7SMichał Górny // MSBIT - the most significant bit at which the current register value
65214054f7SMichał Górny // starts at
66214054f7SMichał Górny // LSBIT - the least significant bit at which the current register value
67214054f7SMichał Górny // ends at
68214054f7SMichał Górny static llvm::Regex g_bitfield_regex(
69214054f7SMichał Górny "([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]");
70214054f7SMichał Górny llvm::SmallVector<llvm::StringRef, 4> matches;
71214054f7SMichał Górny if (!g_bitfield_regex.match(slice_str, &matches))
72214054f7SMichał Górny return llvm::createStringError(
73214054f7SMichał Górny llvm::inconvertibleErrorCode(),
74214054f7SMichał Górny "failed to match against register bitfield regex (slice: %s)",
75214054f7SMichał Górny slice_str.str().c_str());
76214054f7SMichał Górny
77214054f7SMichał Górny llvm::StringRef reg_name_str = matches[1];
78214054f7SMichał Górny llvm::StringRef msbit_str = matches[2];
79214054f7SMichał Górny llvm::StringRef lsbit_str = matches[3];
80214054f7SMichał Górny uint32_t msbit;
81214054f7SMichał Górny uint32_t lsbit;
82214054f7SMichał Górny if (!llvm::to_integer(msbit_str, msbit) ||
83214054f7SMichał Górny !llvm::to_integer(lsbit_str, lsbit))
84214054f7SMichał Górny return llvm::createStringError(
85214054f7SMichał Górny llvm::inconvertibleErrorCode(), "msbit (%s) or lsbit (%s) are invalid",
86214054f7SMichał Górny msbit_str.str().c_str(), lsbit_str.str().c_str());
87214054f7SMichał Górny
88214054f7SMichał Górny if (msbit <= lsbit)
89214054f7SMichał Górny return llvm::createStringError(llvm::inconvertibleErrorCode(),
90214054f7SMichał Górny "msbit (%u) must be greater than lsbit (%u)",
91214054f7SMichał Górny msbit, lsbit);
92214054f7SMichał Górny
93214054f7SMichał Górny const uint32_t msbyte = msbit / 8;
94214054f7SMichał Górny const uint32_t lsbyte = lsbit / 8;
95214054f7SMichał Górny
96214054f7SMichał Górny const RegisterInfo *containing_reg_info = GetRegisterInfo(reg_name_str);
97214054f7SMichał Górny if (!containing_reg_info)
98214054f7SMichał Górny return llvm::createStringError(llvm::inconvertibleErrorCode(),
99214054f7SMichał Górny "invalid concrete register \"%s\"",
100214054f7SMichał Górny reg_name_str.str().c_str());
101214054f7SMichał Górny
102214054f7SMichał Górny const uint32_t max_bit = containing_reg_info->byte_size * 8;
103214054f7SMichał Górny
104214054f7SMichał Górny if (msbit > max_bit)
105214054f7SMichał Górny return llvm::createStringError(
106214054f7SMichał Górny llvm::inconvertibleErrorCode(),
107214054f7SMichał Górny "msbit (%u) must be less than the bitsize of the register \"%s\" (%u)",
108214054f7SMichał Górny msbit, reg_name_str.str().c_str(), max_bit);
109214054f7SMichał Górny if (lsbit > max_bit)
110214054f7SMichał Górny return llvm::createStringError(
111214054f7SMichał Górny llvm::inconvertibleErrorCode(),
112214054f7SMichał Górny "lsbit (%u) must be less than the bitsize of the register \"%s\" (%u)",
113214054f7SMichał Górny lsbit, reg_name_str.str().c_str(), max_bit);
114214054f7SMichał Górny
115214054f7SMichał Górny m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]]
116214054f7SMichał Górny .push_back(index);
117214054f7SMichał Górny m_value_regs_map[index].push_back(
118214054f7SMichał Górny containing_reg_info->kinds[eRegisterKindLLDB]);
119214054f7SMichał Górny m_invalidate_regs_map[index].push_back(
120214054f7SMichał Górny containing_reg_info->kinds[eRegisterKindLLDB]);
121214054f7SMichał Górny
122214054f7SMichał Górny if (byte_order == eByteOrderLittle)
123214054f7SMichał Górny return containing_reg_info->byte_offset + lsbyte;
124214054f7SMichał Górny if (byte_order == eByteOrderBig)
125214054f7SMichał Górny return containing_reg_info->byte_offset + msbyte;
126214054f7SMichał Górny llvm_unreachable("Invalid byte order");
127214054f7SMichał Górny }
128214054f7SMichał Górny
ByteOffsetFromComposite(uint32_t index,StructuredData::Array & composite_reg_list,lldb::ByteOrder byte_order)129214054f7SMichał Górny llvm::Expected<uint32_t> DynamicRegisterInfo::ByteOffsetFromComposite(
130214054f7SMichał Górny uint32_t index, StructuredData::Array &composite_reg_list,
131214054f7SMichał Górny lldb::ByteOrder byte_order) {
132214054f7SMichał Górny const size_t num_composite_regs = composite_reg_list.GetSize();
133214054f7SMichał Górny if (num_composite_regs == 0)
134214054f7SMichał Górny return llvm::createStringError(llvm::inconvertibleErrorCode(),
135214054f7SMichał Górny "\"composite\" list is empty");
136214054f7SMichał Górny
137214054f7SMichał Górny uint32_t composite_offset = UINT32_MAX;
138214054f7SMichał Górny for (uint32_t composite_idx = 0; composite_idx < num_composite_regs;
139214054f7SMichał Górny ++composite_idx) {
140214054f7SMichał Górny ConstString composite_reg_name;
141214054f7SMichał Górny if (!composite_reg_list.GetItemAtIndexAsString(composite_idx,
142214054f7SMichał Górny composite_reg_name, nullptr))
143214054f7SMichał Górny return llvm::createStringError(
144214054f7SMichał Górny llvm::inconvertibleErrorCode(),
145214054f7SMichał Górny "\"composite\" list value is not a Python string at index %d",
146214054f7SMichał Górny composite_idx);
147214054f7SMichał Górny
148214054f7SMichał Górny const RegisterInfo *composite_reg_info =
149214054f7SMichał Górny GetRegisterInfo(composite_reg_name.GetStringRef());
150214054f7SMichał Górny if (!composite_reg_info)
151214054f7SMichał Górny return llvm::createStringError(
152214054f7SMichał Górny llvm::inconvertibleErrorCode(),
153214054f7SMichał Górny "failed to find composite register by name: \"%s\"",
154214054f7SMichał Górny composite_reg_name.GetCString());
155214054f7SMichał Górny
156214054f7SMichał Górny composite_offset =
157214054f7SMichał Górny std::min(composite_offset, composite_reg_info->byte_offset);
158214054f7SMichał Górny m_value_regs_map[index].push_back(
159214054f7SMichał Górny composite_reg_info->kinds[eRegisterKindLLDB]);
160214054f7SMichał Górny m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]]
161214054f7SMichał Górny .push_back(index);
162214054f7SMichał Górny m_invalidate_regs_map[index].push_back(
163214054f7SMichał Górny composite_reg_info->kinds[eRegisterKindLLDB]);
164214054f7SMichał Górny }
165214054f7SMichał Górny
166214054f7SMichał Górny return composite_offset;
167214054f7SMichał Górny }
168214054f7SMichał Górny
ByteOffsetFromRegInfoDict(uint32_t index,StructuredData::Dictionary & reg_info_dict,lldb::ByteOrder byte_order)169214054f7SMichał Górny llvm::Expected<uint32_t> DynamicRegisterInfo::ByteOffsetFromRegInfoDict(
170214054f7SMichał Górny uint32_t index, StructuredData::Dictionary ®_info_dict,
171214054f7SMichał Górny lldb::ByteOrder byte_order) {
172214054f7SMichał Górny uint32_t byte_offset;
173214054f7SMichał Górny if (reg_info_dict.GetValueForKeyAsInteger("offset", byte_offset))
174214054f7SMichał Górny return byte_offset;
175214054f7SMichał Górny
176214054f7SMichał Górny // No offset for this register, see if the register has a value
177214054f7SMichał Górny // expression which indicates this register is part of another register.
178214054f7SMichał Górny // Value expressions are things like "rax[31:0]" which state that the
179214054f7SMichał Górny // current register's value is in a concrete register "rax" in bits 31:0.
180214054f7SMichał Górny // If there is a value expression we can calculate the offset
181214054f7SMichał Górny llvm::StringRef slice_str;
182214054f7SMichał Górny if (reg_info_dict.GetValueForKeyAsString("slice", slice_str, nullptr))
183214054f7SMichał Górny return ByteOffsetFromSlice(index, slice_str, byte_order);
184214054f7SMichał Górny
185214054f7SMichał Górny StructuredData::Array *composite_reg_list;
186214054f7SMichał Górny if (reg_info_dict.GetValueForKeyAsArray("composite", composite_reg_list))
187214054f7SMichał Górny return ByteOffsetFromComposite(index, *composite_reg_list, byte_order);
188214054f7SMichał Górny
189214054f7SMichał Górny return llvm::createStringError(llvm::inconvertibleErrorCode(),
190214054f7SMichał Górny "insufficient data to calculate byte offset");
191214054f7SMichał Górny }
192214054f7SMichał Górny
193214054f7SMichał Górny size_t
SetRegisterInfo(const StructuredData::Dictionary & dict,const ArchSpec & arch)194214054f7SMichał Górny DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
195214054f7SMichał Górny const ArchSpec &arch) {
196a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Object);
197214054f7SMichał Górny assert(!m_finalized);
198214054f7SMichał Górny StructuredData::Array *sets = nullptr;
199214054f7SMichał Górny if (dict.GetValueForKeyAsArray("sets", sets)) {
200214054f7SMichał Górny const uint32_t num_sets = sets->GetSize();
201214054f7SMichał Górny for (uint32_t i = 0; i < num_sets; ++i) {
202214054f7SMichał Górny ConstString set_name;
203214054f7SMichał Górny if (sets->GetItemAtIndexAsString(i, set_name) && !set_name.IsEmpty()) {
204214054f7SMichał Górny m_sets.push_back({set_name.AsCString(), nullptr, 0, nullptr});
205214054f7SMichał Górny } else {
206214054f7SMichał Górny Clear();
207214054f7SMichał Górny printf("error: register sets must have valid names\n");
208214054f7SMichał Górny return 0;
209214054f7SMichał Górny }
210214054f7SMichał Górny }
211214054f7SMichał Górny m_set_reg_nums.resize(m_sets.size());
212214054f7SMichał Górny }
213214054f7SMichał Górny
214214054f7SMichał Górny StructuredData::Array *regs = nullptr;
215214054f7SMichał Górny if (!dict.GetValueForKeyAsArray("registers", regs))
216214054f7SMichał Górny return 0;
217214054f7SMichał Górny
218214054f7SMichał Górny const ByteOrder byte_order = arch.GetByteOrder();
219214054f7SMichał Górny
220214054f7SMichał Górny const uint32_t num_regs = regs->GetSize();
221214054f7SMichał Górny // typedef std::map<std::string, std::vector<std::string> >
222214054f7SMichał Górny // InvalidateNameMap;
223214054f7SMichał Górny // InvalidateNameMap invalidate_map;
224214054f7SMichał Górny for (uint32_t i = 0; i < num_regs; ++i) {
225214054f7SMichał Górny StructuredData::Dictionary *reg_info_dict = nullptr;
226214054f7SMichał Górny if (!regs->GetItemAtIndexAsDictionary(i, reg_info_dict)) {
227214054f7SMichał Górny Clear();
228214054f7SMichał Górny printf("error: items in the 'registers' array must be dictionaries\n");
229214054f7SMichał Górny regs->DumpToStdout();
230214054f7SMichał Górny return 0;
231214054f7SMichał Górny }
232214054f7SMichał Górny
233214054f7SMichał Górny // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16,
234214054f7SMichał Górny // 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2,
235214054f7SMichał Górny // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
236214054f7SMichał Górny RegisterInfo reg_info;
237214054f7SMichał Górny std::vector<uint32_t> value_regs;
238214054f7SMichał Górny std::vector<uint32_t> invalidate_regs;
239214054f7SMichał Górny memset(®_info, 0, sizeof(reg_info));
240214054f7SMichał Górny
241214054f7SMichał Górny ConstString name_val;
242214054f7SMichał Górny ConstString alt_name_val;
243214054f7SMichał Górny if (!reg_info_dict->GetValueForKeyAsString("name", name_val, nullptr)) {
244214054f7SMichał Górny Clear();
245214054f7SMichał Górny printf("error: registers must have valid names and offsets\n");
246214054f7SMichał Górny reg_info_dict->DumpToStdout();
247214054f7SMichał Górny return 0;
248214054f7SMichał Górny }
249214054f7SMichał Górny reg_info.name = name_val.GetCString();
250214054f7SMichał Górny reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val, nullptr);
251214054f7SMichał Górny reg_info.alt_name = alt_name_val.GetCString();
252214054f7SMichał Górny
253214054f7SMichał Górny llvm::Expected<uint32_t> byte_offset =
254214054f7SMichał Górny ByteOffsetFromRegInfoDict(i, *reg_info_dict, byte_order);
255214054f7SMichał Górny if (byte_offset)
256214054f7SMichał Górny reg_info.byte_offset = byte_offset.get();
257214054f7SMichał Górny else {
258214054f7SMichał Górny LLDB_LOG_ERROR(log, byte_offset.takeError(),
259214054f7SMichał Górny "error while parsing register {1}: {0}", reg_info.name);
260214054f7SMichał Górny Clear();
261214054f7SMichał Górny reg_info_dict->DumpToStdout();
262214054f7SMichał Górny return 0;
263214054f7SMichał Górny }
264214054f7SMichał Górny
265214054f7SMichał Górny int64_t bitsize = 0;
266214054f7SMichał Górny if (!reg_info_dict->GetValueForKeyAsInteger("bitsize", bitsize)) {
267214054f7SMichał Górny Clear();
268214054f7SMichał Górny printf("error: invalid or missing 'bitsize' key/value pair in register "
269214054f7SMichał Górny "dictionary\n");
270214054f7SMichał Górny reg_info_dict->DumpToStdout();
271214054f7SMichał Górny return 0;
272214054f7SMichał Górny }
273214054f7SMichał Górny
274214054f7SMichał Górny reg_info.byte_size = bitsize / 8;
275214054f7SMichał Górny
276214054f7SMichał Górny llvm::StringRef format_str;
277214054f7SMichał Górny if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) {
278214054f7SMichał Górny if (OptionArgParser::ToFormat(format_str.str().c_str(), reg_info.format,
279214054f7SMichał Górny nullptr)
280214054f7SMichał Górny .Fail()) {
281214054f7SMichał Górny Clear();
282214054f7SMichał Górny printf("error: invalid 'format' value in register dictionary\n");
283214054f7SMichał Górny reg_info_dict->DumpToStdout();
284214054f7SMichał Górny return 0;
285214054f7SMichał Górny }
286214054f7SMichał Górny } else {
287214054f7SMichał Górny reg_info_dict->GetValueForKeyAsInteger("format", reg_info.format,
288214054f7SMichał Górny eFormatHex);
289214054f7SMichał Górny }
290214054f7SMichał Górny
291214054f7SMichał Górny llvm::StringRef encoding_str;
292214054f7SMichał Górny if (reg_info_dict->GetValueForKeyAsString("encoding", encoding_str))
293214054f7SMichał Górny reg_info.encoding = Args::StringToEncoding(encoding_str, eEncodingUint);
294214054f7SMichał Górny else
295214054f7SMichał Górny reg_info_dict->GetValueForKeyAsInteger("encoding", reg_info.encoding,
296214054f7SMichał Górny eEncodingUint);
297214054f7SMichał Górny
298214054f7SMichał Górny size_t set = 0;
299214054f7SMichał Górny if (!reg_info_dict->GetValueForKeyAsInteger<size_t>("set", set, -1) ||
300214054f7SMichał Górny set >= m_sets.size()) {
301214054f7SMichał Górny Clear();
302214054f7SMichał Górny printf("error: invalid 'set' value in register dictionary, valid values "
303214054f7SMichał Górny "are 0 - %i\n",
304214054f7SMichał Górny (int)set);
305214054f7SMichał Górny reg_info_dict->DumpToStdout();
306214054f7SMichał Górny return 0;
307214054f7SMichał Górny }
308214054f7SMichał Górny
309214054f7SMichał Górny // Fill in the register numbers
310214054f7SMichał Górny reg_info.kinds[lldb::eRegisterKindLLDB] = i;
311214054f7SMichał Górny reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i;
312214054f7SMichał Górny uint32_t eh_frame_regno = LLDB_INVALID_REGNUM;
313214054f7SMichał Górny reg_info_dict->GetValueForKeyAsInteger("gcc", eh_frame_regno,
314214054f7SMichał Górny LLDB_INVALID_REGNUM);
315214054f7SMichał Górny if (eh_frame_regno == LLDB_INVALID_REGNUM)
316214054f7SMichał Górny reg_info_dict->GetValueForKeyAsInteger("ehframe", eh_frame_regno,
317214054f7SMichał Górny LLDB_INVALID_REGNUM);
318214054f7SMichał Górny reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno;
319214054f7SMichał Górny reg_info_dict->GetValueForKeyAsInteger(
320214054f7SMichał Górny "dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM);
321214054f7SMichał Górny llvm::StringRef generic_str;
322214054f7SMichał Górny if (reg_info_dict->GetValueForKeyAsString("generic", generic_str))
323214054f7SMichał Górny reg_info.kinds[lldb::eRegisterKindGeneric] =
324214054f7SMichał Górny Args::StringToGenericRegister(generic_str);
325214054f7SMichał Górny else
326214054f7SMichał Górny reg_info_dict->GetValueForKeyAsInteger(
327214054f7SMichał Górny "generic", reg_info.kinds[lldb::eRegisterKindGeneric],
328214054f7SMichał Górny LLDB_INVALID_REGNUM);
329214054f7SMichał Górny
330214054f7SMichał Górny // Check if this register invalidates any other register values when it is
331214054f7SMichał Górny // modified
332214054f7SMichał Górny StructuredData::Array *invalidate_reg_list = nullptr;
333214054f7SMichał Górny if (reg_info_dict->GetValueForKeyAsArray("invalidate-regs",
334214054f7SMichał Górny invalidate_reg_list)) {
335214054f7SMichał Górny const size_t num_regs = invalidate_reg_list->GetSize();
336214054f7SMichał Górny if (num_regs > 0) {
337214054f7SMichał Górny for (uint32_t idx = 0; idx < num_regs; ++idx) {
338214054f7SMichał Górny ConstString invalidate_reg_name;
339214054f7SMichał Górny uint64_t invalidate_reg_num;
340214054f7SMichał Górny if (invalidate_reg_list->GetItemAtIndexAsString(
341214054f7SMichał Górny idx, invalidate_reg_name)) {
342214054f7SMichał Górny const RegisterInfo *invalidate_reg_info =
343214054f7SMichał Górny GetRegisterInfo(invalidate_reg_name.GetStringRef());
344214054f7SMichał Górny if (invalidate_reg_info) {
345214054f7SMichał Górny m_invalidate_regs_map[i].push_back(
346214054f7SMichał Górny invalidate_reg_info->kinds[eRegisterKindLLDB]);
347214054f7SMichał Górny } else {
348214054f7SMichał Górny // TODO: print error invalid slice string that doesn't follow the
349214054f7SMichał Górny // format
350214054f7SMichał Górny printf("error: failed to find a 'invalidate-regs' register for "
351214054f7SMichał Górny "\"%s\" while parsing register \"%s\"\n",
352214054f7SMichał Górny invalidate_reg_name.GetCString(), reg_info.name);
353214054f7SMichał Górny }
354214054f7SMichał Górny } else if (invalidate_reg_list->GetItemAtIndexAsInteger(
355214054f7SMichał Górny idx, invalidate_reg_num)) {
356214054f7SMichał Górny if (invalidate_reg_num != UINT64_MAX)
357214054f7SMichał Górny m_invalidate_regs_map[i].push_back(invalidate_reg_num);
358214054f7SMichał Górny else
359214054f7SMichał Górny printf("error: 'invalidate-regs' list value wasn't a valid "
360214054f7SMichał Górny "integer\n");
361214054f7SMichał Górny } else {
362214054f7SMichał Górny printf("error: 'invalidate-regs' list value wasn't a python string "
363214054f7SMichał Górny "or integer\n");
364214054f7SMichał Górny }
365214054f7SMichał Górny }
366214054f7SMichał Górny } else {
367214054f7SMichał Górny printf("error: 'invalidate-regs' contained an empty list\n");
368214054f7SMichał Górny }
369214054f7SMichał Górny }
370214054f7SMichał Górny
371214054f7SMichał Górny // Calculate the register offset
372214054f7SMichał Górny const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
373214054f7SMichał Górny if (m_reg_data_byte_size < end_reg_offset)
374214054f7SMichał Górny m_reg_data_byte_size = end_reg_offset;
375214054f7SMichał Górny
376214054f7SMichał Górny m_regs.push_back(reg_info);
377214054f7SMichał Górny m_set_reg_nums[set].push_back(i);
378214054f7SMichał Górny }
379214054f7SMichał Górny Finalize(arch);
380214054f7SMichał Górny return m_regs.size();
381214054f7SMichał Górny }
382214054f7SMichał Górny
SetRegisterInfo(std::vector<DynamicRegisterInfo::Register> && regs,const ArchSpec & arch)38366063277SMichał Górny size_t DynamicRegisterInfo::SetRegisterInfo(
38466063277SMichał Górny std::vector<DynamicRegisterInfo::Register> &®s,
38566063277SMichał Górny const ArchSpec &arch) {
38666063277SMichał Górny assert(!m_finalized);
38766063277SMichał Górny
38866063277SMichał Górny for (auto it : llvm::enumerate(regs)) {
38966063277SMichał Górny uint32_t local_regnum = it.index();
39066063277SMichał Górny const DynamicRegisterInfo::Register ® = it.value();
39166063277SMichał Górny
39266063277SMichał Górny assert(reg.name);
39366063277SMichał Górny assert(reg.set_name);
39466063277SMichał Górny
39566063277SMichał Górny if (!reg.value_regs.empty())
39666063277SMichał Górny m_value_regs_map[local_regnum] = std::move(reg.value_regs);
39766063277SMichał Górny if (!reg.invalidate_regs.empty())
39866063277SMichał Górny m_invalidate_regs_map[local_regnum] = std::move(reg.invalidate_regs);
3990d1705a9SMichał Górny if (reg.value_reg_offset != 0) {
4000d1705a9SMichał Górny assert(reg.value_regs.size() == 1);
4010d1705a9SMichał Górny m_value_reg_offset_map[local_regnum] = reg.value_reg_offset;
4020d1705a9SMichał Górny }
40366063277SMichał Górny
40466063277SMichał Górny struct RegisterInfo reg_info {
40566063277SMichał Górny reg.name.AsCString(), reg.alt_name.AsCString(), reg.byte_size,
40666063277SMichał Górny reg.byte_offset, reg.encoding, reg.format,
40766063277SMichał Górny {reg.regnum_ehframe, reg.regnum_dwarf, reg.regnum_generic,
40866063277SMichał Górny reg.regnum_remote, local_regnum},
40966063277SMichał Górny // value_regs and invalidate_regs are filled by Finalize()
41066063277SMichał Górny nullptr, nullptr
41166063277SMichał Górny };
41266063277SMichał Górny
41366063277SMichał Górny m_regs.push_back(reg_info);
41466063277SMichał Górny
41566063277SMichał Górny uint32_t set = GetRegisterSetIndexByName(reg.set_name, true);
41666063277SMichał Górny assert(set < m_sets.size());
41766063277SMichał Górny assert(set < m_set_reg_nums.size());
41866063277SMichał Górny assert(set < m_set_names.size());
41966063277SMichał Górny m_set_reg_nums[set].push_back(local_regnum);
42066063277SMichał Górny };
42166063277SMichał Górny
42266063277SMichał Górny Finalize(arch);
42366063277SMichał Górny return m_regs.size();
42466063277SMichał Górny }
42566063277SMichał Górny
Finalize(const ArchSpec & arch)426214054f7SMichał Górny void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
427214054f7SMichał Górny if (m_finalized)
428214054f7SMichał Górny return;
429214054f7SMichał Górny
430214054f7SMichał Górny m_finalized = true;
431214054f7SMichał Górny const size_t num_sets = m_sets.size();
432214054f7SMichał Górny for (size_t set = 0; set < num_sets; ++set) {
433214054f7SMichał Górny assert(m_sets.size() == m_set_reg_nums.size());
434214054f7SMichał Górny m_sets[set].num_registers = m_set_reg_nums[set].size();
435214054f7SMichał Górny m_sets[set].registers = m_set_reg_nums[set].data();
436214054f7SMichał Górny }
437214054f7SMichał Górny
438f290efc3SMichał Górny // make sure value_regs are terminated with LLDB_INVALID_REGNUM
439214054f7SMichał Górny
440214054f7SMichał Górny for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(),
441214054f7SMichał Górny end = m_value_regs_map.end();
442214054f7SMichał Górny pos != end; ++pos) {
443214054f7SMichał Górny if (pos->second.back() != LLDB_INVALID_REGNUM)
444214054f7SMichał Górny pos->second.push_back(LLDB_INVALID_REGNUM);
445214054f7SMichał Górny }
446214054f7SMichał Górny
447214054f7SMichał Górny // Now update all value_regs with each register info as needed
448214054f7SMichał Górny const size_t num_regs = m_regs.size();
449214054f7SMichał Górny for (size_t i = 0; i < num_regs; ++i) {
450214054f7SMichał Górny if (m_value_regs_map.find(i) != m_value_regs_map.end())
451214054f7SMichał Górny m_regs[i].value_regs = m_value_regs_map[i].data();
452214054f7SMichał Górny else
453214054f7SMichał Górny m_regs[i].value_regs = nullptr;
454214054f7SMichał Górny }
455214054f7SMichał Górny
456214054f7SMichał Górny // Expand all invalidation dependencies
457214054f7SMichał Górny for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(),
458214054f7SMichał Górny end = m_invalidate_regs_map.end();
459214054f7SMichał Górny pos != end; ++pos) {
460214054f7SMichał Górny const uint32_t reg_num = pos->first;
461214054f7SMichał Górny
462214054f7SMichał Górny if (m_regs[reg_num].value_regs) {
463214054f7SMichał Górny reg_num_collection extra_invalid_regs;
464214054f7SMichał Górny for (const uint32_t invalidate_reg_num : pos->second) {
465214054f7SMichał Górny reg_to_regs_map::iterator invalidate_pos =
466214054f7SMichał Górny m_invalidate_regs_map.find(invalidate_reg_num);
467214054f7SMichał Górny if (invalidate_pos != m_invalidate_regs_map.end()) {
468214054f7SMichał Górny for (const uint32_t concrete_invalidate_reg_num :
469214054f7SMichał Górny invalidate_pos->second) {
470214054f7SMichał Górny if (concrete_invalidate_reg_num != reg_num)
471214054f7SMichał Górny extra_invalid_regs.push_back(concrete_invalidate_reg_num);
472214054f7SMichał Górny }
473214054f7SMichał Górny }
474214054f7SMichał Górny }
475214054f7SMichał Górny pos->second.insert(pos->second.end(), extra_invalid_regs.begin(),
476214054f7SMichał Górny extra_invalid_regs.end());
477214054f7SMichał Górny }
478214054f7SMichał Górny }
479214054f7SMichał Górny
480214054f7SMichał Górny // sort and unique all invalidate registers and make sure each is terminated
481214054f7SMichał Górny // with LLDB_INVALID_REGNUM
482214054f7SMichał Górny for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(),
483214054f7SMichał Górny end = m_invalidate_regs_map.end();
484214054f7SMichał Górny pos != end; ++pos) {
485214054f7SMichał Górny if (pos->second.size() > 1) {
486*cd9a5cfdSDmitri Gribenko llvm::sort(pos->second);
487214054f7SMichał Górny reg_num_collection::iterator unique_end =
488214054f7SMichał Górny std::unique(pos->second.begin(), pos->second.end());
489214054f7SMichał Górny if (unique_end != pos->second.end())
490214054f7SMichał Górny pos->second.erase(unique_end, pos->second.end());
491214054f7SMichał Górny }
492214054f7SMichał Górny assert(!pos->second.empty());
493214054f7SMichał Górny if (pos->second.back() != LLDB_INVALID_REGNUM)
494214054f7SMichał Górny pos->second.push_back(LLDB_INVALID_REGNUM);
495214054f7SMichał Górny }
496214054f7SMichał Górny
497214054f7SMichał Górny // Now update all invalidate_regs with each register info as needed
498214054f7SMichał Górny for (size_t i = 0; i < num_regs; ++i) {
499214054f7SMichał Górny if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end())
500214054f7SMichał Górny m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data();
501214054f7SMichał Górny else
502214054f7SMichał Górny m_regs[i].invalidate_regs = nullptr;
503214054f7SMichał Górny }
504214054f7SMichał Górny
505214054f7SMichał Górny // Check if we need to automatically set the generic registers in case they
506214054f7SMichał Górny // weren't set
507214054f7SMichał Górny bool generic_regs_specified = false;
508214054f7SMichał Górny for (const auto ® : m_regs) {
509214054f7SMichał Górny if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
510214054f7SMichał Górny generic_regs_specified = true;
511214054f7SMichał Górny break;
512214054f7SMichał Górny }
513214054f7SMichał Górny }
514214054f7SMichał Górny
515214054f7SMichał Górny if (!generic_regs_specified) {
516214054f7SMichał Górny switch (arch.GetMachine()) {
517214054f7SMichał Górny case llvm::Triple::aarch64:
518214054f7SMichał Górny case llvm::Triple::aarch64_32:
519214054f7SMichał Górny case llvm::Triple::aarch64_be:
520214054f7SMichał Górny for (auto ® : m_regs) {
521214054f7SMichał Górny if (strcmp(reg.name, "pc") == 0)
522214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
523214054f7SMichał Górny else if ((strcmp(reg.name, "fp") == 0) ||
524214054f7SMichał Górny (strcmp(reg.name, "x29") == 0))
525214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
526214054f7SMichał Górny else if ((strcmp(reg.name, "lr") == 0) ||
527214054f7SMichał Górny (strcmp(reg.name, "x30") == 0))
528214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
529214054f7SMichał Górny else if ((strcmp(reg.name, "sp") == 0) ||
530214054f7SMichał Górny (strcmp(reg.name, "x31") == 0))
531214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
532214054f7SMichał Górny else if (strcmp(reg.name, "cpsr") == 0)
533214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
534214054f7SMichał Górny }
535214054f7SMichał Górny break;
536214054f7SMichał Górny
537214054f7SMichał Górny case llvm::Triple::arm:
538214054f7SMichał Górny case llvm::Triple::armeb:
539214054f7SMichał Górny case llvm::Triple::thumb:
540214054f7SMichał Górny case llvm::Triple::thumbeb:
541214054f7SMichał Górny for (auto ® : m_regs) {
542214054f7SMichał Górny if ((strcmp(reg.name, "pc") == 0) || (strcmp(reg.name, "r15") == 0))
543214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
544214054f7SMichał Górny else if ((strcmp(reg.name, "sp") == 0) ||
545214054f7SMichał Górny (strcmp(reg.name, "r13") == 0))
546214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
547214054f7SMichał Górny else if ((strcmp(reg.name, "lr") == 0) ||
548214054f7SMichał Górny (strcmp(reg.name, "r14") == 0))
549214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
550214054f7SMichał Górny else if ((strcmp(reg.name, "r7") == 0) &&
551214054f7SMichał Górny arch.GetTriple().getVendor() == llvm::Triple::Apple)
552214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
553214054f7SMichał Górny else if ((strcmp(reg.name, "r11") == 0) &&
554214054f7SMichał Górny arch.GetTriple().getVendor() != llvm::Triple::Apple)
555214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
556214054f7SMichał Górny else if (strcmp(reg.name, "fp") == 0)
557214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
558214054f7SMichał Górny else if (strcmp(reg.name, "cpsr") == 0)
559214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
560214054f7SMichał Górny }
561214054f7SMichał Górny break;
562214054f7SMichał Górny
563214054f7SMichał Górny case llvm::Triple::x86:
564214054f7SMichał Górny for (auto ® : m_regs) {
565214054f7SMichał Górny if ((strcmp(reg.name, "eip") == 0) || (strcmp(reg.name, "pc") == 0))
566214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
567214054f7SMichał Górny else if ((strcmp(reg.name, "esp") == 0) ||
568214054f7SMichał Górny (strcmp(reg.name, "sp") == 0))
569214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
570214054f7SMichał Górny else if ((strcmp(reg.name, "ebp") == 0) ||
571214054f7SMichał Górny (strcmp(reg.name, "fp") == 0))
572214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
573214054f7SMichał Górny else if ((strcmp(reg.name, "eflags") == 0) ||
574214054f7SMichał Górny (strcmp(reg.name, "flags") == 0))
575214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
576214054f7SMichał Górny }
577214054f7SMichał Górny break;
578214054f7SMichał Górny
579214054f7SMichał Górny case llvm::Triple::x86_64:
580214054f7SMichał Górny for (auto ® : m_regs) {
581214054f7SMichał Górny if ((strcmp(reg.name, "rip") == 0) || (strcmp(reg.name, "pc") == 0))
582214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
583214054f7SMichał Górny else if ((strcmp(reg.name, "rsp") == 0) ||
584214054f7SMichał Górny (strcmp(reg.name, "sp") == 0))
585214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
586214054f7SMichał Górny else if ((strcmp(reg.name, "rbp") == 0) ||
587214054f7SMichał Górny (strcmp(reg.name, "fp") == 0))
588214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
589214054f7SMichał Górny else if ((strcmp(reg.name, "rflags") == 0) ||
590214054f7SMichał Górny (strcmp(reg.name, "eflags") == 0) ||
591214054f7SMichał Górny (strcmp(reg.name, "flags") == 0))
592214054f7SMichał Górny reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
593214054f7SMichał Górny }
594214054f7SMichał Górny break;
595214054f7SMichał Górny
596214054f7SMichał Górny default:
597214054f7SMichał Górny break;
598214054f7SMichał Górny }
599214054f7SMichał Górny }
600214054f7SMichał Górny
601214054f7SMichał Górny // At this stage call ConfigureOffsets to calculate register offsets for
602214054f7SMichał Górny // targets supporting dynamic offset calculation. It also calculates
603214054f7SMichał Górny // total byte size of register data.
604214054f7SMichał Górny ConfigureOffsets();
605214054f7SMichał Górny
606214054f7SMichał Górny // Check if register info is reconfigurable
607214054f7SMichał Górny // AArch64 SVE register set has configurable register sizes
608214054f7SMichał Górny if (arch.GetTriple().isAArch64()) {
609214054f7SMichał Górny for (const auto ® : m_regs) {
610214054f7SMichał Górny if (strcmp(reg.name, "vg") == 0) {
611214054f7SMichał Górny m_is_reconfigurable = true;
612214054f7SMichał Górny break;
613214054f7SMichał Górny }
614214054f7SMichał Górny }
615214054f7SMichał Górny }
616214054f7SMichał Górny }
617214054f7SMichał Górny
ConfigureOffsets()618214054f7SMichał Górny void DynamicRegisterInfo::ConfigureOffsets() {
619214054f7SMichał Górny // We are going to create a map between remote (eRegisterKindProcessPlugin)
620214054f7SMichał Górny // and local (eRegisterKindLLDB) register numbers. This map will give us
621214054f7SMichał Górny // remote register numbers in increasing order for offset calculation.
622214054f7SMichał Górny std::map<uint32_t, uint32_t> remote_to_local_regnum_map;
623214054f7SMichał Górny for (const auto ® : m_regs)
624214054f7SMichał Górny remote_to_local_regnum_map[reg.kinds[eRegisterKindProcessPlugin]] =
625214054f7SMichał Górny reg.kinds[eRegisterKindLLDB];
626214054f7SMichał Górny
627214054f7SMichał Górny // At this stage we manually calculate g/G packet offsets of all primary
628214054f7SMichał Górny // registers, only if target XML or qRegisterInfo packet did not send
629214054f7SMichał Górny // an offset explicitly.
630214054f7SMichał Górny uint32_t reg_offset = 0;
631214054f7SMichał Górny for (auto const ®num_pair : remote_to_local_regnum_map) {
632214054f7SMichał Górny if (m_regs[regnum_pair.second].byte_offset == LLDB_INVALID_INDEX32 &&
633214054f7SMichał Górny m_regs[regnum_pair.second].value_regs == nullptr) {
634214054f7SMichał Górny m_regs[regnum_pair.second].byte_offset = reg_offset;
635214054f7SMichał Górny
636214054f7SMichał Górny reg_offset = m_regs[regnum_pair.second].byte_offset +
637214054f7SMichał Górny m_regs[regnum_pair.second].byte_size;
638214054f7SMichał Górny }
639214054f7SMichał Górny }
640214054f7SMichał Górny
641214054f7SMichał Górny // Now update all value_regs with each register info as needed
642214054f7SMichał Górny for (auto ® : m_regs) {
643214054f7SMichał Górny if (reg.value_regs != nullptr) {
644f290efc3SMichał Górny // Assign a valid offset to all pseudo registers that have only a single
645f290efc3SMichał Górny // parent register in value_regs list, if not assigned by stub. Pseudo
646f290efc3SMichał Górny // registers with value_regs list populated will share same offset as
647f290efc3SMichał Górny // that of their corresponding parent register.
648214054f7SMichał Górny if (reg.byte_offset == LLDB_INVALID_INDEX32) {
649214054f7SMichał Górny uint32_t value_regnum = reg.value_regs[0];
650f290efc3SMichał Górny if (value_regnum != LLDB_INVALID_INDEX32 &&
651f290efc3SMichał Górny reg.value_regs[1] == LLDB_INVALID_INDEX32) {
652f290efc3SMichał Górny reg.byte_offset =
653f290efc3SMichał Górny GetRegisterInfoAtIndex(value_regnum)->byte_offset;
6540d1705a9SMichał Górny auto it = m_value_reg_offset_map.find(reg.kinds[eRegisterKindLLDB]);
6550d1705a9SMichał Górny if (it != m_value_reg_offset_map.end())
6560d1705a9SMichał Górny reg.byte_offset += it->second;
6570d1705a9SMichał Górny }
658214054f7SMichał Górny }
659214054f7SMichał Górny }
660214054f7SMichał Górny
661214054f7SMichał Górny reg_offset = reg.byte_offset + reg.byte_size;
662214054f7SMichał Górny if (m_reg_data_byte_size < reg_offset)
663214054f7SMichał Górny m_reg_data_byte_size = reg_offset;
664214054f7SMichał Górny }
665214054f7SMichał Górny }
666214054f7SMichał Górny
IsReconfigurable()667214054f7SMichał Górny bool DynamicRegisterInfo::IsReconfigurable() { return m_is_reconfigurable; }
668214054f7SMichał Górny
GetNumRegisters() const669214054f7SMichał Górny size_t DynamicRegisterInfo::GetNumRegisters() const { return m_regs.size(); }
670214054f7SMichał Górny
GetNumRegisterSets() const671214054f7SMichał Górny size_t DynamicRegisterInfo::GetNumRegisterSets() const { return m_sets.size(); }
672214054f7SMichał Górny
GetRegisterDataByteSize() const673214054f7SMichał Górny size_t DynamicRegisterInfo::GetRegisterDataByteSize() const {
674214054f7SMichał Górny return m_reg_data_byte_size;
675214054f7SMichał Górny }
676214054f7SMichał Górny
677214054f7SMichał Górny const RegisterInfo *
GetRegisterInfoAtIndex(uint32_t i) const678214054f7SMichał Górny DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) const {
679214054f7SMichał Górny if (i < m_regs.size())
680214054f7SMichał Górny return &m_regs[i];
681214054f7SMichał Górny return nullptr;
682214054f7SMichał Górny }
683214054f7SMichał Górny
GetRegisterInfo(uint32_t kind,uint32_t num) const684214054f7SMichał Górny const RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(uint32_t kind,
685214054f7SMichał Górny uint32_t num) const {
686214054f7SMichał Górny uint32_t reg_index = ConvertRegisterKindToRegisterNumber(kind, num);
687214054f7SMichał Górny if (reg_index != LLDB_INVALID_REGNUM)
688214054f7SMichał Górny return &m_regs[reg_index];
689214054f7SMichał Górny return nullptr;
690214054f7SMichał Górny }
691214054f7SMichał Górny
GetRegisterSet(uint32_t i) const692214054f7SMichał Górny const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const {
693214054f7SMichał Górny if (i < m_sets.size())
694214054f7SMichał Górny return &m_sets[i];
695214054f7SMichał Górny return nullptr;
696214054f7SMichał Górny }
697214054f7SMichał Górny
69866063277SMichał Górny uint32_t
GetRegisterSetIndexByName(const ConstString & set_name,bool can_create)69966063277SMichał Górny DynamicRegisterInfo::GetRegisterSetIndexByName(const ConstString &set_name,
700214054f7SMichał Górny bool can_create) {
701214054f7SMichał Górny name_collection::iterator pos, end = m_set_names.end();
702214054f7SMichał Górny for (pos = m_set_names.begin(); pos != end; ++pos) {
703214054f7SMichał Górny if (*pos == set_name)
704214054f7SMichał Górny return std::distance(m_set_names.begin(), pos);
705214054f7SMichał Górny }
706214054f7SMichał Górny
707214054f7SMichał Górny m_set_names.push_back(set_name);
708214054f7SMichał Górny m_set_reg_nums.resize(m_set_reg_nums.size() + 1);
709214054f7SMichał Górny RegisterSet new_set = {set_name.AsCString(), nullptr, 0, nullptr};
710214054f7SMichał Górny m_sets.push_back(new_set);
711214054f7SMichał Górny return m_sets.size() - 1;
712214054f7SMichał Górny }
713214054f7SMichał Górny
714214054f7SMichał Górny uint32_t
ConvertRegisterKindToRegisterNumber(uint32_t kind,uint32_t num) const715214054f7SMichał Górny DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber(uint32_t kind,
716214054f7SMichał Górny uint32_t num) const {
717214054f7SMichał Górny reg_collection::const_iterator pos, end = m_regs.end();
718214054f7SMichał Górny for (pos = m_regs.begin(); pos != end; ++pos) {
719214054f7SMichał Górny if (pos->kinds[kind] == num)
720214054f7SMichał Górny return std::distance(m_regs.begin(), pos);
721214054f7SMichał Górny }
722214054f7SMichał Górny
723214054f7SMichał Górny return LLDB_INVALID_REGNUM;
724214054f7SMichał Górny }
725214054f7SMichał Górny
Clear()726214054f7SMichał Górny void DynamicRegisterInfo::Clear() {
727214054f7SMichał Górny m_regs.clear();
728214054f7SMichał Górny m_sets.clear();
729214054f7SMichał Górny m_set_reg_nums.clear();
730214054f7SMichał Górny m_set_names.clear();
731214054f7SMichał Górny m_value_regs_map.clear();
732214054f7SMichał Górny m_invalidate_regs_map.clear();
733214054f7SMichał Górny m_reg_data_byte_size = 0;
734214054f7SMichał Górny m_finalized = false;
735214054f7SMichał Górny }
736214054f7SMichał Górny
Dump() const737214054f7SMichał Górny void DynamicRegisterInfo::Dump() const {
738214054f7SMichał Górny StreamFile s(stdout, false);
739214054f7SMichał Górny const size_t num_regs = m_regs.size();
740214054f7SMichał Górny s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " registers:\n",
741214054f7SMichał Górny static_cast<const void *>(this), static_cast<uint64_t>(num_regs));
742214054f7SMichał Górny for (size_t i = 0; i < num_regs; ++i) {
743214054f7SMichał Górny s.Printf("[%3" PRIu64 "] name = %-10s", (uint64_t)i, m_regs[i].name);
744214054f7SMichał Górny s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s",
745214054f7SMichał Górny m_regs[i].byte_size, m_regs[i].byte_offset, m_regs[i].encoding,
746214054f7SMichał Górny FormatManager::GetFormatAsCString(m_regs[i].format));
747214054f7SMichał Górny if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM)
748214054f7SMichał Górny s.Printf(", process plugin = %3u",
749214054f7SMichał Górny m_regs[i].kinds[eRegisterKindProcessPlugin]);
750214054f7SMichał Górny if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
751214054f7SMichał Górny s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]);
752214054f7SMichał Górny if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
753214054f7SMichał Górny s.Printf(", ehframe = %3u", m_regs[i].kinds[eRegisterKindEHFrame]);
754214054f7SMichał Górny if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
755214054f7SMichał Górny s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);
756214054f7SMichał Górny if (m_regs[i].alt_name)
757214054f7SMichał Górny s.Printf(", alt-name = %s", m_regs[i].alt_name);
758214054f7SMichał Górny if (m_regs[i].value_regs) {
759214054f7SMichał Górny s.Printf(", value_regs = [ ");
760214054f7SMichał Górny for (size_t j = 0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j) {
761214054f7SMichał Górny s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name);
762214054f7SMichał Górny }
763214054f7SMichał Górny s.Printf("]");
764214054f7SMichał Górny }
765214054f7SMichał Górny if (m_regs[i].invalidate_regs) {
766214054f7SMichał Górny s.Printf(", invalidate_regs = [ ");
767214054f7SMichał Górny for (size_t j = 0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM;
768214054f7SMichał Górny ++j) {
769214054f7SMichał Górny s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name);
770214054f7SMichał Górny }
771214054f7SMichał Górny s.Printf("]");
772214054f7SMichał Górny }
773214054f7SMichał Górny s.EOL();
774214054f7SMichał Górny }
775214054f7SMichał Górny
776214054f7SMichał Górny const size_t num_sets = m_sets.size();
777214054f7SMichał Górny s.Printf("%p: DynamicRegisterInfo contains %" PRIu64 " register sets:\n",
778214054f7SMichał Górny static_cast<const void *>(this), static_cast<uint64_t>(num_sets));
779214054f7SMichał Górny for (size_t i = 0; i < num_sets; ++i) {
780214054f7SMichał Górny s.Printf("set[%" PRIu64 "] name = %s, regs = [", (uint64_t)i,
781214054f7SMichał Górny m_sets[i].name);
782214054f7SMichał Górny for (size_t idx = 0; idx < m_sets[i].num_registers; ++idx) {
783214054f7SMichał Górny s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name);
784214054f7SMichał Górny }
785214054f7SMichał Górny s.Printf("]\n");
786214054f7SMichał Górny }
787214054f7SMichał Górny }
788214054f7SMichał Górny
789214054f7SMichał Górny const lldb_private::RegisterInfo *
GetRegisterInfo(llvm::StringRef reg_name) const790214054f7SMichał Górny DynamicRegisterInfo::GetRegisterInfo(llvm::StringRef reg_name) const {
791214054f7SMichał Górny for (auto ®_info : m_regs)
792214054f7SMichał Górny if (reg_info.name == reg_name)
793214054f7SMichał Górny return ®_info;
794214054f7SMichał Górny return nullptr;
795214054f7SMichał Górny }
7961afda54fSMichał Górny
addSupplementaryRegister(std::vector<DynamicRegisterInfo::Register> & regs,DynamicRegisterInfo::Register new_reg_info)7971afda54fSMichał Górny void lldb_private::addSupplementaryRegister(
7981afda54fSMichał Górny std::vector<DynamicRegisterInfo::Register> ®s,
7991afda54fSMichał Górny DynamicRegisterInfo::Register new_reg_info) {
8001afda54fSMichał Górny assert(!new_reg_info.value_regs.empty());
8011afda54fSMichał Górny const uint32_t reg_num = regs.size();
8021afda54fSMichał Górny regs.push_back(new_reg_info);
8031afda54fSMichał Górny
8041afda54fSMichał Górny std::map<uint32_t, std::vector<uint32_t>> new_invalidates;
8051afda54fSMichał Górny for (uint32_t value_reg : new_reg_info.value_regs) {
8061afda54fSMichał Górny // copy value_regs to invalidate_regs
8071afda54fSMichał Górny new_invalidates[reg_num].push_back(value_reg);
8081afda54fSMichał Górny
8091afda54fSMichał Górny // copy invalidate_regs from the parent register
8101afda54fSMichał Górny llvm::append_range(new_invalidates[reg_num],
8111afda54fSMichał Górny regs[value_reg].invalidate_regs);
8121afda54fSMichał Górny
8131afda54fSMichał Górny // add reverse invalidate entries
8141afda54fSMichał Górny for (uint32_t x : new_invalidates[reg_num])
8151afda54fSMichał Górny new_invalidates[x].push_back(reg_num);
8161afda54fSMichał Górny }
8171afda54fSMichał Górny
8181afda54fSMichał Górny for (const auto &x : new_invalidates)
8191afda54fSMichał Górny llvm::append_range(regs[x.first].invalidate_regs, x.second);
8201afda54fSMichał Górny }
821