xref: /NextBSD/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxVector.cpp (revision 84d351007654069f9643c8e4b4802a7f5f08ee42)
1 //===-- LibCxxVector.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/DataFormatters/CXXFormatterFunctions.h"
11 
12 #include "lldb/Core/ConstString.h"
13 #include "lldb/Core/ValueObject.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 using namespace lldb_private::formatters;
18 
19 namespace lldb_private {
20     namespace formatters {
21         class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
22         {
23         public:
24             LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
25 
26             virtual size_t
27             CalculateNumChildren ();
28 
29             virtual lldb::ValueObjectSP
30             GetChildAtIndex (size_t idx);
31 
32             virtual bool
33             Update();
34 
35             virtual bool
36             MightHaveChildren ();
37 
38             virtual size_t
39             GetIndexOfChildWithName (const ConstString &name);
40 
41             virtual
42             ~LibcxxStdVectorSyntheticFrontEnd ();
43         private:
44             ValueObject* m_start;
45             ValueObject* m_finish;
46             ClangASTType m_element_type;
47             uint32_t m_element_size;
48             std::map<size_t,lldb::ValueObjectSP> m_children;
49         };
50     }
51 }
52 
LibcxxStdVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)53 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
54 SyntheticChildrenFrontEnd(*valobj_sp.get()),
55 m_start(NULL),
56 m_finish(NULL),
57 m_element_type(),
58 m_element_size(0),
59 m_children()
60 {
61     if (valobj_sp)
62         Update();
63 }
64 
65 size_t
CalculateNumChildren()66 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
67 {
68     if (!m_start || !m_finish)
69         return 0;
70     uint64_t start_val = m_start->GetValueAsUnsigned(0);
71     uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
72 
73     if (start_val == 0 || finish_val == 0)
74         return 0;
75 
76     if (start_val >= finish_val)
77         return 0;
78 
79     size_t num_children = (finish_val - start_val);
80     if (num_children % m_element_size)
81         return 0;
82     return num_children/m_element_size;
83 }
84 
85 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)86 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
87 {
88     if (!m_start || !m_finish)
89         return lldb::ValueObjectSP();
90 
91     auto cached = m_children.find(idx);
92     if (cached != m_children.end())
93         return cached->second;
94 
95     uint64_t offset = idx * m_element_size;
96     offset = offset + m_start->GetValueAsUnsigned(0);
97     StreamString name;
98     name.Printf("[%" PRIu64 "]", (uint64_t)idx);
99     ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
100     m_children[idx] = child_sp;
101     return child_sp;
102 }
103 
104 bool
Update()105 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
106 {
107     m_start = m_finish = NULL;
108     m_children.clear();
109     ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
110     if (!data_type_finder_sp)
111         return false;
112     data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
113     if (!data_type_finder_sp)
114         return false;
115     m_element_type = data_type_finder_sp->GetClangType().GetPointeeType();
116     m_element_size = m_element_type.GetByteSize(nullptr);
117 
118     if (m_element_size > 0)
119     {
120         // store raw pointers or end up with a circular dependency
121         m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
122         m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
123     }
124     return false;
125 }
126 
127 bool
MightHaveChildren()128 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
129 {
130     return true;
131 }
132 
133 size_t
GetIndexOfChildWithName(const ConstString & name)134 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
135 {
136     if (!m_start || !m_finish)
137         return UINT32_MAX;
138     return ExtractIndexFromString(name.GetCString());
139 }
140 
~LibcxxStdVectorSyntheticFrontEnd()141 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
142 {
143     // these need to stay around because they are child objects who will follow their parent's life cycle
144     // delete m_start;
145     // delete m_finish;
146 }
147 
148 lldb_private::SyntheticChildrenFrontEnd*
LibcxxStdVectorSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)149 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
150 {
151     if (!valobj_sp)
152         return NULL;
153     return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
154 }
155 
156