xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/DataFormatters/FormattersHelpers.h"
12 #include "lldb/ValueObject/ValueObject.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 
LibcxxStdSliceArraySummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)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   llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
66 
67 private:
68   /// A non-owning pointer to slice_array.__vp_.
69   ValueObject *m_start = nullptr;
70   /// slice_array.__size_.
71   size_t m_size = 0;
72   /// slice_array.__stride_.
73   size_t m_stride = 0;
74   /// The type of slice_array's template argument T.
75   CompilerType m_element_type;
76   /// The sizeof slice_array's template argument T.
77   uint32_t m_element_size = 0;
78 };
79 
80 } // namespace formatters
81 } // namespace lldb_private
82 
83 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)84     LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
85     : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
86   if (valobj_sp)
87     Update();
88 }
89 
90 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
~LibcxxStdSliceArraySyntheticFrontEnd()91     ~LibcxxStdSliceArraySyntheticFrontEnd() {
92   // these need to stay around because they are child objects who will follow
93   // their parent's life cycle
94   // delete m_start;
95 }
96 
97 llvm::Expected<uint32_t> lldb_private::formatters::
CalculateNumChildren()98     LibcxxStdSliceArraySyntheticFrontEnd::CalculateNumChildren() {
99   return m_size;
100 }
101 
102 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx)103 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::GetChildAtIndex(
104     uint32_t idx) {
105   if (!m_start)
106     return lldb::ValueObjectSP();
107 
108   uint64_t offset = idx * m_stride * m_element_size;
109   offset = offset + m_start->GetValueAsUnsigned(0);
110   StreamString name;
111   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
112   return CreateValueObjectFromAddress(name.GetString(), offset,
113                                       m_backend.GetExecutionContextRef(),
114                                       m_element_type);
115 }
116 
117 lldb::ChildCacheState
Update()118 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::Update() {
119   m_start = nullptr;
120 
121   CompilerType type = m_backend.GetCompilerType();
122   if (type.GetNumTemplateArguments() == 0)
123     return ChildCacheState::eRefetch;
124 
125   m_element_type = type.GetTypeTemplateArgument(0);
126   if (std::optional<uint64_t> size =
127           llvm::expectedToOptional(m_element_type.GetByteSize(nullptr)))
128     m_element_size = *size;
129 
130   if (m_element_size == 0)
131     return ChildCacheState::eRefetch;
132 
133   ValueObjectSP start = m_backend.GetChildMemberWithName("__vp_");
134   ValueObjectSP size = m_backend.GetChildMemberWithName("__size_");
135   ValueObjectSP stride = m_backend.GetChildMemberWithName("__stride_");
136 
137   if (!start || !size || !stride)
138     return ChildCacheState::eRefetch;
139 
140   m_start = start.get();
141   m_size = size->GetValueAsUnsigned(0);
142   m_stride = stride->GetValueAsUnsigned(0);
143 
144   return ChildCacheState::eRefetch;
145 }
146 
147 llvm::Expected<size_t>
148 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)149     GetIndexOfChildWithName(ConstString name) {
150   if (!m_start)
151     return llvm::createStringError("Type has no child named '%s'",
152                                    name.AsCString());
153   auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());
154   if (!optional_idx) {
155     return llvm::createStringError("Type has no child named '%s'",
156                                    name.AsCString());
157   }
158   return *optional_idx;
159 }
160 
161 lldb_private::SyntheticChildrenFrontEnd *
LibcxxStdSliceArraySyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)162 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEndCreator(
163     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
164   if (!valobj_sp)
165     return nullptr;
166   return new LibcxxStdSliceArraySyntheticFrontEnd(valobj_sp);
167 }
168