180814287SRaphael Isemann //===-- BlockPointer.cpp --------------------------------------------------===//
2c530ba98SSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c530ba98SSean Callanan //
7c530ba98SSean Callanan //===----------------------------------------------------------------------===//
8c530ba98SSean Callanan
9c530ba98SSean Callanan #include "BlockPointer.h"
10c530ba98SSean Callanan
118be30215SAlex Langford #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
12c4f6fbe9SAlex Langford #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
138be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14c530ba98SSean Callanan #include "lldb/Core/ValueObject.h"
15c530ba98SSean Callanan #include "lldb/DataFormatters/FormattersHelpers.h"
16c530ba98SSean Callanan #include "lldb/Symbol/CompilerType.h"
17c530ba98SSean Callanan #include "lldb/Symbol/TypeSystem.h"
18c530ba98SSean Callanan #include "lldb/Target/Target.h"
19c530ba98SSean Callanan #include "lldb/Utility/LLDBAssert.h"
20*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
210e252e38SAlex Langford #include "lldb/Utility/Log.h"
22c530ba98SSean Callanan
23c530ba98SSean Callanan using namespace lldb;
24c530ba98SSean Callanan using namespace lldb_private;
25c530ba98SSean Callanan using namespace lldb_private::formatters;
26c530ba98SSean Callanan
27b9c1b51eSKate Stone namespace lldb_private {
28b9c1b51eSKate Stone namespace formatters {
29c530ba98SSean Callanan
30b9c1b51eSKate Stone class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
31c530ba98SSean Callanan public:
BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)32c530ba98SSean Callanan BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
33b9c1b51eSKate Stone : SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {
34c530ba98SSean Callanan CompilerType block_pointer_type(m_backend.GetCompilerType());
35c530ba98SSean Callanan CompilerType function_pointer_type;
36c530ba98SSean Callanan block_pointer_type.IsBlockPointerType(&function_pointer_type);
37c530ba98SSean Callanan
38c530ba98SSean Callanan TargetSP target_sp(m_backend.GetTargetSP());
39c530ba98SSean Callanan
40b9c1b51eSKate Stone if (!target_sp) {
41c530ba98SSean Callanan return;
42c530ba98SSean Callanan }
43c530ba98SSean Callanan
440e252e38SAlex Langford auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage(
450e252e38SAlex Langford lldb::eLanguageTypeC_plus_plus);
460e252e38SAlex Langford if (auto err = type_system_or_err.takeError()) {
47a007a6d8SPavel Labath LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(err),
48a007a6d8SPavel Labath "Failed to get scratch TypeSystemClang");
49c530ba98SSean Callanan return;
50c530ba98SSean Callanan }
51c530ba98SSean Callanan
526e3b0cc2SRaphael Isemann TypeSystemClang *clang_ast_context =
53839e8452SRaphael Isemann llvm::cast<TypeSystemClang>(block_pointer_type.GetTypeSystem());
54c530ba98SSean Callanan
557c9ebdd3SAlex Langford std::shared_ptr<ClangASTImporter> clang_ast_importer;
56c4f6fbe9SAlex Langford auto *state = target_sp->GetPersistentExpressionStateForLanguage(
57c4f6fbe9SAlex Langford lldb::eLanguageTypeC_plus_plus);
58c4f6fbe9SAlex Langford if (state) {
59c4f6fbe9SAlex Langford auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
60c4f6fbe9SAlex Langford clang_ast_importer = persistent_vars->GetClangASTImporter();
61c4f6fbe9SAlex Langford }
62c530ba98SSean Callanan
63b9c1b51eSKate Stone if (!clang_ast_importer) {
64c530ba98SSean Callanan return;
65c530ba98SSean Callanan }
66c530ba98SSean Callanan
67c530ba98SSean Callanan const char *const isa_name("__isa");
68b9c1b51eSKate Stone const CompilerType isa_type =
69b9c1b51eSKate Stone clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);
70c530ba98SSean Callanan const char *const flags_name("__flags");
71b9c1b51eSKate Stone const CompilerType flags_type =
72b9c1b51eSKate Stone clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
73c530ba98SSean Callanan const char *const reserved_name("__reserved");
74b9c1b51eSKate Stone const CompilerType reserved_type =
75b9c1b51eSKate Stone clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
76c530ba98SSean Callanan const char *const FuncPtr_name("__FuncPtr");
77c530ba98SSean Callanan
78b9c1b51eSKate Stone m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
79b9c1b51eSKate Stone ConstString(), {{isa_name, isa_type},
80c530ba98SSean Callanan {flags_name, flags_type},
81c530ba98SSean Callanan {reserved_name, reserved_type},
824f14c17dSShafik Yaghmour {FuncPtr_name, function_pointer_type}});
83c530ba98SSean Callanan }
84c530ba98SSean Callanan
85c530ba98SSean Callanan ~BlockPointerSyntheticFrontEnd() override = default;
86c530ba98SSean Callanan
CalculateNumChildren()87b9c1b51eSKate Stone size_t CalculateNumChildren() override {
88c530ba98SSean Callanan const bool omit_empty_base_classes = false;
89eca07c59SAdrian Prantl return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);
90c530ba98SSean Callanan }
91c530ba98SSean Callanan
GetChildAtIndex(size_t idx)92b9c1b51eSKate Stone lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
93b9c1b51eSKate Stone if (!m_block_struct_type.IsValid()) {
94c530ba98SSean Callanan return lldb::ValueObjectSP();
95c530ba98SSean Callanan }
96c530ba98SSean Callanan
97b9c1b51eSKate Stone if (idx >= CalculateNumChildren()) {
98c530ba98SSean Callanan return lldb::ValueObjectSP();
99c530ba98SSean Callanan }
100c530ba98SSean Callanan
101c530ba98SSean Callanan const bool thread_and_frame_only_if_stopped = true;
102b9c1b51eSKate Stone ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(
103b9c1b51eSKate Stone thread_and_frame_only_if_stopped);
104c530ba98SSean Callanan const bool transparent_pointers = false;
105c530ba98SSean Callanan const bool omit_empty_base_classes = false;
106c530ba98SSean Callanan const bool ignore_array_bounds = false;
107c530ba98SSean Callanan ValueObject *value_object = nullptr;
108c530ba98SSean Callanan
109c530ba98SSean Callanan std::string child_name;
110c530ba98SSean Callanan uint32_t child_byte_size = 0;
111c530ba98SSean Callanan int32_t child_byte_offset = 0;
112c530ba98SSean Callanan uint32_t child_bitfield_bit_size = 0;
113c530ba98SSean Callanan uint32_t child_bitfield_bit_offset = 0;
114c530ba98SSean Callanan bool child_is_base_class = false;
115c530ba98SSean Callanan bool child_is_deref_of_parent = false;
116c530ba98SSean Callanan uint64_t language_flags = 0;
117c530ba98SSean Callanan
118b9c1b51eSKate Stone const CompilerType child_type =
119b9c1b51eSKate Stone m_block_struct_type.GetChildCompilerTypeAtIndex(
120b9c1b51eSKate Stone &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
121b9c1b51eSKate Stone ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
122b9c1b51eSKate Stone child_bitfield_bit_size, child_bitfield_bit_offset,
123b9c1b51eSKate Stone child_is_base_class, child_is_deref_of_parent, value_object,
124b9c1b51eSKate Stone language_flags);
125c530ba98SSean Callanan
126b9c1b51eSKate Stone ValueObjectSP struct_pointer_sp =
127b9c1b51eSKate Stone m_backend.Cast(m_block_struct_type.GetPointerType());
128c530ba98SSean Callanan
129b9c1b51eSKate Stone if (!struct_pointer_sp) {
130c530ba98SSean Callanan return lldb::ValueObjectSP();
131c530ba98SSean Callanan }
132c530ba98SSean Callanan
13397206d57SZachary Turner Status err;
134c530ba98SSean Callanan ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);
135c530ba98SSean Callanan
136b9c1b51eSKate Stone if (!struct_sp || !err.Success()) {
137c530ba98SSean Callanan return lldb::ValueObjectSP();
138c530ba98SSean Callanan }
139c530ba98SSean Callanan
140b9c1b51eSKate Stone ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(
141b9c1b51eSKate Stone child_byte_offset, child_type, true,
142c530ba98SSean Callanan ConstString(child_name.c_str(), child_name.size())));
143c530ba98SSean Callanan
144c530ba98SSean Callanan return child_sp;
145c530ba98SSean Callanan }
146c530ba98SSean Callanan
14705097246SAdrian Prantl // return true if this object is now safe to use forever without ever
14805097246SAdrian Prantl // updating again; the typical (and tested) answer here is 'false'
Update()149b9c1b51eSKate Stone bool Update() override { return false; }
150c530ba98SSean Callanan
151c530ba98SSean Callanan // maybe return false if the block pointer is, say, null
MightHaveChildren()152b9c1b51eSKate Stone bool MightHaveChildren() override { return true; }
153c530ba98SSean Callanan
GetIndexOfChildWithName(ConstString name)1540e4c4821SAdrian Prantl size_t GetIndexOfChildWithName(ConstString name) override {
155c530ba98SSean Callanan if (!m_block_struct_type.IsValid())
156c530ba98SSean Callanan return UINT32_MAX;
157c530ba98SSean Callanan
158c530ba98SSean Callanan const bool omit_empty_base_classes = false;
159b9c1b51eSKate Stone return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
160b9c1b51eSKate Stone omit_empty_base_classes);
161c530ba98SSean Callanan }
162c530ba98SSean Callanan
163c530ba98SSean Callanan private:
164c530ba98SSean Callanan CompilerType m_block_struct_type;
165c530ba98SSean Callanan };
166c530ba98SSean Callanan
167c530ba98SSean Callanan } // namespace formatters
168c530ba98SSean Callanan } // namespace lldb_private
169c530ba98SSean Callanan
BlockPointerSummaryProvider(ValueObject & valobj,Stream & s,const TypeSummaryOptions &)170b9c1b51eSKate Stone bool lldb_private::formatters::BlockPointerSummaryProvider(
171b9c1b51eSKate Stone ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
172b9c1b51eSKate Stone lldb_private::SyntheticChildrenFrontEnd *synthetic_children =
173b9c1b51eSKate Stone BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
174b9c1b51eSKate Stone if (!synthetic_children) {
175c530ba98SSean Callanan return false;
176c530ba98SSean Callanan }
177c530ba98SSean Callanan
178c530ba98SSean Callanan synthetic_children->Update();
179c530ba98SSean Callanan
180c530ba98SSean Callanan static const ConstString s_FuncPtr_name("__FuncPtr");
181c530ba98SSean Callanan
182b9c1b51eSKate Stone lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
183b9c1b51eSKate Stone synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
184c530ba98SSean Callanan
185b9c1b51eSKate Stone if (!child_sp) {
186c530ba98SSean Callanan return false;
187c530ba98SSean Callanan }
188c530ba98SSean Callanan
189b9c1b51eSKate Stone lldb::ValueObjectSP qualified_child_representation_sp =
190b9c1b51eSKate Stone child_sp->GetQualifiedRepresentationIfAvailable(
191b9c1b51eSKate Stone lldb::eDynamicDontRunTarget, true);
192c530ba98SSean Callanan
193b9c1b51eSKate Stone const char *child_value =
194b9c1b51eSKate Stone qualified_child_representation_sp->GetValueAsCString();
195c530ba98SSean Callanan
196c530ba98SSean Callanan s.Printf("%s", child_value);
197c530ba98SSean Callanan
198c530ba98SSean Callanan return true;
199c530ba98SSean Callanan }
200c530ba98SSean Callanan
201c530ba98SSean Callanan lldb_private::SyntheticChildrenFrontEnd *
BlockPointerSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)202b9c1b51eSKate Stone lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(
203b9c1b51eSKate Stone CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
204c530ba98SSean Callanan if (!valobj_sp)
205c530ba98SSean Callanan return nullptr;
206c530ba98SSean Callanan return new BlockPointerSyntheticFrontEnd(valobj_sp);
207c530ba98SSean Callanan }
208