Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp
Line
Count
Source (jump to first uncovered line)
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
0
  size_t GetIndexOfChildWithName(ConstString name) override {
32
0
    return formatters::ExtractIndexFromString(name.GetCString());
33
0
  }
34
35
2
  bool MightHaveChildren() override { return true; }
36
  bool Update() override;
37
20
  size_t CalculateNumChildren() override { return m_elements.size(); }
38
  ValueObjectSP GetChildAtIndex(size_t idx) override;
39
40
private:
41
  llvm::StringRef GetDataContainerMemberName();
42
43
  // The lifetime of a ValueObject and all its derivative ValueObjects
44
  // (children, clones, etc.) is managed by a ClusterManager. These
45
  // objects are only destroyed when every shared pointer to any of them
46
  // is destroyed, so we must not store a shared pointer to any ValueObject
47
  // derived from our backend ValueObject (since we're in the same cluster).
48
  // Value objects created from raw data (i.e. in a different cluster) must
49
  // be referenced via shared pointer to keep them alive, however.
50
  std::vector<ValueObjectSP> m_elements;
51
  ValueObject *m_first = nullptr;
52
  CompilerType m_bool_type;
53
  ByteOrder m_byte_order = eByteOrderInvalid;
54
  uint8_t m_byte_size = 0;
55
  StdLib m_stdlib;
56
};
57
} // namespace
58
59
GenericBitsetFrontEnd::GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib)
60
20
    : SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {
61
20
  m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool);
62
20
  if (auto target_sp = m_backend.GetTargetSP()) {
63
20
    m_byte_order = target_sp->GetArchitecture().GetByteOrder();
64
20
    m_byte_size = target_sp->GetArchitecture().GetAddressByteSize();
65
20
    Update();
66
20
  }
67
20
}
68
69
40
llvm::StringRef GenericBitsetFrontEnd::GetDataContainerMemberName() {
70
40
  static constexpr llvm::StringLiteral s_libcxx_case("__first_");
71
40
  static constexpr llvm::StringLiteral s_libstdcpp_case("_M_w");
72
40
  switch (m_stdlib) {
73
40
  case StdLib::LibCxx:
74
40
    return s_libcxx_case;
75
0
  case StdLib::LibStdcpp:
76
0
    return s_libstdcpp_case;
77
40
  }
78
0
  llvm_unreachable("Unknown StdLib enum");
79
0
}
80
81
40
bool GenericBitsetFrontEnd::Update() {
82
40
  m_elements.clear();
83
40
  m_first = nullptr;
84
85
40
  TargetSP target_sp = m_backend.GetTargetSP();
86
40
  if (!target_sp)
87
0
    return false;
88
89
40
  size_t size = 0;
90
91
40
  if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0))
92
40
    size = arg->value.getLimitedValue();
93
94
40
  m_elements.assign(size, ValueObjectSP());
95
40
  m_first =
96
40
      m_backend.GetChildMemberWithName(GetDataContainerMemberName()).get();
97
40
  return false;
98
40
}
99
100
6.49k
ValueObjectSP GenericBitsetFrontEnd::GetChildAtIndex(size_t idx) {
101
6.49k
  if (idx >= m_elements.size() || !m_first)
102
0
    return ValueObjectSP();
103
104
6.49k
  if (m_elements[idx])
105
0
    return m_elements[idx];
106
107
6.49k
  ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false);
108
6.49k
  CompilerType type;
109
6.49k
  ValueObjectSP chunk;
110
  // For small bitsets __first_ is not an array, but a plain size_t.
111
6.49k
  if (m_first->GetCompilerType().IsArrayType(&type)) {
112
6.42k
    std::optional<uint64_t> bit_size =
113
6.42k
        type.GetBitSize(ctx.GetBestExecutionContextScope());
114
6.42k
    if (!bit_size || *bit_size == 0)
115
0
      return {};
116
6.42k
    chunk = m_first->GetChildAtIndex(idx / *bit_size);
117
6.42k
  } else {
118
78
    type = m_first->GetCompilerType();
119
78
    chunk = m_first->GetSP();
120
78
  }
121
6.49k
  if (!type || !chunk)
122
0
    return {};
123
124
6.49k
  std::optional<uint64_t> bit_size =
125
6.49k
      type.GetBitSize(ctx.GetBestExecutionContextScope());
126
6.49k
  if (!bit_size || *bit_size == 0)
127
0
    return {};
128
6.49k
  size_t chunk_idx = idx % *bit_size;
129
6.49k
  uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx));
130
6.49k
  DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size);
131
132
6.49k
  m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(),
133
6.49k
                                              data, ctx, m_bool_type);
134
135
6.49k
  return m_elements[idx];
136
6.49k
}
137
138
SyntheticChildrenFrontEnd *formatters::LibStdcppBitsetSyntheticFrontEndCreator(
139
0
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
140
0
  if (valobj_sp)
141
0
    return new GenericBitsetFrontEnd(*valobj_sp,
142
0
                                     GenericBitsetFrontEnd::StdLib::LibStdcpp);
143
0
  return nullptr;
144
0
}
145
146
SyntheticChildrenFrontEnd *formatters::LibcxxBitsetSyntheticFrontEndCreator(
147
20
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
148
20
  if (valobj_sp)
149
20
    return new GenericBitsetFrontEnd(*valobj_sp,
150
20
                                     GenericBitsetFrontEnd::StdLib::LibCxx);
151
0
  return nullptr;
152
20
}