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