1 //===-- LibCxxAtomic.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 "LibCxxAtomic.h"
10 #include "lldb/DataFormatters/FormattersHelpers.h"
11
12 using namespace lldb;
13 using namespace lldb_private;
14 using namespace lldb_private::formatters;
15
16 //
17 // We are supporting two versions of libc++ std::atomic
18 //
19 // Given std::atomic<int> i;
20 //
21 // The previous version of std::atomic was laid out like this
22 //
23 // (lldb) frame var -L -R i
24 // 0x00007ffeefbff9a0: (std::__1::atomic<int>) i = {
25 // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, true> = {
26 // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, false> = {
27 // 0x00007ffeefbff9a0: __a_ = 5
28 // }
29 // }
30 // }
31 //
32 // In this case we need to obtain __a_ and the current version is laid out as so
33 //
34 // (lldb) frame var -L -R i
35 // 0x00007ffeefbff9b0: (std::__1::atomic<int>) i = {
36 // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, true> = {
37 // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, false> = {
38 // 0x00007ffeefbff9b0: __a_ = {
39 // 0x00007ffeefbff9b0: std::__1::__cxx_atomic_base_impl<int> = {
40 // 0x00007ffeefbff9b0: __a_value = 5
41 // }
42 // }
43 // }
44 // }
45 //}
46 //
47 // In this case we need to obtain __a_value
48 //
49 // The below method covers both cases and returns the relevant member as a
50 // ValueObjectSP
51 //
52 ValueObjectSP
GetLibCxxAtomicValue(ValueObject & valobj)53 lldb_private::formatters::GetLibCxxAtomicValue(ValueObject &valobj) {
54 ValueObjectSP non_sythetic = valobj.GetNonSyntheticValue();
55 if (!non_sythetic)
56 return {};
57
58 ValueObjectSP member__a_ =
59 non_sythetic->GetChildMemberWithName(ConstString("__a_"), true);
60 if (!member__a_)
61 return {};
62
63 ValueObjectSP member__a_value =
64 member__a_->GetChildMemberWithName(ConstString("__a_value"), true);
65 if (!member__a_value)
66 return member__a_;
67
68 return member__a_value;
69 }
70
LibCxxAtomicSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)71 bool lldb_private::formatters::LibCxxAtomicSummaryProvider(
72 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
73
74 if (ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj)) {
75 std::string summary;
76 if (atomic_value->GetSummaryAsCString(summary, options) &&
77 summary.size() > 0) {
78 stream.Printf("%s", summary.c_str());
79 return true;
80 }
81 }
82
83 return false;
84 }
85
86 namespace lldb_private {
87 namespace formatters {
88 class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
89 public:
90 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
91
92 ~LibcxxStdAtomicSyntheticFrontEnd() override = default;
93
94 size_t CalculateNumChildren() override;
95
96 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
97
98 bool Update() override;
99
100 bool MightHaveChildren() override;
101
102 size_t GetIndexOfChildWithName(ConstString name) override;
103
104 private:
105 ValueObject *m_real_child = nullptr;
106 };
107 } // namespace formatters
108 } // namespace lldb_private
109
110 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)111 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
112 : SyntheticChildrenFrontEnd(*valobj_sp) {}
113
Update()114 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() {
115 ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend);
116 if (atomic_value)
117 m_real_child = GetLibCxxAtomicValue(m_backend).get();
118
119 return false;
120 }
121
122 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
MightHaveChildren()123 MightHaveChildren() {
124 return true;
125 }
126
127 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
CalculateNumChildren()128 CalculateNumChildren() {
129 return m_real_child ? 1 : 0;
130 }
131
132 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)133 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex(
134 size_t idx) {
135 if (idx == 0)
136 return m_real_child->GetSP()->Clone(ConstString("Value"));
137 return nullptr;
138 }
139
140 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)141 GetIndexOfChildWithName(ConstString name) {
142 return formatters::ExtractIndexFromString(name.GetCString());
143 }
144
145 SyntheticChildrenFrontEnd *
LibcxxAtomicSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)146 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator(
147 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
148 if (valobj_sp)
149 return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp);
150 return nullptr;
151 }
152