Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp
39644 views
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"
11
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
12
#include "lldb/DataFormatters/FormattersHelpers.h"
13
#include "lldb/Target/Target.h"
14
#include <optional>
15
16
using namespace lldb;
17
using namespace lldb_private;
18
19
namespace {
20
21
/// This class can be used for handling bitsets from both libcxx and libstdcpp.
22
class GenericBitsetFrontEnd : public SyntheticChildrenFrontEnd {
23
public:
24
enum class StdLib {
25
LibCxx,
26
LibStdcpp,
27
};
28
29
GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib);
30
31
size_t GetIndexOfChildWithName(ConstString name) override {
32
return formatters::ExtractIndexFromString(name.GetCString());
33
}
34
35
bool MightHaveChildren() override { return true; }
36
lldb::ChildCacheState Update() override;
37
llvm::Expected<uint32_t> CalculateNumChildren() override {
38
return m_elements.size();
39
}
40
ValueObjectSP GetChildAtIndex(uint32_t idx) override;
41
42
private:
43
llvm::StringRef GetDataContainerMemberName();
44
45
// The lifetime of a ValueObject and all its derivative ValueObjects
46
// (children, clones, etc.) is managed by a ClusterManager. These
47
// objects are only destroyed when every shared pointer to any of them
48
// is destroyed, so we must not store a shared pointer to any ValueObject
49
// derived from our backend ValueObject (since we're in the same cluster).
50
// Value objects created from raw data (i.e. in a different cluster) must
51
// be referenced via shared pointer to keep them alive, however.
52
std::vector<ValueObjectSP> m_elements;
53
ValueObject *m_first = nullptr;
54
CompilerType m_bool_type;
55
ByteOrder m_byte_order = eByteOrderInvalid;
56
uint8_t m_byte_size = 0;
57
StdLib m_stdlib;
58
};
59
} // namespace
60
61
GenericBitsetFrontEnd::GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib)
62
: SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {
63
m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool);
64
if (auto target_sp = m_backend.GetTargetSP()) {
65
m_byte_order = target_sp->GetArchitecture().GetByteOrder();
66
m_byte_size = target_sp->GetArchitecture().GetAddressByteSize();
67
Update();
68
}
69
}
70
71
llvm::StringRef GenericBitsetFrontEnd::GetDataContainerMemberName() {
72
static constexpr llvm::StringLiteral s_libcxx_case("__first_");
73
static constexpr llvm::StringLiteral s_libstdcpp_case("_M_w");
74
switch (m_stdlib) {
75
case StdLib::LibCxx:
76
return s_libcxx_case;
77
case StdLib::LibStdcpp:
78
return s_libstdcpp_case;
79
}
80
llvm_unreachable("Unknown StdLib enum");
81
}
82
83
lldb::ChildCacheState GenericBitsetFrontEnd::Update() {
84
m_elements.clear();
85
m_first = nullptr;
86
87
TargetSP target_sp = m_backend.GetTargetSP();
88
if (!target_sp)
89
return lldb::ChildCacheState::eRefetch;
90
91
size_t size = 0;
92
93
if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0))
94
size = arg->value.getLimitedValue();
95
96
m_elements.assign(size, ValueObjectSP());
97
m_first =
98
m_backend.GetChildMemberWithName(GetDataContainerMemberName()).get();
99
return lldb::ChildCacheState::eRefetch;
100
}
101
102
ValueObjectSP GenericBitsetFrontEnd::GetChildAtIndex(uint32_t idx) {
103
if (idx >= m_elements.size() || !m_first)
104
return ValueObjectSP();
105
106
if (m_elements[idx])
107
return m_elements[idx];
108
109
ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false);
110
CompilerType type;
111
ValueObjectSP chunk;
112
// For small bitsets __first_ is not an array, but a plain size_t.
113
if (m_first->GetCompilerType().IsArrayType(&type)) {
114
std::optional<uint64_t> bit_size =
115
type.GetBitSize(ctx.GetBestExecutionContextScope());
116
if (!bit_size || *bit_size == 0)
117
return {};
118
chunk = m_first->GetChildAtIndex(idx / *bit_size);
119
} else {
120
type = m_first->GetCompilerType();
121
chunk = m_first->GetSP();
122
}
123
if (!type || !chunk)
124
return {};
125
126
std::optional<uint64_t> bit_size =
127
type.GetBitSize(ctx.GetBestExecutionContextScope());
128
if (!bit_size || *bit_size == 0)
129
return {};
130
size_t chunk_idx = idx % *bit_size;
131
uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx));
132
DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size);
133
134
m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(),
135
data, ctx, m_bool_type);
136
137
return m_elements[idx];
138
}
139
140
SyntheticChildrenFrontEnd *formatters::LibStdcppBitsetSyntheticFrontEndCreator(
141
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
142
if (valobj_sp)
143
return new GenericBitsetFrontEnd(*valobj_sp,
144
GenericBitsetFrontEnd::StdLib::LibStdcpp);
145
return nullptr;
146
}
147
148
SyntheticChildrenFrontEnd *formatters::LibcxxBitsetSyntheticFrontEndCreator(
149
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
150
if (valobj_sp)
151
return new GenericBitsetFrontEnd(*valobj_sp,
152
GenericBitsetFrontEnd::StdLib::LibCxx);
153
return nullptr;
154
}
155
156