LLDB  mainline
GenericBitset.cpp
Go to the documentation of this file.
1 //===-- GenericBitset.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 #include "LibStdcpp.h"
13 #include "lldb/Target/Target.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
18 namespace {
19 
20 /// This class can be used for handling bitsets from both libcxx and libstdcpp.
21 class GenericBitsetFrontEnd : public SyntheticChildrenFrontEnd {
22 public:
23  enum class StdLib {
24  LibCxx,
25  LibStdcpp,
26  };
27 
28  GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib);
29 
30  size_t GetIndexOfChildWithName(ConstString name) override {
32  }
33 
34  bool MightHaveChildren() override { return true; }
35  bool Update() override;
36  size_t CalculateNumChildren() override { return m_elements.size(); }
37  ValueObjectSP GetChildAtIndex(size_t idx) override;
38 
39 private:
40  ConstString GetDataContainerMemberName();
41 
42  // The lifetime of a ValueObject and all its derivative ValueObjects
43  // (children, clones, etc.) is managed by a ClusterManager. These
44  // objects are only destroyed when every shared pointer to any of them
45  // is destroyed, so we must not store a shared pointer to any ValueObject
46  // derived from our backend ValueObject (since we're in the same cluster).
47  // Value objects created from raw data (i.e. in a different cluster) must
48  // be referenced via shared pointer to keep them alive, however.
49  std::vector<ValueObjectSP> m_elements;
50  ValueObject *m_first = nullptr;
51  CompilerType m_bool_type;
52  ByteOrder m_byte_order = eByteOrderInvalid;
53  uint8_t m_byte_size = 0;
54  StdLib m_stdlib;
55 };
56 } // namespace
57 
58 GenericBitsetFrontEnd::GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib)
59  : SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {
60  m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool);
61  if (auto target_sp = m_backend.GetTargetSP()) {
62  m_byte_order = target_sp->GetArchitecture().GetByteOrder();
63  m_byte_size = target_sp->GetArchitecture().GetAddressByteSize();
64  Update();
65  }
66 }
67 
68 ConstString GenericBitsetFrontEnd::GetDataContainerMemberName() {
69  switch (m_stdlib) {
70  case StdLib::LibCxx:
71  return ConstString("__first_");
72  case StdLib::LibStdcpp:
73  return ConstString("_M_w");
74  }
75  llvm_unreachable("Unknown StdLib enum");
76 }
77 
78 bool GenericBitsetFrontEnd::Update() {
79  m_elements.clear();
80  m_first = nullptr;
81 
82  TargetSP target_sp = m_backend.GetTargetSP();
83  if (!target_sp)
84  return false;
85 
86  size_t size = 0;
87 
88  if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0))
89  size = arg->value.getLimitedValue();
90 
91  m_elements.assign(size, ValueObjectSP());
92  m_first = m_backend.GetChildMemberWithName(GetDataContainerMemberName(), true)
93  .get();
94  return false;
95 }
96 
97 ValueObjectSP GenericBitsetFrontEnd::GetChildAtIndex(size_t idx) {
98  if (idx >= m_elements.size() || !m_first)
99  return ValueObjectSP();
100 
101  if (m_elements[idx])
102  return m_elements[idx];
103 
104  ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false);
105  CompilerType type;
106  ValueObjectSP chunk;
107  // For small bitsets __first_ is not an array, but a plain size_t.
108  if (m_first->GetCompilerType().IsArrayType(&type)) {
109  llvm::Optional<uint64_t> bit_size =
111  if (!bit_size || *bit_size == 0)
112  return {};
113  chunk = m_first->GetChildAtIndex(idx / *bit_size, true);
114  } else {
115  type = m_first->GetCompilerType();
116  chunk = m_first->GetSP();
117  }
118  if (!type || !chunk)
119  return {};
120 
121  llvm::Optional<uint64_t> bit_size =
123  if (!bit_size || *bit_size == 0)
124  return {};
125  size_t chunk_idx = idx % *bit_size;
126  uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx));
127  DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size);
128 
129  m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(),
130  data, ctx, m_bool_type);
131 
132  return m_elements[idx];
133 }
134 
136  CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
137  if (valobj_sp)
138  return new GenericBitsetFrontEnd(*valobj_sp,
139  GenericBitsetFrontEnd::StdLib::LibStdcpp);
140  return nullptr;
141 }
142 
144  CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
145  if (valobj_sp)
146  return new GenericBitsetFrontEnd(*valobj_sp,
147  GenericBitsetFrontEnd::StdLib::LibCxx);
148  return nullptr;
149 }
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb::eBasicTypeBool
@ eBasicTypeBool
Definition: lldb-enumerations.h:771
CalculateNumChildren
static size_t CalculateNumChildren(CompilerType container_type, CompilerType element_type, lldb_private::ExecutionContextScope *exe_scope=nullptr)
Definition: VectorType.cpp:169
lldb_private::SyntheticChildrenFrontEnd
Definition: TypeSynthetic.h:27
Target.h
lldb_private::DataExtractor
Definition: DataExtractor.h:48
TypeSystemClang.h
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator
SyntheticChildrenFrontEnd * LibcxxBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: GenericBitset.cpp:143
lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator
SyntheticChildrenFrontEnd * LibStdcppBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: GenericBitset.cpp:135
lldb_private::ValueObject
ValueObject:
Definition: ValueObject.h:105
lldb::eByteOrderInvalid
@ eByteOrderInvalid
Definition: lldb-enumerations.h:139
lldb_private::ExecutionContext::GetBestExecutionContextScope
ExecutionContextScope * GetBestExecutionContextScope() const
Definition: ExecutionContext.cpp:214
lldb_private::CompilerType::GetBitSize
llvm::Optional< uint64_t > GetBitSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bits.
Definition: CompilerType.cpp:482
lldb_private::ValueObject::GetCompilerType
CompilerType GetCompilerType()
Definition: ValueObject.h:352
lldb_private::ConstString::GetCString
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
lldb_private::CompilerType::GetBasicTypeFromAST
CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) const
Create related types using the current type's AST.
Definition: CompilerType.cpp:474
lldb_private::CompilerType
Generic representation of a type in a programming language.
Definition: CompilerType.h:33
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
LibCxx.h
lldb_private::CXXSyntheticChildren
Definition: TypeSynthetic.h:358
FormattersHelpers.h
lldb
Definition: SBAddress.h:15
LibStdcpp.h
lldb_private::formatters::ExtractIndexFromString
size_t ExtractIndexFromString(const char *item_name)
Definition: FormattersHelpers.cpp:119
lldb::ByteOrder
ByteOrder
Byte ordering definitions.
Definition: lldb-enumerations.h:138