168 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "LibCxx.h"10 11#include "lldb/DataFormatters/FormattersHelpers.h"12#include "lldb/ValueObject/ValueObject.h"13#include <optional>14 15using namespace lldb;16using namespace lldb_private;17using namespace lldb_private::formatters;18 19namespace lldb_private {20namespace formatters {21 22bool 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 start51/// - __size_ is @a size52/// - __stride_is @a stride53class LibcxxStdSliceArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {54public: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 67private: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 formatters81} // namespace lldb_private82 83lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::84 LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)85 : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {86 if (valobj_sp)87 Update();88}89 90lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::91 ~LibcxxStdSliceArraySyntheticFrontEnd() {92 // these need to stay around because they are child objects who will follow93 // their parent's life cycle94 // delete m_start;95}96 97llvm::Expected<uint32_t> lldb_private::formatters::98 LibcxxStdSliceArraySyntheticFrontEnd::CalculateNumChildren() {99 return m_size;100}101 102lldb::ValueObjectSP103lldb_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 117lldb::ChildCacheState118lldb_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 147llvm::Expected<size_t>148lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::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 161lldb_private::SyntheticChildrenFrontEnd *162lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEndCreator(163 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {164 if (!valobj_sp)165 return nullptr;166 return new LibcxxStdSliceArraySyntheticFrontEnd(valobj_sp);167}168