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