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