//===-- SBTypeSummary.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 "lldb/API/SBTypeSummary.h" #include "SBReproducerPrivate.h" #include "Utils.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBValue.h" #include "lldb/DataFormatters/DataVisualization.h" #include "llvm/Support/Casting.h" using namespace lldb; using namespace lldb_private; SBTypeSummaryOptions::SBTypeSummaryOptions() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTypeSummaryOptions); m_opaque_up = std::make_unique(); } SBTypeSummaryOptions::SBTypeSummaryOptions( const lldb::SBTypeSummaryOptions &rhs) { LLDB_RECORD_CONSTRUCTOR(SBTypeSummaryOptions, (const lldb::SBTypeSummaryOptions &), rhs); m_opaque_up = clone(rhs.m_opaque_up); } SBTypeSummaryOptions::~SBTypeSummaryOptions() = default; bool SBTypeSummaryOptions::IsValid() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummaryOptions, IsValid); return this->operator bool(); } SBTypeSummaryOptions::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummaryOptions, operator bool); return m_opaque_up.get(); } lldb::LanguageType SBTypeSummaryOptions::GetLanguage() { LLDB_RECORD_METHOD_NO_ARGS(lldb::LanguageType, SBTypeSummaryOptions, GetLanguage); if (IsValid()) return m_opaque_up->GetLanguage(); return lldb::eLanguageTypeUnknown; } lldb::TypeSummaryCapping SBTypeSummaryOptions::GetCapping() { LLDB_RECORD_METHOD_NO_ARGS(lldb::TypeSummaryCapping, SBTypeSummaryOptions, GetCapping); if (IsValid()) return m_opaque_up->GetCapping(); return eTypeSummaryCapped; } void SBTypeSummaryOptions::SetLanguage(lldb::LanguageType l) { LLDB_RECORD_METHOD(void, SBTypeSummaryOptions, SetLanguage, (lldb::LanguageType), l); if (IsValid()) m_opaque_up->SetLanguage(l); } void SBTypeSummaryOptions::SetCapping(lldb::TypeSummaryCapping c) { LLDB_RECORD_METHOD(void, SBTypeSummaryOptions, SetCapping, (lldb::TypeSummaryCapping), c); if (IsValid()) m_opaque_up->SetCapping(c); } lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::operator->() { return m_opaque_up.get(); } const lldb_private::TypeSummaryOptions *SBTypeSummaryOptions:: operator->() const { return m_opaque_up.get(); } lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::get() { return m_opaque_up.get(); } lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() { return *m_opaque_up; } const lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() const { return *m_opaque_up; } SBTypeSummaryOptions::SBTypeSummaryOptions( const lldb_private::TypeSummaryOptions *lldb_object_ptr) { LLDB_RECORD_CONSTRUCTOR(SBTypeSummaryOptions, (const lldb_private::TypeSummaryOptions *), lldb_object_ptr); SetOptions(lldb_object_ptr); } void SBTypeSummaryOptions::SetOptions( const lldb_private::TypeSummaryOptions *lldb_object_ptr) { if (lldb_object_ptr) m_opaque_up = std::make_unique(*lldb_object_ptr); else m_opaque_up = std::make_unique(); } SBTypeSummary::SBTypeSummary() : m_opaque_sp() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTypeSummary); } SBTypeSummary SBTypeSummary::CreateWithSummaryString(const char *data, uint32_t options) { LLDB_RECORD_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary, CreateWithSummaryString, (const char *, uint32_t), data, options); if (!data || data[0] == 0) return LLDB_RECORD_RESULT(SBTypeSummary()); return LLDB_RECORD_RESULT( SBTypeSummary(TypeSummaryImplSP(new StringSummaryFormat(options, data)))); } SBTypeSummary SBTypeSummary::CreateWithFunctionName(const char *data, uint32_t options) { LLDB_RECORD_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary, CreateWithFunctionName, (const char *, uint32_t), data, options); if (!data || data[0] == 0) return LLDB_RECORD_RESULT(SBTypeSummary()); return LLDB_RECORD_RESULT( SBTypeSummary(TypeSummaryImplSP(new ScriptSummaryFormat(options, data)))); } SBTypeSummary SBTypeSummary::CreateWithScriptCode(const char *data, uint32_t options) { LLDB_RECORD_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary, CreateWithScriptCode, (const char *, uint32_t), data, options); if (!data || data[0] == 0) return LLDB_RECORD_RESULT(SBTypeSummary()); return LLDB_RECORD_RESULT(SBTypeSummary( TypeSummaryImplSP(new ScriptSummaryFormat(options, "", data)))); } SBTypeSummary SBTypeSummary::CreateWithCallback(FormatCallback cb, uint32_t options, const char *description) { LLDB_RECORD_DUMMY( lldb::SBTypeSummary, SBTypeSummary, CreateWithCallback, (lldb::SBTypeSummary::FormatCallback, uint32_t, const char *), cb, options, description); SBTypeSummary retval; if (cb) { retval.SetSP(TypeSummaryImplSP(new CXXFunctionSummaryFormat( options, [cb](ValueObject &valobj, Stream &stm, const TypeSummaryOptions &opt) -> bool { SBStream stream; SBValue sb_value(valobj.GetSP()); SBTypeSummaryOptions options(&opt); if (!cb(sb_value, options, stream)) return false; stm.Write(stream.GetData(), stream.GetSize()); return true; }, description ? description : "callback summary formatter"))); } return retval; } SBTypeSummary::SBTypeSummary(const lldb::SBTypeSummary &rhs) : m_opaque_sp(rhs.m_opaque_sp) { LLDB_RECORD_CONSTRUCTOR(SBTypeSummary, (const lldb::SBTypeSummary &), rhs); } SBTypeSummary::~SBTypeSummary() = default; bool SBTypeSummary::IsValid() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummary, IsValid); return this->operator bool(); } SBTypeSummary::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummary, operator bool); return m_opaque_sp.get() != nullptr; } bool SBTypeSummary::IsFunctionCode() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsFunctionCode); if (!IsValid()) return false; if (ScriptSummaryFormat *script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { const char *ftext = script_summary_ptr->GetPythonScript(); return (ftext && *ftext != 0); } return false; } bool SBTypeSummary::IsFunctionName() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsFunctionName); if (!IsValid()) return false; if (ScriptSummaryFormat *script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { const char *ftext = script_summary_ptr->GetPythonScript(); return (!ftext || *ftext == 0); } return false; } bool SBTypeSummary::IsSummaryString() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsSummaryString); if (!IsValid()) return false; return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString; } const char *SBTypeSummary::GetData() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTypeSummary, GetData); if (!IsValid()) return nullptr; if (ScriptSummaryFormat *script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { const char *fname = script_summary_ptr->GetFunctionName(); const char *ftext = script_summary_ptr->GetPythonScript(); if (ftext && *ftext) return ftext; return fname; } else if (StringSummaryFormat *string_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) return string_summary_ptr->GetSummaryString(); return nullptr; } uint32_t SBTypeSummary::GetOptions() { LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBTypeSummary, GetOptions); if (!IsValid()) return lldb::eTypeOptionNone; return m_opaque_sp->GetOptions(); } void SBTypeSummary::SetOptions(uint32_t value) { LLDB_RECORD_METHOD(void, SBTypeSummary, SetOptions, (uint32_t), value); if (!CopyOnWrite_Impl()) return; m_opaque_sp->SetOptions(value); } void SBTypeSummary::SetSummaryString(const char *data) { LLDB_RECORD_METHOD(void, SBTypeSummary, SetSummaryString, (const char *), data); if (!IsValid()) return; if (!llvm::isa(m_opaque_sp.get())) ChangeSummaryType(false); if (StringSummaryFormat *string_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) string_summary_ptr->SetSummaryString(data); } void SBTypeSummary::SetFunctionName(const char *data) { LLDB_RECORD_METHOD(void, SBTypeSummary, SetFunctionName, (const char *), data); if (!IsValid()) return; if (!llvm::isa(m_opaque_sp.get())) ChangeSummaryType(true); if (ScriptSummaryFormat *script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) script_summary_ptr->SetFunctionName(data); } void SBTypeSummary::SetFunctionCode(const char *data) { LLDB_RECORD_METHOD(void, SBTypeSummary, SetFunctionCode, (const char *), data); if (!IsValid()) return; if (!llvm::isa(m_opaque_sp.get())) ChangeSummaryType(true); if (ScriptSummaryFormat *script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) script_summary_ptr->SetPythonScript(data); } bool SBTypeSummary::GetDescription(lldb::SBStream &description, lldb::DescriptionLevel description_level) { LLDB_RECORD_METHOD(bool, SBTypeSummary, GetDescription, (lldb::SBStream &, lldb::DescriptionLevel), description, description_level); if (!CopyOnWrite_Impl()) return false; else { description.Printf("%s\n", m_opaque_sp->GetDescription().c_str()); return true; } } bool SBTypeSummary::DoesPrintValue(lldb::SBValue value) { LLDB_RECORD_METHOD(bool, SBTypeSummary, DoesPrintValue, (lldb::SBValue), value); if (!IsValid()) return false; lldb::ValueObjectSP value_sp = value.GetSP(); return m_opaque_sp->DoesPrintValue(value_sp.get()); } lldb::SBTypeSummary &SBTypeSummary::operator=(const lldb::SBTypeSummary &rhs) { LLDB_RECORD_METHOD(lldb::SBTypeSummary &, SBTypeSummary, operator=,(const lldb::SBTypeSummary &), rhs); if (this != &rhs) { m_opaque_sp = rhs.m_opaque_sp; } return LLDB_RECORD_RESULT(*this); } bool SBTypeSummary::operator==(lldb::SBTypeSummary &rhs) { LLDB_RECORD_METHOD(bool, SBTypeSummary, operator==,(lldb::SBTypeSummary &), rhs); if (!IsValid()) return !rhs.IsValid(); return m_opaque_sp == rhs.m_opaque_sp; } bool SBTypeSummary::IsEqualTo(lldb::SBTypeSummary &rhs) { LLDB_RECORD_METHOD(bool, SBTypeSummary, IsEqualTo, (lldb::SBTypeSummary &), rhs); if (IsValid()) { // valid and invalid are different if (!rhs.IsValid()) return false; } else { // invalid and valid are different if (rhs.IsValid()) return false; else // both invalid are the same return true; } if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind()) return false; switch (m_opaque_sp->GetKind()) { case TypeSummaryImpl::Kind::eCallback: return llvm::dyn_cast(m_opaque_sp.get()) == llvm::dyn_cast(rhs.m_opaque_sp.get()); case TypeSummaryImpl::Kind::eScript: if (IsFunctionCode() != rhs.IsFunctionCode()) return false; if (IsFunctionName() != rhs.IsFunctionName()) return false; return GetOptions() == rhs.GetOptions(); case TypeSummaryImpl::Kind::eSummaryString: if (IsSummaryString() != rhs.IsSummaryString()) return false; return GetOptions() == rhs.GetOptions(); case TypeSummaryImpl::Kind::eInternal: return (m_opaque_sp.get() == rhs.m_opaque_sp.get()); } return false; } bool SBTypeSummary::operator!=(lldb::SBTypeSummary &rhs) { LLDB_RECORD_METHOD(bool, SBTypeSummary, operator!=,(lldb::SBTypeSummary &), rhs); if (!IsValid()) return !rhs.IsValid(); return m_opaque_sp != rhs.m_opaque_sp; } lldb::TypeSummaryImplSP SBTypeSummary::GetSP() { return m_opaque_sp; } void SBTypeSummary::SetSP(const lldb::TypeSummaryImplSP &typesummary_impl_sp) { m_opaque_sp = typesummary_impl_sp; } SBTypeSummary::SBTypeSummary(const lldb::TypeSummaryImplSP &typesummary_impl_sp) : m_opaque_sp(typesummary_impl_sp) {} bool SBTypeSummary::CopyOnWrite_Impl() { if (!IsValid()) return false; if (m_opaque_sp.unique()) return true; TypeSummaryImplSP new_sp; if (CXXFunctionSummaryFormat *current_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat( GetOptions(), current_summary_ptr->m_impl, current_summary_ptr->m_description.c_str())); } else if (ScriptSummaryFormat *current_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { new_sp = TypeSummaryImplSP(new ScriptSummaryFormat( GetOptions(), current_summary_ptr->GetFunctionName(), current_summary_ptr->GetPythonScript())); } else if (StringSummaryFormat *current_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { new_sp = TypeSummaryImplSP(new StringSummaryFormat( GetOptions(), current_summary_ptr->GetSummaryString())); } SetSP(new_sp); return nullptr != new_sp.get(); } bool SBTypeSummary::ChangeSummaryType(bool want_script) { if (!IsValid()) return false; TypeSummaryImplSP new_sp; if (want_script == (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript)) { if (m_opaque_sp->GetKind() == lldb_private::TypeSummaryImpl::Kind::eCallback && !want_script) new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), "")); else return CopyOnWrite_Impl(); } if (!new_sp) { if (want_script) new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", "")); else new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), "")); } SetSP(new_sp); return true; } namespace lldb_private { namespace repro { template <> void RegisterMethods(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBTypeSummaryOptions, ()); LLDB_REGISTER_CONSTRUCTOR(SBTypeSummaryOptions, (const lldb::SBTypeSummaryOptions &)); LLDB_REGISTER_METHOD(bool, SBTypeSummaryOptions, IsValid, ()); LLDB_REGISTER_METHOD_CONST(bool, SBTypeSummaryOptions, operator bool, ()); LLDB_REGISTER_METHOD(lldb::LanguageType, SBTypeSummaryOptions, GetLanguage, ()); LLDB_REGISTER_METHOD(lldb::TypeSummaryCapping, SBTypeSummaryOptions, GetCapping, ()); LLDB_REGISTER_METHOD(void, SBTypeSummaryOptions, SetLanguage, (lldb::LanguageType)); LLDB_REGISTER_METHOD(void, SBTypeSummaryOptions, SetCapping, (lldb::TypeSummaryCapping)); LLDB_REGISTER_CONSTRUCTOR(SBTypeSummaryOptions, (const lldb_private::TypeSummaryOptions *)); } template <> void RegisterMethods(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBTypeSummary, ()); LLDB_REGISTER_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary, CreateWithSummaryString, (const char *, uint32_t)); LLDB_REGISTER_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary, CreateWithFunctionName, (const char *, uint32_t)); LLDB_REGISTER_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary, CreateWithScriptCode, (const char *, uint32_t)); LLDB_REGISTER_CONSTRUCTOR(SBTypeSummary, (const lldb::SBTypeSummary &)); LLDB_REGISTER_METHOD_CONST(bool, SBTypeSummary, IsValid, ()); LLDB_REGISTER_METHOD_CONST(bool, SBTypeSummary, operator bool, ()); LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsFunctionCode, ()); LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsFunctionName, ()); LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsSummaryString, ()); LLDB_REGISTER_METHOD(const char *, SBTypeSummary, GetData, ()); LLDB_REGISTER_METHOD(uint32_t, SBTypeSummary, GetOptions, ()); LLDB_REGISTER_METHOD(void, SBTypeSummary, SetOptions, (uint32_t)); LLDB_REGISTER_METHOD(void, SBTypeSummary, SetSummaryString, (const char *)); LLDB_REGISTER_METHOD(void, SBTypeSummary, SetFunctionName, (const char *)); LLDB_REGISTER_METHOD(void, SBTypeSummary, SetFunctionCode, (const char *)); LLDB_REGISTER_METHOD(bool, SBTypeSummary, GetDescription, (lldb::SBStream &, lldb::DescriptionLevel)); LLDB_REGISTER_METHOD(bool, SBTypeSummary, DoesPrintValue, (lldb::SBValue)); LLDB_REGISTER_METHOD( lldb::SBTypeSummary &, SBTypeSummary, operator=,(const lldb::SBTypeSummary &)); LLDB_REGISTER_METHOD(bool, SBTypeSummary, operator==,(lldb::SBTypeSummary &)); LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsEqualTo, (lldb::SBTypeSummary &)); LLDB_REGISTER_METHOD(bool, SBTypeSummary, operator!=,(lldb::SBTypeSummary &)); } } }