xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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::
LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)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::
~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::
CalculateNumChildren()67     LibcxxStdValarraySyntheticFrontEnd::CalculateNumChildren() {
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(uint32_t idx)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(0);
93   StreamString name;
94   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
95   return CreateValueObjectFromAddress(name.GetString(), offset,
96                                       m_backend.GetExecutionContextRef(),
97                                       m_element_type);
98 }
99 
100 lldb::ChildCacheState
Update()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(0);
109   if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr))
110     m_element_size = *size;
111 
112   if (m_element_size == 0)
113     return ChildCacheState::eRefetch;
114 
115   ValueObjectSP start = m_backend.GetChildMemberWithName("__begin_");
116   ValueObjectSP finish = m_backend.GetChildMemberWithName("__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::
MightHaveChildren()128     MightHaveChildren() {
129   return true;
130 }
131 
132 size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)133     GetIndexOfChildWithName(ConstString name) {
134   if (!m_start || !m_finish)
135     return std::numeric_limits<size_t>::max();
136   return ExtractIndexFromString(name.GetCString());
137 }
138 
139 lldb_private::SyntheticChildrenFrontEnd *
LibcxxStdValarraySyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)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