]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
Upgrade to OpenPAM Tabebuia.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Language / CPlusPlus / BlockPointer.cpp
1 //===-- BlockPointer.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "BlockPointer.h"
15
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/DataFormatters/FormattersHelpers.h"
18 #include "lldb/Symbol/ClangASTContext.h"
19 #include "lldb/Symbol/ClangASTImporter.h"
20 #include "lldb/Symbol/CompilerType.h"
21 #include "lldb/Symbol/TypeSystem.h"
22 #include "lldb/Target/Target.h"
23
24 #include "lldb/Utility/LLDBAssert.h"
25
26 using namespace lldb;
27 using namespace lldb_private;
28 using namespace lldb_private::formatters;
29
30 namespace lldb_private {
31 namespace formatters {
32
33 class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
34 public:
35   BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
36       : SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {
37     CompilerType block_pointer_type(m_backend.GetCompilerType());
38     CompilerType function_pointer_type;
39     block_pointer_type.IsBlockPointerType(&function_pointer_type);
40
41     TargetSP target_sp(m_backend.GetTargetSP());
42
43     if (!target_sp) {
44       return;
45     }
46
47     Status err;
48     TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(
49         &err, lldb::eLanguageTypeC_plus_plus);
50
51     if (!err.Success() || !type_system) {
52       return;
53     }
54
55     ClangASTContext *clang_ast_context =
56         llvm::dyn_cast<ClangASTContext>(type_system);
57
58     if (!clang_ast_context) {
59       return;
60     }
61
62     ClangASTImporterSP clang_ast_importer = target_sp->GetClangASTImporter();
63
64     if (!clang_ast_importer) {
65       return;
66     }
67
68     const char *const isa_name("__isa");
69     const CompilerType isa_type =
70         clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);
71     const char *const flags_name("__flags");
72     const CompilerType flags_type =
73         clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
74     const char *const reserved_name("__reserved");
75     const CompilerType reserved_type =
76         clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
77     const char *const FuncPtr_name("__FuncPtr");
78     const CompilerType FuncPtr_type =
79         clang_ast_importer->CopyType(*clang_ast_context, function_pointer_type);
80
81     m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
82         ConstString(), {{isa_name, isa_type},
83                         {flags_name, flags_type},
84                         {reserved_name, reserved_type},
85                         {FuncPtr_name, FuncPtr_type}});
86   }
87
88   ~BlockPointerSyntheticFrontEnd() override = default;
89
90   size_t CalculateNumChildren() override {
91     const bool omit_empty_base_classes = false;
92     return m_block_struct_type.GetNumChildren(omit_empty_base_classes);
93   }
94
95   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
96     if (!m_block_struct_type.IsValid()) {
97       return lldb::ValueObjectSP();
98     }
99
100     if (idx >= CalculateNumChildren()) {
101       return lldb::ValueObjectSP();
102     }
103
104     const bool thread_and_frame_only_if_stopped = true;
105     ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(
106         thread_and_frame_only_if_stopped);
107     const bool transparent_pointers = false;
108     const bool omit_empty_base_classes = false;
109     const bool ignore_array_bounds = false;
110     ValueObject *value_object = nullptr;
111
112     std::string child_name;
113     uint32_t child_byte_size = 0;
114     int32_t child_byte_offset = 0;
115     uint32_t child_bitfield_bit_size = 0;
116     uint32_t child_bitfield_bit_offset = 0;
117     bool child_is_base_class = false;
118     bool child_is_deref_of_parent = false;
119     uint64_t language_flags = 0;
120
121     const CompilerType child_type =
122         m_block_struct_type.GetChildCompilerTypeAtIndex(
123             &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
124             ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
125             child_bitfield_bit_size, child_bitfield_bit_offset,
126             child_is_base_class, child_is_deref_of_parent, value_object,
127             language_flags);
128
129     ValueObjectSP struct_pointer_sp =
130         m_backend.Cast(m_block_struct_type.GetPointerType());
131
132     if (!struct_pointer_sp) {
133       return lldb::ValueObjectSP();
134     }
135
136     Status err;
137     ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);
138
139     if (!struct_sp || !err.Success()) {
140       return lldb::ValueObjectSP();
141     }
142
143     ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(
144         child_byte_offset, child_type, true,
145         ConstString(child_name.c_str(), child_name.size())));
146
147     return child_sp;
148   }
149
150   // return true if this object is now safe to use forever without ever
151   // updating again; the typical (and tested) answer here is 'false'
152   bool Update() override { return false; }
153
154   // maybe return false if the block pointer is, say, null
155   bool MightHaveChildren() override { return true; }
156
157   size_t GetIndexOfChildWithName(const ConstString &name) override {
158     if (!m_block_struct_type.IsValid())
159       return UINT32_MAX;
160
161     const bool omit_empty_base_classes = false;
162     return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
163                                                        omit_empty_base_classes);
164   }
165
166 private:
167   CompilerType m_block_struct_type;
168 };
169
170 } // namespace formatters
171 } // namespace lldb_private
172
173 bool lldb_private::formatters::BlockPointerSummaryProvider(
174     ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
175   lldb_private::SyntheticChildrenFrontEnd *synthetic_children =
176       BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
177   if (!synthetic_children) {
178     return false;
179   }
180
181   synthetic_children->Update();
182
183   static const ConstString s_FuncPtr_name("__FuncPtr");
184
185   lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
186       synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
187
188   if (!child_sp) {
189     return false;
190   }
191
192   lldb::ValueObjectSP qualified_child_representation_sp =
193       child_sp->GetQualifiedRepresentationIfAvailable(
194           lldb::eDynamicDontRunTarget, true);
195
196   const char *child_value =
197       qualified_child_representation_sp->GetValueAsCString();
198
199   s.Printf("%s", child_value);
200
201   return true;
202 }
203
204 lldb_private::SyntheticChildrenFrontEnd *
205 lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(
206     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
207   if (!valobj_sp)
208     return nullptr;
209   return new BlockPointerSyntheticFrontEnd(valobj_sp);
210 }