1*0fca6ea1SDimitry Andric //===-- LibCxxValarray.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 class LibcxxStdValarraySyntheticFrontEnd : public SyntheticChildrenFrontEnd { 22*0fca6ea1SDimitry Andric public: 23*0fca6ea1SDimitry Andric LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 24*0fca6ea1SDimitry Andric 25*0fca6ea1SDimitry Andric ~LibcxxStdValarraySyntheticFrontEnd() override; 26*0fca6ea1SDimitry Andric 27*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 28*0fca6ea1SDimitry Andric 29*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 30*0fca6ea1SDimitry Andric 31*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 32*0fca6ea1SDimitry Andric 33*0fca6ea1SDimitry Andric bool MightHaveChildren() override; 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 36*0fca6ea1SDimitry Andric 37*0fca6ea1SDimitry Andric private: 38*0fca6ea1SDimitry Andric /// A non-owning pointer to valarray's __begin_ member. 39*0fca6ea1SDimitry Andric ValueObject *m_start = nullptr; 40*0fca6ea1SDimitry Andric /// A non-owning pointer to valarray's __end_ member. 41*0fca6ea1SDimitry Andric ValueObject *m_finish = nullptr; 42*0fca6ea1SDimitry Andric /// The type of valarray's template argument T. 43*0fca6ea1SDimitry Andric CompilerType m_element_type; 44*0fca6ea1SDimitry Andric /// The sizeof valarray's template argument T. 45*0fca6ea1SDimitry Andric uint32_t m_element_size = 0; 46*0fca6ea1SDimitry Andric }; 47*0fca6ea1SDimitry Andric 48*0fca6ea1SDimitry Andric } // namespace formatters 49*0fca6ea1SDimitry Andric } // namespace lldb_private 50*0fca6ea1SDimitry Andric 51*0fca6ea1SDimitry Andric lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: 52*0fca6ea1SDimitry Andric LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 53*0fca6ea1SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() { 54*0fca6ea1SDimitry Andric if (valobj_sp) 55*0fca6ea1SDimitry Andric Update(); 56*0fca6ea1SDimitry Andric } 57*0fca6ea1SDimitry Andric 58*0fca6ea1SDimitry Andric lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: 59*0fca6ea1SDimitry Andric ~LibcxxStdValarraySyntheticFrontEnd() { 60*0fca6ea1SDimitry Andric // these need to stay around because they are child objects who will follow 61*0fca6ea1SDimitry Andric // their parent's life cycle 62*0fca6ea1SDimitry Andric // delete m_start; 63*0fca6ea1SDimitry Andric // delete m_finish; 64*0fca6ea1SDimitry Andric } 65*0fca6ea1SDimitry Andric 66*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters:: 67*0fca6ea1SDimitry Andric LibcxxStdValarraySyntheticFrontEnd::CalculateNumChildren() { 68*0fca6ea1SDimitry Andric if (!m_start || !m_finish) 69*0fca6ea1SDimitry Andric return 0; 70*0fca6ea1SDimitry Andric uint64_t start_val = m_start->GetValueAsUnsigned(0); 71*0fca6ea1SDimitry Andric uint64_t finish_val = m_finish->GetValueAsUnsigned(0); 72*0fca6ea1SDimitry Andric 73*0fca6ea1SDimitry Andric if (start_val == 0 || finish_val == 0) 74*0fca6ea1SDimitry Andric return 0; 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric if (start_val >= finish_val) 77*0fca6ea1SDimitry Andric return 0; 78*0fca6ea1SDimitry Andric 79*0fca6ea1SDimitry Andric size_t num_children = (finish_val - start_val); 80*0fca6ea1SDimitry Andric if (num_children % m_element_size) 81*0fca6ea1SDimitry Andric return 0; 82*0fca6ea1SDimitry Andric return num_children / m_element_size; 83*0fca6ea1SDimitry Andric } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric lldb::ValueObjectSP 86*0fca6ea1SDimitry Andric lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::GetChildAtIndex( 87*0fca6ea1SDimitry Andric uint32_t idx) { 88*0fca6ea1SDimitry Andric if (!m_start || !m_finish) 89*0fca6ea1SDimitry Andric return lldb::ValueObjectSP(); 90*0fca6ea1SDimitry Andric 91*0fca6ea1SDimitry Andric uint64_t offset = idx * m_element_size; 92*0fca6ea1SDimitry Andric offset = offset + m_start->GetValueAsUnsigned(0); 93*0fca6ea1SDimitry Andric StreamString name; 94*0fca6ea1SDimitry Andric name.Printf("[%" PRIu64 "]", (uint64_t)idx); 95*0fca6ea1SDimitry Andric return CreateValueObjectFromAddress(name.GetString(), offset, 96*0fca6ea1SDimitry Andric m_backend.GetExecutionContextRef(), 97*0fca6ea1SDimitry Andric m_element_type); 98*0fca6ea1SDimitry Andric } 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric lldb::ChildCacheState 101*0fca6ea1SDimitry Andric lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::Update() { 102*0fca6ea1SDimitry Andric m_start = m_finish = nullptr; 103*0fca6ea1SDimitry Andric 104*0fca6ea1SDimitry Andric CompilerType type = m_backend.GetCompilerType(); 105*0fca6ea1SDimitry Andric if (type.GetNumTemplateArguments() == 0) 106*0fca6ea1SDimitry Andric return ChildCacheState::eRefetch; 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric m_element_type = type.GetTypeTemplateArgument(0); 109*0fca6ea1SDimitry Andric if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) 110*0fca6ea1SDimitry Andric m_element_size = *size; 111*0fca6ea1SDimitry Andric 112*0fca6ea1SDimitry Andric if (m_element_size == 0) 113*0fca6ea1SDimitry Andric return ChildCacheState::eRefetch; 114*0fca6ea1SDimitry Andric 115*0fca6ea1SDimitry Andric ValueObjectSP start = m_backend.GetChildMemberWithName("__begin_"); 116*0fca6ea1SDimitry Andric ValueObjectSP finish = m_backend.GetChildMemberWithName("__end_"); 117*0fca6ea1SDimitry Andric 118*0fca6ea1SDimitry Andric if (!start || !finish) 119*0fca6ea1SDimitry Andric return ChildCacheState::eRefetch; 120*0fca6ea1SDimitry Andric 121*0fca6ea1SDimitry Andric m_start = start.get(); 122*0fca6ea1SDimitry Andric m_finish = finish.get(); 123*0fca6ea1SDimitry Andric 124*0fca6ea1SDimitry Andric return ChildCacheState::eRefetch; 125*0fca6ea1SDimitry Andric } 126*0fca6ea1SDimitry Andric 127*0fca6ea1SDimitry Andric bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: 128*0fca6ea1SDimitry Andric MightHaveChildren() { 129*0fca6ea1SDimitry Andric return true; 130*0fca6ea1SDimitry Andric } 131*0fca6ea1SDimitry Andric 132*0fca6ea1SDimitry Andric size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd:: 133*0fca6ea1SDimitry Andric GetIndexOfChildWithName(ConstString name) { 134*0fca6ea1SDimitry Andric if (!m_start || !m_finish) 135*0fca6ea1SDimitry Andric return std::numeric_limits<size_t>::max(); 136*0fca6ea1SDimitry Andric return ExtractIndexFromString(name.GetCString()); 137*0fca6ea1SDimitry Andric } 138*0fca6ea1SDimitry Andric 139*0fca6ea1SDimitry Andric lldb_private::SyntheticChildrenFrontEnd * 140*0fca6ea1SDimitry Andric lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator( 141*0fca6ea1SDimitry Andric CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 142*0fca6ea1SDimitry Andric if (!valobj_sp) 143*0fca6ea1SDimitry Andric return nullptr; 144*0fca6ea1SDimitry Andric return new LibcxxStdValarraySyntheticFrontEnd(valobj_sp); 145*0fca6ea1SDimitry Andric } 146