brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 496bbd0 Raw
157 lines · cpp
1//===-- LibCxxSpan.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "LibCxx.h"10 11#include "lldb/DataFormatters/FormattersHelpers.h"12#include "lldb/Utility/ConstString.h"13#include "lldb/ValueObject/ValueObject.h"14#include "llvm/ADT/APSInt.h"15#include <optional>16 17using namespace lldb;18using namespace lldb_private;19using namespace lldb_private::formatters;20 21namespace lldb_private {22namespace formatters {23 24class LibcxxStdSpanSyntheticFrontEnd : public SyntheticChildrenFrontEnd {25public:26  LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);27 28  ~LibcxxStdSpanSyntheticFrontEnd() override = default;29 30  llvm::Expected<uint32_t> CalculateNumChildren() override;31 32  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;33 34  /// Determines properties of the std::span<> associated with this object35  //36  // std::span can either be instantiated with a compile-time known37  // extent or a std::dynamic_extent (this is the default if only the38  // type template argument is provided). The layout of std::span39  // depends on whether the extent is dynamic or not. For static40  // extents (e.g., std::span<int, 9>):41  //42  // (std::__1::span<const int, 9>) s = {43  //   __data = 0x000000016fdff49444  // }45  //46  // For dynamic extents, e.g., std::span<int>, the layout is:47  //48  // (std::__1::span<const int, 18446744073709551615>) s = {49  //   __data = 0x000000016fdff49450  //   __size = 651  // }52  //53  // This function checks for a '__size' member to determine the number54  // of elements in the span. If no such member exists, we get the size55  // from the only other place it can be: the template argument.56  lldb::ChildCacheState Update() override;57 58  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;59 60private:61  ValueObject *m_start = nullptr; ///< First element of span. Held, not owned.62  CompilerType m_element_type{};  ///< Type of span elements.63  size_t m_num_elements = 0;      ///< Number of elements in span.64  uint32_t m_element_size = 0;    ///< Size in bytes of each span element.65};66 67lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::68    LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)69    : SyntheticChildrenFrontEnd(*valobj_sp) {70  if (valobj_sp)71    Update();72}73 74llvm::Expected<uint32_t> lldb_private::formatters::75    LibcxxStdSpanSyntheticFrontEnd::CalculateNumChildren() {76  return m_num_elements;77}78 79lldb::ValueObjectSP80lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::GetChildAtIndex(81    uint32_t idx) {82  if (!m_start)83    return {};84 85  uint64_t offset = idx * m_element_size;86  offset = offset + m_start->GetValueAsUnsigned(0);87  StreamString name;88  name.Printf("[%" PRIu64 "]", (uint64_t)idx);89  return CreateValueObjectFromAddress(name.GetString(), offset,90                                      m_backend.GetExecutionContextRef(),91                                      m_element_type);92}93 94lldb::ChildCacheState95lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() {96  // Get element type.97  ValueObjectSP data_type_finder_sp = GetChildMemberWithName(98      m_backend, {ConstString("__data_"), ConstString("__data")});99  if (!data_type_finder_sp)100    return lldb::ChildCacheState::eRefetch;101 102  m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();103 104  // Get element size.105  llvm::Expected<uint64_t> size_or_err = m_element_type.GetByteSize(nullptr);106  if (!size_or_err)107    LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), size_or_err.takeError(),108                    "{0}");109  else {110    m_element_size = *size_or_err;111 112    // Get data.113    if (m_element_size > 0) {114      m_start = data_type_finder_sp.get();115    }116 117    // Get number of elements.118    if (auto size_sp = GetChildMemberWithName(119            m_backend, {ConstString("__size_"), ConstString("__size")})) {120      m_num_elements = size_sp->GetValueAsUnsigned(0);121    } else if (auto arg =122                   m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) {123 124      m_num_elements = arg->value.GetAPSInt().getLimitedValue();125    }126  }127 128  return lldb::ChildCacheState::eReuse;129}130 131llvm::Expected<size_t> lldb_private::formatters::132    LibcxxStdSpanSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {133  if (!m_start)134    return llvm::createStringError("Type has no child named '%s'",135                                   name.AsCString());136  auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());137  if (!optional_idx) {138    return llvm::createStringError("Type has no child named '%s'",139                                   name.AsCString());140  }141  return *optional_idx;142}143 144lldb_private::SyntheticChildrenFrontEnd *145LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *,146                                      lldb::ValueObjectSP valobj_sp) {147  if (!valobj_sp)148    return nullptr;149  CompilerType type = valobj_sp->GetCompilerType();150  if (!type.IsValid() || type.GetNumTemplateArguments() != 2)151    return nullptr;152  return new LibcxxStdSpanSyntheticFrontEnd(valobj_sp);153}154 155} // namespace formatters156} // namespace lldb_private157