15ffd83dbSDimitry Andric //===-- LibCxxAtomic.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "LibCxxAtomic.h"
105ffd83dbSDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric using namespace lldb;
130b57cec5SDimitry Andric using namespace lldb_private;
140b57cec5SDimitry Andric using namespace lldb_private::formatters;
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric // We are supporting two versions of libc++ std::atomic
180b57cec5SDimitry Andric //
190b57cec5SDimitry Andric // Given std::atomic<int> i;
200b57cec5SDimitry Andric //
210b57cec5SDimitry Andric // The previous version of std::atomic was laid out like this
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric // (lldb) frame var -L -R i
240b57cec5SDimitry Andric // 0x00007ffeefbff9a0: (std::__1::atomic<int>) i = {
250b57cec5SDimitry Andric // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, true> = {
260b57cec5SDimitry Andric // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, false> = {
270b57cec5SDimitry Andric // 0x00007ffeefbff9a0: __a_ = 5
280b57cec5SDimitry Andric // }
290b57cec5SDimitry Andric // }
300b57cec5SDimitry Andric // }
310b57cec5SDimitry Andric //
320b57cec5SDimitry Andric // In this case we need to obtain __a_ and the current version is laid out as so
330b57cec5SDimitry Andric //
340b57cec5SDimitry Andric // (lldb) frame var -L -R i
350b57cec5SDimitry Andric // 0x00007ffeefbff9b0: (std::__1::atomic<int>) i = {
360b57cec5SDimitry Andric // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, true> = {
370b57cec5SDimitry Andric // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, false> = {
380b57cec5SDimitry Andric // 0x00007ffeefbff9b0: __a_ = {
390b57cec5SDimitry Andric // 0x00007ffeefbff9b0: std::__1::__cxx_atomic_base_impl<int> = {
400b57cec5SDimitry Andric // 0x00007ffeefbff9b0: __a_value = 5
410b57cec5SDimitry Andric // }
420b57cec5SDimitry Andric // }
430b57cec5SDimitry Andric // }
440b57cec5SDimitry Andric // }
450b57cec5SDimitry Andric //}
460b57cec5SDimitry Andric //
470b57cec5SDimitry Andric // In this case we need to obtain __a_value
480b57cec5SDimitry Andric //
490b57cec5SDimitry Andric // The below method covers both cases and returns the relevant member as a
500b57cec5SDimitry Andric // ValueObjectSP
510b57cec5SDimitry Andric //
520b57cec5SDimitry Andric ValueObjectSP
GetLibCxxAtomicValue(ValueObject & valobj)530b57cec5SDimitry Andric lldb_private::formatters::GetLibCxxAtomicValue(ValueObject &valobj) {
540b57cec5SDimitry Andric ValueObjectSP non_sythetic = valobj.GetNonSyntheticValue();
550b57cec5SDimitry Andric if (!non_sythetic)
560b57cec5SDimitry Andric return {};
570b57cec5SDimitry Andric
58*fe013be4SDimitry Andric ValueObjectSP member__a_ = non_sythetic->GetChildMemberWithName("__a_");
590b57cec5SDimitry Andric if (!member__a_)
600b57cec5SDimitry Andric return {};
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric ValueObjectSP member__a_value =
63*fe013be4SDimitry Andric member__a_->GetChildMemberWithName("__a_value");
640b57cec5SDimitry Andric if (!member__a_value)
650b57cec5SDimitry Andric return member__a_;
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric return member__a_value;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric
LibCxxAtomicSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)700b57cec5SDimitry Andric bool lldb_private::formatters::LibCxxAtomicSummaryProvider(
710b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric if (ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj)) {
740b57cec5SDimitry Andric std::string summary;
750b57cec5SDimitry Andric if (atomic_value->GetSummaryAsCString(summary, options) &&
760b57cec5SDimitry Andric summary.size() > 0) {
770b57cec5SDimitry Andric stream.Printf("%s", summary.c_str());
780b57cec5SDimitry Andric return true;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric return false;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric namespace lldb_private {
860b57cec5SDimitry Andric namespace formatters {
870b57cec5SDimitry Andric class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
880b57cec5SDimitry Andric public:
890b57cec5SDimitry Andric LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric ~LibcxxStdAtomicSyntheticFrontEnd() override = default;
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric size_t CalculateNumChildren() override;
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric bool Update() override;
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric bool MightHaveChildren() override;
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override;
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric private:
10481ad6265SDimitry Andric ValueObject *m_real_child = nullptr;
1050b57cec5SDimitry Andric };
1060b57cec5SDimitry Andric } // namespace formatters
1070b57cec5SDimitry Andric } // namespace lldb_private
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)1100b57cec5SDimitry Andric LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
11181ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp) {}
1120b57cec5SDimitry Andric
Update()1130b57cec5SDimitry Andric bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() {
1140b57cec5SDimitry Andric ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend);
1150b57cec5SDimitry Andric if (atomic_value)
1160b57cec5SDimitry Andric m_real_child = GetLibCxxAtomicValue(m_backend).get();
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric return false;
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
MightHaveChildren()1220b57cec5SDimitry Andric MightHaveChildren() {
1230b57cec5SDimitry Andric return true;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
CalculateNumChildren()1270b57cec5SDimitry Andric CalculateNumChildren() {
1285ffd83dbSDimitry Andric return m_real_child ? 1 : 0;
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric lldb::ValueObjectSP
GetChildAtIndex(size_t idx)1320b57cec5SDimitry Andric lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex(
1330b57cec5SDimitry Andric size_t idx) {
1345ffd83dbSDimitry Andric if (idx == 0)
1355ffd83dbSDimitry Andric return m_real_child->GetSP()->Clone(ConstString("Value"));
1365ffd83dbSDimitry Andric return nullptr;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)1400b57cec5SDimitry Andric GetIndexOfChildWithName(ConstString name) {
141*fe013be4SDimitry Andric return name == "Value" ? 0 : UINT32_MAX;
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric SyntheticChildrenFrontEnd *
LibcxxAtomicSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)1450b57cec5SDimitry Andric lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator(
1460b57cec5SDimitry Andric CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
1470b57cec5SDimitry Andric if (valobj_sp)
1480b57cec5SDimitry Andric return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp);
1490b57cec5SDimitry Andric return nullptr;
1500b57cec5SDimitry Andric }
151