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 |
53 | lldb_private::formatters::GetLibCxxAtomicValue(ValueObject &valobj) { |
54 | ValueObjectSP non_sythetic = valobj.GetNonSyntheticValue(); |
55 | if (!non_sythetic) |
56 | return {}; |
57 | |
58 | ValueObjectSP member__a_ = non_sythetic->GetChildMemberWithName(name: "__a_" ); |
59 | if (!member__a_) |
60 | return {}; |
61 | |
62 | ValueObjectSP member__a_value = |
63 | member__a_->GetChildMemberWithName(name: "__a_value" ); |
64 | if (!member__a_value) |
65 | return member__a_; |
66 | |
67 | return member__a_value; |
68 | } |
69 | |
70 | bool lldb_private::formatters::LibCxxAtomicSummaryProvider( |
71 | ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { |
72 | |
73 | if (ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj)) { |
74 | std::string summary; |
75 | if (atomic_value->GetSummaryAsCString(destination&: summary, options) && |
76 | summary.size() > 0) { |
77 | stream.Printf(format: "%s" , summary.c_str()); |
78 | return true; |
79 | } |
80 | } |
81 | |
82 | return false; |
83 | } |
84 | |
85 | namespace lldb_private { |
86 | namespace formatters { |
87 | class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd { |
88 | public: |
89 | LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); |
90 | |
91 | ~LibcxxStdAtomicSyntheticFrontEnd() override = default; |
92 | |
93 | llvm::Expected<uint32_t> CalculateNumChildren() override; |
94 | |
95 | lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; |
96 | |
97 | lldb::ChildCacheState Update() override; |
98 | |
99 | bool MightHaveChildren() override; |
100 | |
101 | size_t GetIndexOfChildWithName(ConstString name) override; |
102 | |
103 | private: |
104 | ValueObject *m_real_child = nullptr; |
105 | }; |
106 | } // namespace formatters |
107 | } // namespace lldb_private |
108 | |
109 | lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: |
110 | LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) |
111 | : SyntheticChildrenFrontEnd(*valobj_sp) {} |
112 | |
113 | lldb::ChildCacheState |
114 | lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() { |
115 | ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj&: m_backend); |
116 | if (atomic_value) |
117 | m_real_child = GetLibCxxAtomicValue(valobj&: m_backend).get(); |
118 | |
119 | return lldb::ChildCacheState::eRefetch; |
120 | } |
121 | |
122 | bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: |
123 | MightHaveChildren() { |
124 | return true; |
125 | } |
126 | |
127 | llvm::Expected<uint32_t> lldb_private::formatters:: |
128 | LibcxxStdAtomicSyntheticFrontEnd::CalculateNumChildren() { |
129 | return m_real_child ? 1 : 0; |
130 | } |
131 | |
132 | lldb::ValueObjectSP |
133 | lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex( |
134 | uint32_t idx) { |
135 | if (idx == 0) |
136 | return m_real_child->GetSP()->Clone(new_name: ConstString("Value" )); |
137 | return nullptr; |
138 | } |
139 | |
140 | size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: |
141 | GetIndexOfChildWithName(ConstString name) { |
142 | return name == "Value" ? 0 : UINT32_MAX; |
143 | } |
144 | |
145 | SyntheticChildrenFrontEnd * |
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 | |