1 | //===-- LibCxxValarray.cpp ------------------------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "LibCxx.h" |
10 | |
11 | #include "lldb/Core/ValueObject.h" |
12 | #include "lldb/DataFormatters/FormattersHelpers.h" |
13 | #include <optional> |
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 LibcxxStdValarraySyntheticFrontEnd : public SyntheticChildrenFrontEnd { |
22 | public: |
23 | LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); |
24 | |
25 | ~LibcxxStdValarraySyntheticFrontEnd() override; |
26 | |
27 | llvm::Expected<uint32_t> CalculateNumChildren() override; |
28 | |
29 | lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; |
30 | |
31 | lldb::ChildCacheState Update() override; |
32 | |
33 | bool MightHaveChildren() override; |
34 | |
35 | size_t GetIndexOfChildWithName(ConstString name) override; |
36 | |
37 | private: |
38 | /// A non-owning pointer to valarray's __begin_ member. |
39 | ValueObject *m_start = nullptr; |
40 | /// A non-owning pointer to valarray's __end_ member. |
41 | ValueObject *m_finish = nullptr; |
42 | /// The type of valarray's template argument T. |
43 | CompilerType m_element_type; |
44 | /// The sizeof valarray's template argument T. |
45 | uint32_t m_element_size = 0; |
46 | }; |
47 | |
48 | } // namespace formatters |
49 | } // namespace lldb_private |
50 | |
51 | lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: |
52 | LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) |
53 | : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() { |
54 | if (valobj_sp) |
55 | Update(); |
56 | } |
57 | |
58 | lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: |
59 | ~LibcxxStdValarraySyntheticFrontEnd() { |
60 | // these need to stay around because they are child objects who will follow |
61 | // their parent's life cycle |
62 | // delete m_start; |
63 | // delete m_finish; |
64 | } |
65 | |
66 | llvm::Expected<uint32_t> lldb_private::formatters:: |
67 | LibcxxStdValarraySyntheticFrontEnd::CalculateNumChildren() { |
68 | if (!m_start || !m_finish) |
69 | return 0; |
70 | uint64_t start_val = m_start->GetValueAsUnsigned(fail_value: 0); |
71 | uint64_t finish_val = m_finish->GetValueAsUnsigned(fail_value: 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 |
86 | lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::GetChildAtIndex( |
87 | uint32_t idx) { |
88 | if (!m_start || !m_finish) |
89 | return lldb::ValueObjectSP(); |
90 | |
91 | uint64_t offset = idx * m_element_size; |
92 | offset = offset + m_start->GetValueAsUnsigned(fail_value: 0); |
93 | StreamString name; |
94 | name.Printf(format: "[%"PRIu64 "]", (uint64_t)idx); |
95 | return CreateValueObjectFromAddress(name: name.GetString(), address: offset, |
96 | exe_ctx: m_backend.GetExecutionContextRef(), |
97 | type: m_element_type); |
98 | } |
99 | |
100 | lldb::ChildCacheState |
101 | lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::Update() { |
102 | m_start = m_finish = nullptr; |
103 | |
104 | CompilerType type = m_backend.GetCompilerType(); |
105 | if (type.GetNumTemplateArguments() == 0) |
106 | return ChildCacheState::eRefetch; |
107 | |
108 | m_element_type = type.GetTypeTemplateArgument(idx: 0); |
109 | if (std::optional<uint64_t> size = m_element_type.GetByteSize(exe_scope: nullptr)) |
110 | m_element_size = *size; |
111 | |
112 | if (m_element_size == 0) |
113 | return ChildCacheState::eRefetch; |
114 | |
115 | ValueObjectSP start = m_backend.GetChildMemberWithName(name: "__begin_"); |
116 | ValueObjectSP finish = m_backend.GetChildMemberWithName(name: "__end_"); |
117 | |
118 | if (!start || !finish) |
119 | return ChildCacheState::eRefetch; |
120 | |
121 | m_start = start.get(); |
122 | m_finish = finish.get(); |
123 | |
124 | return ChildCacheState::eRefetch; |
125 | } |
126 | |
127 | bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: |
128 | MightHaveChildren() { |
129 | return true; |
130 | } |
131 | |
132 | size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: |
133 | GetIndexOfChildWithName(ConstString name) { |
134 | if (!m_start || !m_finish) |
135 | return std::numeric_limits<size_t>::max(); |
136 | return ExtractIndexFromString(item_name: name.GetCString()); |
137 | } |
138 | |
139 | lldb_private::SyntheticChildrenFrontEnd * |
140 | lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator( |
141 | CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { |
142 | if (!valobj_sp) |
143 | return nullptr; |
144 | return new LibcxxStdValarraySyntheticFrontEnd(valobj_sp); |
145 | } |
146 |