1*81ad6265SDimitry Andric //===-- LibCxxSpan.cpp ----------------------------------------------------===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #include "LibCxx.h" 10*81ad6265SDimitry Andric 11*81ad6265SDimitry Andric #include "lldb/Core/ValueObject.h" 12*81ad6265SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h" 13*81ad6265SDimitry Andric #include "lldb/Utility/ConstString.h" 14*81ad6265SDimitry Andric #include "llvm/ADT/APSInt.h" 15*81ad6265SDimitry Andric 16*81ad6265SDimitry Andric using namespace lldb; 17*81ad6265SDimitry Andric using namespace lldb_private; 18*81ad6265SDimitry Andric using namespace lldb_private::formatters; 19*81ad6265SDimitry Andric 20*81ad6265SDimitry Andric namespace lldb_private { 21*81ad6265SDimitry Andric namespace formatters { 22*81ad6265SDimitry Andric 23*81ad6265SDimitry Andric class LibcxxStdSpanSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 24*81ad6265SDimitry Andric public: 25*81ad6265SDimitry Andric LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 26*81ad6265SDimitry Andric 27*81ad6265SDimitry Andric ~LibcxxStdSpanSyntheticFrontEnd() override = default; 28*81ad6265SDimitry Andric 29*81ad6265SDimitry Andric size_t CalculateNumChildren() override; 30*81ad6265SDimitry Andric 31*81ad6265SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 32*81ad6265SDimitry Andric 33*81ad6265SDimitry Andric /// Determines properties of the std::span<> associated with this object 34*81ad6265SDimitry Andric // 35*81ad6265SDimitry Andric // std::span can either be instantiated with a compile-time known 36*81ad6265SDimitry Andric // extent or a std::dynamic_extent (this is the default if only the 37*81ad6265SDimitry Andric // type template argument is provided). The layout of std::span 38*81ad6265SDimitry Andric // depends on whether the extent is dynamic or not. For static 39*81ad6265SDimitry Andric // extents (e.g., std::span<int, 9>): 40*81ad6265SDimitry Andric // 41*81ad6265SDimitry Andric // (std::__1::span<const int, 9>) s = { 42*81ad6265SDimitry Andric // __data = 0x000000016fdff494 43*81ad6265SDimitry Andric // } 44*81ad6265SDimitry Andric // 45*81ad6265SDimitry Andric // For dynamic extents, e.g., std::span<int>, the layout is: 46*81ad6265SDimitry Andric // 47*81ad6265SDimitry Andric // (std::__1::span<const int, 18446744073709551615>) s = { 48*81ad6265SDimitry Andric // __data = 0x000000016fdff494 49*81ad6265SDimitry Andric // __size = 6 50*81ad6265SDimitry Andric // } 51*81ad6265SDimitry Andric // 52*81ad6265SDimitry Andric // This function checks for a '__size' member to determine the number 53*81ad6265SDimitry Andric // of elements in the span. If no such member exists, we get the size 54*81ad6265SDimitry Andric // from the only other place it can be: the template argument. 55*81ad6265SDimitry Andric bool Update() override; 56*81ad6265SDimitry Andric 57*81ad6265SDimitry Andric bool MightHaveChildren() override; 58*81ad6265SDimitry Andric 59*81ad6265SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 60*81ad6265SDimitry Andric 61*81ad6265SDimitry Andric private: 62*81ad6265SDimitry Andric ValueObject *m_start = nullptr; ///< First element of span. Held, not owned. 63*81ad6265SDimitry Andric CompilerType m_element_type{}; ///< Type of span elements. 64*81ad6265SDimitry Andric size_t m_num_elements = 0; ///< Number of elements in span. 65*81ad6265SDimitry Andric uint32_t m_element_size = 0; ///< Size in bytes of each span element. 66*81ad6265SDimitry Andric }; 67*81ad6265SDimitry Andric 68*81ad6265SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd:: 69*81ad6265SDimitry Andric LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 70*81ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp) { 71*81ad6265SDimitry Andric if (valobj_sp) 72*81ad6265SDimitry Andric Update(); 73*81ad6265SDimitry Andric } 74*81ad6265SDimitry Andric 75*81ad6265SDimitry Andric size_t lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd:: 76*81ad6265SDimitry Andric CalculateNumChildren() { 77*81ad6265SDimitry Andric return m_num_elements; 78*81ad6265SDimitry Andric } 79*81ad6265SDimitry Andric 80*81ad6265SDimitry Andric lldb::ValueObjectSP 81*81ad6265SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::GetChildAtIndex( 82*81ad6265SDimitry Andric size_t idx) { 83*81ad6265SDimitry Andric if (!m_start) 84*81ad6265SDimitry Andric return {}; 85*81ad6265SDimitry Andric 86*81ad6265SDimitry Andric uint64_t offset = idx * m_element_size; 87*81ad6265SDimitry Andric offset = offset + m_start->GetValueAsUnsigned(0); 88*81ad6265SDimitry Andric StreamString name; 89*81ad6265SDimitry Andric name.Printf("[%" PRIu64 "]", (uint64_t)idx); 90*81ad6265SDimitry Andric return CreateValueObjectFromAddress(name.GetString(), offset, 91*81ad6265SDimitry Andric m_backend.GetExecutionContextRef(), 92*81ad6265SDimitry Andric m_element_type); 93*81ad6265SDimitry Andric } 94*81ad6265SDimitry Andric 95*81ad6265SDimitry Andric bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { 96*81ad6265SDimitry Andric // Get element type. 97*81ad6265SDimitry Andric ValueObjectSP data_type_finder_sp( 98*81ad6265SDimitry Andric m_backend.GetChildMemberWithName(ConstString("__data"), true)); 99*81ad6265SDimitry Andric if (!data_type_finder_sp) 100*81ad6265SDimitry Andric return false; 101*81ad6265SDimitry Andric 102*81ad6265SDimitry Andric m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType(); 103*81ad6265SDimitry Andric 104*81ad6265SDimitry Andric // Get element size. 105*81ad6265SDimitry Andric if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { 106*81ad6265SDimitry Andric m_element_size = *size; 107*81ad6265SDimitry Andric 108*81ad6265SDimitry Andric // Get data. 109*81ad6265SDimitry Andric if (m_element_size > 0) { 110*81ad6265SDimitry Andric m_start = data_type_finder_sp.get(); 111*81ad6265SDimitry Andric } 112*81ad6265SDimitry Andric 113*81ad6265SDimitry Andric // Get number of elements. 114*81ad6265SDimitry Andric if (auto size_sp = 115*81ad6265SDimitry Andric m_backend.GetChildMemberWithName(ConstString("__size"), true)) { 116*81ad6265SDimitry Andric m_num_elements = size_sp->GetValueAsUnsigned(0); 117*81ad6265SDimitry Andric } else if (auto arg = 118*81ad6265SDimitry Andric m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { 119*81ad6265SDimitry Andric 120*81ad6265SDimitry Andric m_num_elements = arg->value.getLimitedValue(); 121*81ad6265SDimitry Andric } 122*81ad6265SDimitry Andric } 123*81ad6265SDimitry Andric 124*81ad6265SDimitry Andric return true; 125*81ad6265SDimitry Andric } 126*81ad6265SDimitry Andric 127*81ad6265SDimitry Andric bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd:: 128*81ad6265SDimitry Andric MightHaveChildren() { 129*81ad6265SDimitry Andric return true; 130*81ad6265SDimitry Andric } 131*81ad6265SDimitry Andric 132*81ad6265SDimitry Andric size_t lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd:: 133*81ad6265SDimitry Andric GetIndexOfChildWithName(ConstString name) { 134*81ad6265SDimitry Andric if (!m_start) 135*81ad6265SDimitry Andric return UINT32_MAX; 136*81ad6265SDimitry Andric return ExtractIndexFromString(name.GetCString()); 137*81ad6265SDimitry Andric } 138*81ad6265SDimitry Andric 139*81ad6265SDimitry Andric lldb_private::SyntheticChildrenFrontEnd * 140*81ad6265SDimitry Andric LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *, 141*81ad6265SDimitry Andric lldb::ValueObjectSP valobj_sp) { 142*81ad6265SDimitry Andric if (!valobj_sp) 143*81ad6265SDimitry Andric return nullptr; 144*81ad6265SDimitry Andric CompilerType type = valobj_sp->GetCompilerType(); 145*81ad6265SDimitry Andric if (!type.IsValid() || type.GetNumTemplateArguments() != 2) 146*81ad6265SDimitry Andric return nullptr; 147*81ad6265SDimitry Andric return new LibcxxStdSpanSyntheticFrontEnd(valobj_sp); 148*81ad6265SDimitry Andric } 149*81ad6265SDimitry Andric 150*81ad6265SDimitry Andric } // namespace formatters 151*81ad6265SDimitry Andric } // namespace lldb_private 152