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