xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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_ = non_sythetic->GetChildMemberWithName("__a_");
59   if (!member__a_)
60     return {};
61 
62   ValueObjectSP member__a_value =
63       member__a_->GetChildMemberWithName("__a_value");
64   if (!member__a_value)
65     return member__a_;
66 
67   return member__a_value;
68 }
69 
LibCxxAtomicSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)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(summary, options) &&
76         summary.size() > 0) {
77       stream.Printf("%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::
LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)110     LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
111     : SyntheticChildrenFrontEnd(*valobj_sp) {}
112 
113 lldb::ChildCacheState
Update()114 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 lldb::ChildCacheState::eRefetch;
120 }
121 
122 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
MightHaveChildren()123     MightHaveChildren() {
124   return true;
125 }
126 
127 llvm::Expected<uint32_t> lldb_private::formatters::
CalculateNumChildren()128     LibcxxStdAtomicSyntheticFrontEnd::CalculateNumChildren() {
129   return m_real_child ? 1 : 0;
130 }
131 
132 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx)133 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex(
134     uint32_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 name == "Value" ? 0 : UINT32_MAX;
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