xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
1 //===-- LibCxxSliceArray.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 
22 bool LibcxxStdSliceArraySummaryProvider(ValueObject &valobj, Stream &stream,
23                                         const TypeSummaryOptions &options) {
24   ValueObjectSP obj = valobj.GetNonSyntheticValue();
25   if (!obj)
26     return false;
27 
28   ValueObjectSP ptr_sp = obj->GetChildMemberWithName("__size_");
29   if (!ptr_sp)
30     return false;
31   const size_t size = ptr_sp->GetValueAsUnsigned(0);
32 
33   ptr_sp = obj->GetChildMemberWithName("__stride_");
34   if (!ptr_sp)
35     return false;
36   const size_t stride = ptr_sp->GetValueAsUnsigned(0);
37 
38   stream.Printf("stride=%zu size=%zu", stride, size);
39 
40   return true;
41 }
42 
43 /// Data formatter for libc++'s std::slice_array.
44 ///
45 /// A slice_array is created by using:
46 ///   operator[](std::slice slicearr);
47 /// and std::slice is created by:
48 ///   slice(std::size_t start, std::size_t size, std::size_t stride);
49 /// The std::slice_array has the following members:
50 /// - __vp_ points to std::valarray::__begin_ + @a start
51 /// - __size_ is @a size
52 /// - __stride_is @a stride
53 class LibcxxStdSliceArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
54 public:
55   LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
56 
57   ~LibcxxStdSliceArraySyntheticFrontEnd() override;
58 
59   llvm::Expected<uint32_t> CalculateNumChildren() override;
60 
61   lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
62 
63   lldb::ChildCacheState Update() override;
64 
65   bool MightHaveChildren() override;
66 
67   size_t GetIndexOfChildWithName(ConstString name) override;
68 
69 private:
70   /// A non-owning pointer to slice_array.__vp_.
71   ValueObject *m_start = nullptr;
72   /// slice_array.__size_.
73   size_t m_size = 0;
74   /// slice_array.__stride_.
75   size_t m_stride = 0;
76   /// The type of slice_array's template argument T.
77   CompilerType m_element_type;
78   /// The sizeof slice_array's template argument T.
79   uint32_t m_element_size = 0;
80 };
81 
82 } // namespace formatters
83 } // namespace lldb_private
84 
85 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
86     LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
87     : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
88   if (valobj_sp)
89     Update();
90 }
91 
92 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
93     ~LibcxxStdSliceArraySyntheticFrontEnd() {
94   // these need to stay around because they are child objects who will follow
95   // their parent's life cycle
96   // delete m_start;
97 }
98 
99 llvm::Expected<uint32_t> lldb_private::formatters::
100     LibcxxStdSliceArraySyntheticFrontEnd::CalculateNumChildren() {
101   return m_size;
102 }
103 
104 lldb::ValueObjectSP
105 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::GetChildAtIndex(
106     uint32_t idx) {
107   if (!m_start)
108     return lldb::ValueObjectSP();
109 
110   uint64_t offset = idx * m_stride * m_element_size;
111   offset = offset + m_start->GetValueAsUnsigned(0);
112   StreamString name;
113   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
114   return CreateValueObjectFromAddress(name.GetString(), offset,
115                                       m_backend.GetExecutionContextRef(),
116                                       m_element_type);
117 }
118 
119 lldb::ChildCacheState
120 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::Update() {
121   m_start = nullptr;
122 
123   CompilerType type = m_backend.GetCompilerType();
124   if (type.GetNumTemplateArguments() == 0)
125     return ChildCacheState::eRefetch;
126 
127   m_element_type = type.GetTypeTemplateArgument(0);
128   if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr))
129     m_element_size = *size;
130 
131   if (m_element_size == 0)
132     return ChildCacheState::eRefetch;
133 
134   ValueObjectSP start = m_backend.GetChildMemberWithName("__vp_");
135   ValueObjectSP size = m_backend.GetChildMemberWithName("__size_");
136   ValueObjectSP stride = m_backend.GetChildMemberWithName("__stride_");
137 
138   if (!start || !size || !stride)
139     return ChildCacheState::eRefetch;
140 
141   m_start = start.get();
142   m_size = size->GetValueAsUnsigned(0);
143   m_stride = stride->GetValueAsUnsigned(0);
144 
145   return ChildCacheState::eRefetch;
146 }
147 
148 bool lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
149     MightHaveChildren() {
150   return true;
151 }
152 
153 size_t lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
154     GetIndexOfChildWithName(ConstString name) {
155   if (!m_start)
156     return std::numeric_limits<size_t>::max();
157   return ExtractIndexFromString(name.GetCString());
158 }
159 
160 lldb_private::SyntheticChildrenFrontEnd *
161 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEndCreator(
162     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
163   if (!valobj_sp)
164     return nullptr;
165   return new LibcxxStdSliceArraySyntheticFrontEnd(valobj_sp);
166 }
167