15ffd83dbSDimitry Andric //===-- BlockPointer.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 "BlockPointer.h"
100b57cec5SDimitry Andric
115ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
125ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
135ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
140b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
150b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
160b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
170b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h"
180b57cec5SDimitry Andric #include "lldb/Target/Target.h"
190b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
2081ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
219dba64beSDimitry Andric #include "lldb/Utility/Log.h"
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric using namespace lldb;
240b57cec5SDimitry Andric using namespace lldb_private;
250b57cec5SDimitry Andric using namespace lldb_private::formatters;
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric namespace lldb_private {
280b57cec5SDimitry Andric namespace formatters {
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
310b57cec5SDimitry Andric public:
BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)320b57cec5SDimitry Andric BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
330b57cec5SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {
340b57cec5SDimitry Andric CompilerType block_pointer_type(m_backend.GetCompilerType());
350b57cec5SDimitry Andric CompilerType function_pointer_type;
360b57cec5SDimitry Andric block_pointer_type.IsBlockPointerType(&function_pointer_type);
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric TargetSP target_sp(m_backend.GetTargetSP());
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric if (!target_sp) {
410b57cec5SDimitry Andric return;
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric
449dba64beSDimitry Andric auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage(
459dba64beSDimitry Andric lldb::eLanguageTypeC_plus_plus);
469dba64beSDimitry Andric if (auto err = type_system_or_err.takeError()) {
4781ad6265SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(err),
4806c3fb27SDimitry Andric "Failed to get scratch TypeSystemClang: {0}");
490b57cec5SDimitry Andric return;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric
52bdd1243dSDimitry Andric auto ts = block_pointer_type.GetTypeSystem();
53bdd1243dSDimitry Andric auto clang_ast_context = ts.dyn_cast_or_null<TypeSystemClang>();
54bdd1243dSDimitry Andric if (!clang_ast_context)
55bdd1243dSDimitry Andric return;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric const char *const isa_name("__isa");
580b57cec5SDimitry Andric const CompilerType isa_type =
590b57cec5SDimitry Andric clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);
600b57cec5SDimitry Andric const char *const flags_name("__flags");
610b57cec5SDimitry Andric const CompilerType flags_type =
620b57cec5SDimitry Andric clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
630b57cec5SDimitry Andric const char *const reserved_name("__reserved");
640b57cec5SDimitry Andric const CompilerType reserved_type =
650b57cec5SDimitry Andric clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
660b57cec5SDimitry Andric const char *const FuncPtr_name("__FuncPtr");
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
6906c3fb27SDimitry Andric llvm::StringRef(), {{isa_name, isa_type},
700b57cec5SDimitry Andric {flags_name, flags_type},
710b57cec5SDimitry Andric {reserved_name, reserved_type},
72fe6060f1SDimitry Andric {FuncPtr_name, function_pointer_type}});
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric ~BlockPointerSyntheticFrontEnd() override = default;
760b57cec5SDimitry Andric
CalculateNumChildren()770b57cec5SDimitry Andric size_t CalculateNumChildren() override {
780b57cec5SDimitry Andric const bool omit_empty_base_classes = false;
790b57cec5SDimitry Andric return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric
GetChildAtIndex(size_t idx)820b57cec5SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
830b57cec5SDimitry Andric if (!m_block_struct_type.IsValid()) {
840b57cec5SDimitry Andric return lldb::ValueObjectSP();
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric if (idx >= CalculateNumChildren()) {
880b57cec5SDimitry Andric return lldb::ValueObjectSP();
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric const bool thread_and_frame_only_if_stopped = true;
920b57cec5SDimitry Andric ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(
930b57cec5SDimitry Andric thread_and_frame_only_if_stopped);
940b57cec5SDimitry Andric const bool transparent_pointers = false;
950b57cec5SDimitry Andric const bool omit_empty_base_classes = false;
960b57cec5SDimitry Andric const bool ignore_array_bounds = false;
970b57cec5SDimitry Andric ValueObject *value_object = nullptr;
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric std::string child_name;
1000b57cec5SDimitry Andric uint32_t child_byte_size = 0;
1010b57cec5SDimitry Andric int32_t child_byte_offset = 0;
1020b57cec5SDimitry Andric uint32_t child_bitfield_bit_size = 0;
1030b57cec5SDimitry Andric uint32_t child_bitfield_bit_offset = 0;
1040b57cec5SDimitry Andric bool child_is_base_class = false;
1050b57cec5SDimitry Andric bool child_is_deref_of_parent = false;
1060b57cec5SDimitry Andric uint64_t language_flags = 0;
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric const CompilerType child_type =
1090b57cec5SDimitry Andric m_block_struct_type.GetChildCompilerTypeAtIndex(
1100b57cec5SDimitry Andric &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
1110b57cec5SDimitry Andric ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
1120b57cec5SDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset,
1130b57cec5SDimitry Andric child_is_base_class, child_is_deref_of_parent, value_object,
1140b57cec5SDimitry Andric language_flags);
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric ValueObjectSP struct_pointer_sp =
1170b57cec5SDimitry Andric m_backend.Cast(m_block_struct_type.GetPointerType());
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric if (!struct_pointer_sp) {
1200b57cec5SDimitry Andric return lldb::ValueObjectSP();
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric Status err;
1240b57cec5SDimitry Andric ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric if (!struct_sp || !err.Success()) {
1270b57cec5SDimitry Andric return lldb::ValueObjectSP();
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(
1310b57cec5SDimitry Andric child_byte_offset, child_type, true,
1320b57cec5SDimitry Andric ConstString(child_name.c_str(), child_name.size())));
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric return child_sp;
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric // return true if this object is now safe to use forever without ever
1380b57cec5SDimitry Andric // updating again; the typical (and tested) answer here is 'false'
Update()1390b57cec5SDimitry Andric bool Update() override { return false; }
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric // maybe return false if the block pointer is, say, null
MightHaveChildren()1420b57cec5SDimitry Andric bool MightHaveChildren() override { return true; }
1430b57cec5SDimitry Andric
GetIndexOfChildWithName(ConstString name)1440b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override {
1450b57cec5SDimitry Andric if (!m_block_struct_type.IsValid())
1460b57cec5SDimitry Andric return UINT32_MAX;
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric const bool omit_empty_base_classes = false;
1490b57cec5SDimitry Andric return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
1500b57cec5SDimitry Andric omit_empty_base_classes);
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric private:
1540b57cec5SDimitry Andric CompilerType m_block_struct_type;
1550b57cec5SDimitry Andric };
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric } // namespace formatters
1580b57cec5SDimitry Andric } // namespace lldb_private
1590b57cec5SDimitry Andric
BlockPointerSummaryProvider(ValueObject & valobj,Stream & s,const TypeSummaryOptions &)1600b57cec5SDimitry Andric bool lldb_private::formatters::BlockPointerSummaryProvider(
1610b57cec5SDimitry Andric ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
1620b57cec5SDimitry Andric lldb_private::SyntheticChildrenFrontEnd *synthetic_children =
1630b57cec5SDimitry Andric BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
1640b57cec5SDimitry Andric if (!synthetic_children) {
1650b57cec5SDimitry Andric return false;
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric synthetic_children->Update();
1690b57cec5SDimitry Andric
1700b57cec5SDimitry Andric static const ConstString s_FuncPtr_name("__FuncPtr");
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
1730b57cec5SDimitry Andric synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric if (!child_sp) {
1760b57cec5SDimitry Andric return false;
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric lldb::ValueObjectSP qualified_child_representation_sp =
1800b57cec5SDimitry Andric child_sp->GetQualifiedRepresentationIfAvailable(
1810b57cec5SDimitry Andric lldb::eDynamicDontRunTarget, true);
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric const char *child_value =
1840b57cec5SDimitry Andric qualified_child_representation_sp->GetValueAsCString();
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric s.Printf("%s", child_value);
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andric return true;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric lldb_private::SyntheticChildrenFrontEnd *
BlockPointerSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)1920b57cec5SDimitry Andric lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(
1930b57cec5SDimitry Andric CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
1940b57cec5SDimitry Andric if (!valobj_sp)
1950b57cec5SDimitry Andric return nullptr;
1960b57cec5SDimitry Andric return new BlockPointerSyntheticFrontEnd(valobj_sp);
1970b57cec5SDimitry Andric }
198