181ad6265SDimitry Andric //===-- LibCxxSpan.cpp ----------------------------------------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "LibCxx.h" 1081ad6265SDimitry Andric 1181ad6265SDimitry Andric #include "lldb/Core/ValueObject.h" 1281ad6265SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h" 1381ad6265SDimitry Andric #include "lldb/Utility/ConstString.h" 1481ad6265SDimitry Andric #include "llvm/ADT/APSInt.h" 15bdd1243dSDimitry Andric #include <optional> 1681ad6265SDimitry Andric 1781ad6265SDimitry Andric using namespace lldb; 1881ad6265SDimitry Andric using namespace lldb_private; 1981ad6265SDimitry Andric using namespace lldb_private::formatters; 2081ad6265SDimitry Andric 2181ad6265SDimitry Andric namespace lldb_private { 2281ad6265SDimitry Andric namespace formatters { 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric class LibcxxStdSpanSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 2581ad6265SDimitry Andric public: 2681ad6265SDimitry Andric LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric ~LibcxxStdSpanSyntheticFrontEnd() override = default; 2981ad6265SDimitry Andric 30*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 3181ad6265SDimitry Andric 32*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 3381ad6265SDimitry Andric 3481ad6265SDimitry Andric /// Determines properties of the std::span<> associated with this object 3581ad6265SDimitry Andric // 3681ad6265SDimitry Andric // std::span can either be instantiated with a compile-time known 3781ad6265SDimitry Andric // extent or a std::dynamic_extent (this is the default if only the 3881ad6265SDimitry Andric // type template argument is provided). The layout of std::span 3981ad6265SDimitry Andric // depends on whether the extent is dynamic or not. For static 4081ad6265SDimitry Andric // extents (e.g., std::span<int, 9>): 4181ad6265SDimitry Andric // 4281ad6265SDimitry Andric // (std::__1::span<const int, 9>) s = { 4381ad6265SDimitry Andric // __data = 0x000000016fdff494 4481ad6265SDimitry Andric // } 4581ad6265SDimitry Andric // 4681ad6265SDimitry Andric // For dynamic extents, e.g., std::span<int>, the layout is: 4781ad6265SDimitry Andric // 4881ad6265SDimitry Andric // (std::__1::span<const int, 18446744073709551615>) s = { 4981ad6265SDimitry Andric // __data = 0x000000016fdff494 5081ad6265SDimitry Andric // __size = 6 5181ad6265SDimitry Andric // } 5281ad6265SDimitry Andric // 5381ad6265SDimitry Andric // This function checks for a '__size' member to determine the number 5481ad6265SDimitry Andric // of elements in the span. If no such member exists, we get the size 5581ad6265SDimitry Andric // from the only other place it can be: the template argument. 56*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric bool MightHaveChildren() override; 5981ad6265SDimitry Andric 6081ad6265SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric private: 6381ad6265SDimitry Andric ValueObject *m_start = nullptr; ///< First element of span. Held, not owned. 6481ad6265SDimitry Andric CompilerType m_element_type{}; ///< Type of span elements. 6581ad6265SDimitry Andric size_t m_num_elements = 0; ///< Number of elements in span. 6681ad6265SDimitry Andric uint32_t m_element_size = 0; ///< Size in bytes of each span element. 6781ad6265SDimitry Andric }; 6881ad6265SDimitry Andric 6981ad6265SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd:: 7081ad6265SDimitry Andric LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 7181ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp) { 7281ad6265SDimitry Andric if (valobj_sp) 7381ad6265SDimitry Andric Update(); 7481ad6265SDimitry Andric } 7581ad6265SDimitry Andric 76*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters:: 77*0fca6ea1SDimitry Andric LibcxxStdSpanSyntheticFrontEnd::CalculateNumChildren() { 7881ad6265SDimitry Andric return m_num_elements; 7981ad6265SDimitry Andric } 8081ad6265SDimitry Andric 8181ad6265SDimitry Andric lldb::ValueObjectSP 8281ad6265SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::GetChildAtIndex( 83*0fca6ea1SDimitry Andric uint32_t idx) { 8481ad6265SDimitry Andric if (!m_start) 8581ad6265SDimitry Andric return {}; 8681ad6265SDimitry Andric 8781ad6265SDimitry Andric uint64_t offset = idx * m_element_size; 8881ad6265SDimitry Andric offset = offset + m_start->GetValueAsUnsigned(0); 8981ad6265SDimitry Andric StreamString name; 9081ad6265SDimitry Andric name.Printf("[%" PRIu64 "]", (uint64_t)idx); 9181ad6265SDimitry Andric return CreateValueObjectFromAddress(name.GetString(), offset, 9281ad6265SDimitry Andric m_backend.GetExecutionContextRef(), 9381ad6265SDimitry Andric m_element_type); 9481ad6265SDimitry Andric } 9581ad6265SDimitry Andric 96*0fca6ea1SDimitry Andric lldb::ChildCacheState 97*0fca6ea1SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { 9881ad6265SDimitry Andric // Get element type. 99bdd1243dSDimitry Andric ValueObjectSP data_type_finder_sp = GetChildMemberWithName( 100bdd1243dSDimitry Andric m_backend, {ConstString("__data_"), ConstString("__data")}); 10181ad6265SDimitry Andric if (!data_type_finder_sp) 102*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 10381ad6265SDimitry Andric 10481ad6265SDimitry Andric m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType(); 10581ad6265SDimitry Andric 10681ad6265SDimitry Andric // Get element size. 107bdd1243dSDimitry Andric if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { 10881ad6265SDimitry Andric m_element_size = *size; 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric // Get data. 11181ad6265SDimitry Andric if (m_element_size > 0) { 11281ad6265SDimitry Andric m_start = data_type_finder_sp.get(); 11381ad6265SDimitry Andric } 11481ad6265SDimitry Andric 11581ad6265SDimitry Andric // Get number of elements. 116bdd1243dSDimitry Andric if (auto size_sp = GetChildMemberWithName( 117bdd1243dSDimitry Andric m_backend, {ConstString("__size_"), ConstString("__size")})) { 11881ad6265SDimitry Andric m_num_elements = size_sp->GetValueAsUnsigned(0); 11981ad6265SDimitry Andric } else if (auto arg = 12081ad6265SDimitry Andric m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { 12181ad6265SDimitry Andric 12281ad6265SDimitry Andric m_num_elements = arg->value.getLimitedValue(); 12381ad6265SDimitry Andric } 12481ad6265SDimitry Andric } 12581ad6265SDimitry Andric 126*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eReuse; 12781ad6265SDimitry Andric } 12881ad6265SDimitry Andric 12981ad6265SDimitry Andric bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd:: 13081ad6265SDimitry Andric MightHaveChildren() { 13181ad6265SDimitry Andric return true; 13281ad6265SDimitry Andric } 13381ad6265SDimitry Andric 13481ad6265SDimitry Andric size_t lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd:: 13581ad6265SDimitry Andric GetIndexOfChildWithName(ConstString name) { 13681ad6265SDimitry Andric if (!m_start) 13781ad6265SDimitry Andric return UINT32_MAX; 13881ad6265SDimitry Andric return ExtractIndexFromString(name.GetCString()); 13981ad6265SDimitry Andric } 14081ad6265SDimitry Andric 14181ad6265SDimitry Andric lldb_private::SyntheticChildrenFrontEnd * 14281ad6265SDimitry Andric LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *, 14381ad6265SDimitry Andric lldb::ValueObjectSP valobj_sp) { 14481ad6265SDimitry Andric if (!valobj_sp) 14581ad6265SDimitry Andric return nullptr; 14681ad6265SDimitry Andric CompilerType type = valobj_sp->GetCompilerType(); 14781ad6265SDimitry Andric if (!type.IsValid() || type.GetNumTemplateArguments() != 2) 14881ad6265SDimitry Andric return nullptr; 14981ad6265SDimitry Andric return new LibcxxStdSpanSyntheticFrontEnd(valobj_sp); 15081ad6265SDimitry Andric } 15181ad6265SDimitry Andric 15281ad6265SDimitry Andric } // namespace formatters 15381ad6265SDimitry Andric } // namespace lldb_private 154