1//===-- DynamicRegisterInfo.cpp ----------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-python.h"
11
12#include "DynamicRegisterInfo.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Interpreter/Args.h"
19
20#ifndef LLDB_DISABLE_PYTHON
21#include "lldb/Interpreter/PythonDataObjects.h"
22#endif
23
24using namespace lldb;
25using namespace lldb_private;
26
27DynamicRegisterInfo::DynamicRegisterInfo () :
28    m_regs (),
29    m_sets (),
30    m_set_reg_nums (),
31    m_set_names (),
32    m_reg_data_byte_size (0)
33{
34}
35
36DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
37    m_regs (),
38    m_sets (),
39    m_set_reg_nums (),
40    m_set_names (),
41    m_reg_data_byte_size (0)
42{
43    SetRegisterInfo (dict);
44}
45
46DynamicRegisterInfo::~DynamicRegisterInfo ()
47{
48}
49
50
51size_t
52DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
53{
54#ifndef LLDB_DISABLE_PYTHON
55    PythonList sets (dict.GetItemForKey("sets"));
56    if (sets)
57    {
58        const uint32_t num_sets = sets.GetSize();
59        for (uint32_t i=0; i<num_sets; ++i)
60        {
61            PythonString py_set_name(sets.GetItemAtIndex(i));
62            ConstString set_name;
63            if (py_set_name)
64                set_name.SetCString(py_set_name.GetString());
65            if (set_name)
66            {
67                RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
68                m_sets.push_back (new_set);
69            }
70            else
71            {
72                Clear();
73                return 0;
74            }
75        }
76        m_set_reg_nums.resize(m_sets.size());
77    }
78    PythonList regs (dict.GetItemForKey("registers"));
79    if (regs)
80    {
81        const uint32_t num_regs = regs.GetSize();
82        PythonString name_pystr("name");
83        PythonString altname_pystr("alt-name");
84        PythonString bitsize_pystr("bitsize");
85        PythonString offset_pystr("offset");
86        PythonString encoding_pystr("encoding");
87        PythonString format_pystr("format");
88        PythonString set_pystr("set");
89        PythonString gcc_pystr("gcc");
90        PythonString dwarf_pystr("dwarf");
91        PythonString generic_pystr("generic");
92        for (uint32_t i=0; i<num_regs; ++i)
93        {
94            PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
95            if (reg_info_dict)
96            {
97                // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
98                RegisterInfo reg_info;
99                bzero (&reg_info, sizeof(reg_info));
100
101                reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
102                if (reg_info.name == NULL)
103                {
104                    Clear();
105                    return 0;
106                }
107
108                reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString();
109
110                reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX);
111
112                if (reg_info.byte_offset == UINT32_MAX)
113                {
114                    Clear();
115                    return 0;
116                }
117                reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
118
119                if (reg_info.byte_size == 0)
120                {
121                    Clear();
122                    return 0;
123                }
124
125                const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
126                if (format_cstr)
127                {
128                    if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
129                    {
130                        Clear();
131                        return 0;
132                    }
133                }
134                else
135                    reg_info.format = eFormatHex;
136
137                const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
138                if (encoding_cstr)
139                    reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
140                else
141                    reg_info.encoding = eEncodingUint;
142
143                const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
144                if (set >= m_sets.size())
145                {
146                    Clear();
147                    return 0;
148                }
149
150                reg_info.kinds[lldb::eRegisterKindLLDB]    = i;
151                reg_info.kinds[lldb::eRegisterKindGDB]     = i;
152                reg_info.kinds[lldb::eRegisterKindGCC]     = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
153                reg_info.kinds[lldb::eRegisterKindDWARF]   = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
154                reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (reg_info_dict.GetItemForKeyAsString(generic_pystr));
155                const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
156                if (m_reg_data_byte_size < end_reg_offset)
157                    m_reg_data_byte_size = end_reg_offset;
158
159                m_regs.push_back (reg_info);
160                m_set_reg_nums[set].push_back(i);
161
162            }
163            else
164            {
165                Clear();
166                return 0;
167            }
168        }
169        Finalize ();
170    }
171#endif
172    return 0;
173}
174
175
176void
177DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
178                                  ConstString &reg_name,
179                                  ConstString &reg_alt_name,
180                                  ConstString &set_name)
181{
182    const uint32_t reg_num = m_regs.size();
183    reg_info.name = reg_name.AsCString();
184    assert (reg_info.name);
185    reg_info.alt_name = reg_alt_name.AsCString(NULL);
186    m_regs.push_back (reg_info);
187    uint32_t set = GetRegisterSetIndexByName (set_name, true);
188    assert (set < m_sets.size());
189    assert (set < m_set_reg_nums.size());
190    assert (set < m_set_names.size());
191    m_set_reg_nums[set].push_back(reg_num);
192    size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
193    if (m_reg_data_byte_size < end_reg_offset)
194        m_reg_data_byte_size = end_reg_offset;
195}
196
197void
198DynamicRegisterInfo::Finalize ()
199{
200    for (uint32_t set = 0; set < m_sets.size(); ++set)
201    {
202        assert (m_sets.size() == m_set_reg_nums.size());
203        m_sets[set].num_registers = m_set_reg_nums[set].size();
204        m_sets[set].registers = &m_set_reg_nums[set][0];
205    }
206}
207
208size_t
209DynamicRegisterInfo::GetNumRegisters() const
210{
211    return m_regs.size();
212}
213
214size_t
215DynamicRegisterInfo::GetNumRegisterSets() const
216{
217    return m_sets.size();
218}
219
220size_t
221DynamicRegisterInfo::GetRegisterDataByteSize() const
222{
223    return m_reg_data_byte_size;
224}
225
226const RegisterInfo *
227DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) const
228{
229    if (i < m_regs.size())
230        return &m_regs[i];
231    return NULL;
232}
233
234const RegisterSet *
235DynamicRegisterInfo::GetRegisterSet (uint32_t i) const
236{
237    if (i < m_sets.size())
238        return &m_sets[i];
239    return NULL;
240}
241
242uint32_t
243DynamicRegisterInfo::GetRegisterSetIndexByName (ConstString &set_name, bool can_create)
244{
245    name_collection::iterator pos, end = m_set_names.end();
246    for (pos = m_set_names.begin(); pos != end; ++pos)
247    {
248        if (*pos == set_name)
249            return std::distance (m_set_names.begin(), pos);
250    }
251
252    m_set_names.push_back(set_name);
253    m_set_reg_nums.resize(m_set_reg_nums.size()+1);
254    RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
255    m_sets.push_back (new_set);
256    return m_sets.size() - 1;
257}
258
259uint32_t
260DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
261{
262    reg_collection::const_iterator pos, end = m_regs.end();
263    for (pos = m_regs.begin(); pos != end; ++pos)
264    {
265        if (pos->kinds[kind] == num)
266            return std::distance (m_regs.begin(), pos);
267    }
268
269    return LLDB_INVALID_REGNUM;
270}
271
272void
273DynamicRegisterInfo::Clear()
274{
275    m_regs.clear();
276    m_sets.clear();
277    m_set_reg_nums.clear();
278    m_set_names.clear();
279}
280