| //===-- LibCxxAtomic.cpp --------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "LibCxxAtomic.h" |
| #include "lldb/DataFormatters/FormattersHelpers.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| using namespace lldb_private::formatters; |
| |
| // |
| // We are supporting two versions of libc++ std::atomic |
| // |
| // Given std::atomic<int> i; |
| // |
| // The previous version of std::atomic was laid out like this |
| // |
| // (lldb) frame var -L -R i |
| // 0x00007ffeefbff9a0: (std::__1::atomic<int>) i = { |
| // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, true> = { |
| // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, false> = { |
| // 0x00007ffeefbff9a0: __a_ = 5 |
| // } |
| // } |
| // } |
| // |
| // In this case we need to obtain __a_ and the current version is laid out as so |
| // |
| // (lldb) frame var -L -R i |
| // 0x00007ffeefbff9b0: (std::__1::atomic<int>) i = { |
| // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, true> = { |
| // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, false> = { |
| // 0x00007ffeefbff9b0: __a_ = { |
| // 0x00007ffeefbff9b0: std::__1::__cxx_atomic_base_impl<int> = { |
| // 0x00007ffeefbff9b0: __a_value = 5 |
| // } |
| // } |
| // } |
| // } |
| //} |
| // |
| // In this case we need to obtain __a_value |
| // |
| // The below method covers both cases and returns the relevant member as a |
| // ValueObjectSP |
| // |
| ValueObjectSP |
| lldb_private::formatters::GetLibCxxAtomicValue(ValueObject &valobj) { |
| ValueObjectSP non_sythetic = valobj.GetNonSyntheticValue(); |
| if (!non_sythetic) |
| return {}; |
| |
| ValueObjectSP member__a_ = |
| non_sythetic->GetChildMemberWithName(ConstString("__a_"), true); |
| if (!member__a_) |
| return {}; |
| |
| ValueObjectSP member__a_value = |
| member__a_->GetChildMemberWithName(ConstString("__a_value"), true); |
| if (!member__a_value) |
| return member__a_; |
| |
| return member__a_value; |
| } |
| |
| bool lldb_private::formatters::LibCxxAtomicSummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { |
| |
| if (ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj)) { |
| std::string summary; |
| if (atomic_value->GetSummaryAsCString(summary, options) && |
| summary.size() > 0) { |
| stream.Printf("%s", summary.c_str()); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| namespace lldb_private { |
| namespace formatters { |
| class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd { |
| public: |
| LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); |
| |
| ~LibcxxStdAtomicSyntheticFrontEnd() override = default; |
| |
| size_t CalculateNumChildren() override; |
| |
| lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; |
| |
| bool Update() override; |
| |
| bool MightHaveChildren() override; |
| |
| size_t GetIndexOfChildWithName(ConstString name) override; |
| |
| private: |
| ValueObject *m_real_child; |
| }; |
| } // namespace formatters |
| } // namespace lldb_private |
| |
| lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: |
| LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) |
| : SyntheticChildrenFrontEnd(*valobj_sp), m_real_child(nullptr) {} |
| |
| bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() { |
| ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend); |
| if (atomic_value) |
| m_real_child = GetLibCxxAtomicValue(m_backend).get(); |
| |
| return false; |
| } |
| |
| bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: |
| MightHaveChildren() { |
| return true; |
| } |
| |
| size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: |
| CalculateNumChildren() { |
| return m_real_child ? 1 : 0; |
| } |
| |
| lldb::ValueObjectSP |
| lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex( |
| size_t idx) { |
| if (idx == 0) |
| return m_real_child->GetSP()->Clone(ConstString("Value")); |
| return nullptr; |
| } |
| |
| size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: |
| GetIndexOfChildWithName(ConstString name) { |
| return formatters::ExtractIndexFromString(name.GetCString()); |
| } |
| |
| SyntheticChildrenFrontEnd * |
| lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator( |
| CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { |
| if (valobj_sp) |
| return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp); |
| return nullptr; |
| } |