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