xref: /openbsd-src/gnu/llvm/lldb/source/Symbol/Block.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- Block.cpp ---------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Symbol/Block.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Core/Module.h"
12061da546Spatrick #include "lldb/Core/Section.h"
13061da546Spatrick #include "lldb/Symbol/Function.h"
14061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
15061da546Spatrick #include "lldb/Symbol/VariableList.h"
16*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
17061da546Spatrick #include "lldb/Utility/Log.h"
18061da546Spatrick 
19061da546Spatrick #include <memory>
20061da546Spatrick 
21061da546Spatrick using namespace lldb;
22061da546Spatrick using namespace lldb_private;
23061da546Spatrick 
Block(lldb::user_id_t uid)24061da546Spatrick Block::Block(lldb::user_id_t uid)
25061da546Spatrick     : UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(),
26061da546Spatrick       m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),
27061da546Spatrick       m_parsed_block_variables(false), m_parsed_child_blocks(false) {}
28061da546Spatrick 
29be691f3bSpatrick Block::~Block() = default;
30061da546Spatrick 
GetDescription(Stream * s,Function * function,lldb::DescriptionLevel level,Target * target) const31061da546Spatrick void Block::GetDescription(Stream *s, Function *function,
32061da546Spatrick                            lldb::DescriptionLevel level, Target *target) const {
33061da546Spatrick   *s << "id = " << ((const UserID &)*this);
34061da546Spatrick 
35061da546Spatrick   size_t num_ranges = m_ranges.GetSize();
36061da546Spatrick   if (num_ranges > 0) {
37061da546Spatrick 
38061da546Spatrick     addr_t base_addr = LLDB_INVALID_ADDRESS;
39061da546Spatrick     if (target)
40061da546Spatrick       base_addr =
41061da546Spatrick           function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
42061da546Spatrick     if (base_addr == LLDB_INVALID_ADDRESS)
43061da546Spatrick       base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
44061da546Spatrick 
45061da546Spatrick     s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
46061da546Spatrick     for (size_t i = 0; i < num_ranges; ++i) {
47061da546Spatrick       const Range &range = m_ranges.GetEntryRef(i);
48061da546Spatrick       DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
49061da546Spatrick                        base_addr + range.GetRangeEnd(), 4);
50061da546Spatrick     }
51061da546Spatrick   }
52061da546Spatrick 
53061da546Spatrick   if (m_inlineInfoSP.get() != nullptr) {
54061da546Spatrick     bool show_fullpaths = (level == eDescriptionLevelVerbose);
55061da546Spatrick     m_inlineInfoSP->Dump(s, show_fullpaths);
56061da546Spatrick   }
57061da546Spatrick }
58061da546Spatrick 
Dump(Stream * s,addr_t base_addr,int32_t depth,bool show_context) const59061da546Spatrick void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
60061da546Spatrick                  bool show_context) const {
61061da546Spatrick   if (depth < 0) {
62061da546Spatrick     Block *parent = GetParent();
63061da546Spatrick     if (parent) {
64061da546Spatrick       // We have a depth that is less than zero, print our parent blocks first
65061da546Spatrick       parent->Dump(s, base_addr, depth + 1, show_context);
66061da546Spatrick     }
67061da546Spatrick   }
68061da546Spatrick 
69061da546Spatrick   s->Printf("%p: ", static_cast<const void *>(this));
70061da546Spatrick   s->Indent();
71061da546Spatrick   *s << "Block" << static_cast<const UserID &>(*this);
72061da546Spatrick   const Block *parent_block = GetParent();
73061da546Spatrick   if (parent_block) {
74061da546Spatrick     s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
75061da546Spatrick   }
76061da546Spatrick   if (m_inlineInfoSP.get() != nullptr) {
77061da546Spatrick     bool show_fullpaths = false;
78061da546Spatrick     m_inlineInfoSP->Dump(s, show_fullpaths);
79061da546Spatrick   }
80061da546Spatrick 
81061da546Spatrick   if (!m_ranges.IsEmpty()) {
82061da546Spatrick     *s << ", ranges =";
83061da546Spatrick 
84061da546Spatrick     size_t num_ranges = m_ranges.GetSize();
85061da546Spatrick     for (size_t i = 0; i < num_ranges; ++i) {
86061da546Spatrick       const Range &range = m_ranges.GetEntryRef(i);
87061da546Spatrick       if (parent_block != nullptr && !parent_block->Contains(range))
88061da546Spatrick         *s << '!';
89061da546Spatrick       else
90061da546Spatrick         *s << ' ';
91061da546Spatrick       DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
92061da546Spatrick                        base_addr + range.GetRangeEnd(), 4);
93061da546Spatrick     }
94061da546Spatrick   }
95061da546Spatrick   s->EOL();
96061da546Spatrick 
97061da546Spatrick   if (depth > 0) {
98061da546Spatrick     s->IndentMore();
99061da546Spatrick 
100061da546Spatrick     if (m_variable_list_sp.get()) {
101061da546Spatrick       m_variable_list_sp->Dump(s, show_context);
102061da546Spatrick     }
103061da546Spatrick 
104061da546Spatrick     collection::const_iterator pos, end = m_children.end();
105061da546Spatrick     for (pos = m_children.begin(); pos != end; ++pos)
106061da546Spatrick       (*pos)->Dump(s, base_addr, depth - 1, show_context);
107061da546Spatrick 
108061da546Spatrick     s->IndentLess();
109061da546Spatrick   }
110061da546Spatrick }
111061da546Spatrick 
FindBlockByID(user_id_t block_id)112061da546Spatrick Block *Block::FindBlockByID(user_id_t block_id) {
113061da546Spatrick   if (block_id == GetID())
114061da546Spatrick     return this;
115061da546Spatrick 
116061da546Spatrick   Block *matching_block = nullptr;
117061da546Spatrick   collection::const_iterator pos, end = m_children.end();
118061da546Spatrick   for (pos = m_children.begin(); pos != end; ++pos) {
119061da546Spatrick     matching_block = (*pos)->FindBlockByID(block_id);
120061da546Spatrick     if (matching_block)
121061da546Spatrick       break;
122061da546Spatrick   }
123061da546Spatrick   return matching_block;
124061da546Spatrick }
125061da546Spatrick 
FindInnermostBlockByOffset(const lldb::addr_t offset)126*f6aab3d8Srobert Block *Block::FindInnermostBlockByOffset(const lldb::addr_t offset) {
127*f6aab3d8Srobert   if (!Contains(offset))
128*f6aab3d8Srobert     return nullptr;
129*f6aab3d8Srobert   for (const BlockSP &block_sp : m_children) {
130*f6aab3d8Srobert     if (Block *block = block_sp->FindInnermostBlockByOffset(offset))
131*f6aab3d8Srobert       return block;
132*f6aab3d8Srobert   }
133*f6aab3d8Srobert   return this;
134*f6aab3d8Srobert }
135*f6aab3d8Srobert 
CalculateSymbolContext(SymbolContext * sc)136061da546Spatrick void Block::CalculateSymbolContext(SymbolContext *sc) {
137061da546Spatrick   if (m_parent_scope)
138061da546Spatrick     m_parent_scope->CalculateSymbolContext(sc);
139061da546Spatrick   sc->block = this;
140061da546Spatrick }
141061da546Spatrick 
CalculateSymbolContextModule()142061da546Spatrick lldb::ModuleSP Block::CalculateSymbolContextModule() {
143061da546Spatrick   if (m_parent_scope)
144061da546Spatrick     return m_parent_scope->CalculateSymbolContextModule();
145061da546Spatrick   return lldb::ModuleSP();
146061da546Spatrick }
147061da546Spatrick 
CalculateSymbolContextCompileUnit()148061da546Spatrick CompileUnit *Block::CalculateSymbolContextCompileUnit() {
149061da546Spatrick   if (m_parent_scope)
150061da546Spatrick     return m_parent_scope->CalculateSymbolContextCompileUnit();
151061da546Spatrick   return nullptr;
152061da546Spatrick }
153061da546Spatrick 
CalculateSymbolContextFunction()154061da546Spatrick Function *Block::CalculateSymbolContextFunction() {
155061da546Spatrick   if (m_parent_scope)
156061da546Spatrick     return m_parent_scope->CalculateSymbolContextFunction();
157061da546Spatrick   return nullptr;
158061da546Spatrick }
159061da546Spatrick 
CalculateSymbolContextBlock()160061da546Spatrick Block *Block::CalculateSymbolContextBlock() { return this; }
161061da546Spatrick 
DumpSymbolContext(Stream * s)162061da546Spatrick void Block::DumpSymbolContext(Stream *s) {
163061da546Spatrick   Function *function = CalculateSymbolContextFunction();
164061da546Spatrick   if (function)
165061da546Spatrick     function->DumpSymbolContext(s);
166061da546Spatrick   s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
167061da546Spatrick }
168061da546Spatrick 
DumpAddressRanges(Stream * s,lldb::addr_t base_addr)169061da546Spatrick void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {
170061da546Spatrick   if (!m_ranges.IsEmpty()) {
171061da546Spatrick     size_t num_ranges = m_ranges.GetSize();
172061da546Spatrick     for (size_t i = 0; i < num_ranges; ++i) {
173061da546Spatrick       const Range &range = m_ranges.GetEntryRef(i);
174061da546Spatrick       DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
175061da546Spatrick                        base_addr + range.GetRangeEnd(), 4);
176061da546Spatrick     }
177061da546Spatrick   }
178061da546Spatrick }
179061da546Spatrick 
Contains(addr_t range_offset) const180061da546Spatrick bool Block::Contains(addr_t range_offset) const {
181061da546Spatrick   return m_ranges.FindEntryThatContains(range_offset) != nullptr;
182061da546Spatrick }
183061da546Spatrick 
Contains(const Block * block) const184061da546Spatrick bool Block::Contains(const Block *block) const {
185061da546Spatrick   if (this == block)
186061da546Spatrick     return false; // This block doesn't contain itself...
187061da546Spatrick 
188061da546Spatrick   // Walk the parent chain for "block" and see if any if them match this block
189061da546Spatrick   const Block *block_parent;
190061da546Spatrick   for (block_parent = block->GetParent(); block_parent != nullptr;
191061da546Spatrick        block_parent = block_parent->GetParent()) {
192061da546Spatrick     if (this == block_parent)
193061da546Spatrick       return true; // One of the parents of "block" is this object!
194061da546Spatrick   }
195061da546Spatrick   return false;
196061da546Spatrick }
197061da546Spatrick 
Contains(const Range & range) const198061da546Spatrick bool Block::Contains(const Range &range) const {
199061da546Spatrick   return m_ranges.FindEntryThatContains(range) != nullptr;
200061da546Spatrick }
201061da546Spatrick 
GetParent() const202061da546Spatrick Block *Block::GetParent() const {
203061da546Spatrick   if (m_parent_scope)
204061da546Spatrick     return m_parent_scope->CalculateSymbolContextBlock();
205061da546Spatrick   return nullptr;
206061da546Spatrick }
207061da546Spatrick 
GetContainingInlinedBlock()208061da546Spatrick Block *Block::GetContainingInlinedBlock() {
209061da546Spatrick   if (GetInlinedFunctionInfo())
210061da546Spatrick     return this;
211061da546Spatrick   return GetInlinedParent();
212061da546Spatrick }
213061da546Spatrick 
GetInlinedParent()214061da546Spatrick Block *Block::GetInlinedParent() {
215061da546Spatrick   Block *parent_block = GetParent();
216061da546Spatrick   if (parent_block) {
217061da546Spatrick     if (parent_block->GetInlinedFunctionInfo())
218061da546Spatrick       return parent_block;
219061da546Spatrick     else
220061da546Spatrick       return parent_block->GetInlinedParent();
221061da546Spatrick   }
222061da546Spatrick   return nullptr;
223061da546Spatrick }
224061da546Spatrick 
GetContainingInlinedBlockWithCallSite(const Declaration & find_call_site)225061da546Spatrick Block *Block::GetContainingInlinedBlockWithCallSite(
226061da546Spatrick     const Declaration &find_call_site) {
227061da546Spatrick   Block *inlined_block = GetContainingInlinedBlock();
228061da546Spatrick 
229061da546Spatrick   while (inlined_block) {
230061da546Spatrick     const auto *function_info = inlined_block->GetInlinedFunctionInfo();
231061da546Spatrick 
232061da546Spatrick     if (function_info &&
233061da546Spatrick         function_info->GetCallSite().FileAndLineEqual(find_call_site))
234061da546Spatrick       return inlined_block;
235061da546Spatrick     inlined_block = inlined_block->GetInlinedParent();
236061da546Spatrick   }
237061da546Spatrick   return nullptr;
238061da546Spatrick }
239061da546Spatrick 
GetRangeContainingOffset(const addr_t offset,Range & range)240061da546Spatrick bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {
241061da546Spatrick   const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
242061da546Spatrick   if (range_ptr) {
243061da546Spatrick     range = *range_ptr;
244061da546Spatrick     return true;
245061da546Spatrick   }
246061da546Spatrick   range.Clear();
247061da546Spatrick   return false;
248061da546Spatrick }
249061da546Spatrick 
GetRangeContainingAddress(const Address & addr,AddressRange & range)250061da546Spatrick bool Block::GetRangeContainingAddress(const Address &addr,
251061da546Spatrick                                       AddressRange &range) {
252061da546Spatrick   Function *function = CalculateSymbolContextFunction();
253061da546Spatrick   if (function) {
254061da546Spatrick     const AddressRange &func_range = function->GetAddressRange();
255061da546Spatrick     if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
256061da546Spatrick       const addr_t addr_offset = addr.GetOffset();
257061da546Spatrick       const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
258061da546Spatrick       if (addr_offset >= func_offset &&
259061da546Spatrick           addr_offset < func_offset + func_range.GetByteSize()) {
260061da546Spatrick         addr_t offset = addr_offset - func_offset;
261061da546Spatrick 
262061da546Spatrick         const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
263061da546Spatrick 
264061da546Spatrick         if (range_ptr) {
265061da546Spatrick           range.GetBaseAddress() = func_range.GetBaseAddress();
266061da546Spatrick           range.GetBaseAddress().SetOffset(func_offset +
267061da546Spatrick                                            range_ptr->GetRangeBase());
268061da546Spatrick           range.SetByteSize(range_ptr->GetByteSize());
269061da546Spatrick           return true;
270061da546Spatrick         }
271061da546Spatrick       }
272061da546Spatrick     }
273061da546Spatrick   }
274061da546Spatrick   range.Clear();
275061da546Spatrick   return false;
276061da546Spatrick }
277061da546Spatrick 
GetRangeContainingLoadAddress(lldb::addr_t load_addr,Target & target,AddressRange & range)278061da546Spatrick bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,
279061da546Spatrick                                           Target &target, AddressRange &range) {
280061da546Spatrick   Address load_address;
281061da546Spatrick   load_address.SetLoadAddress(load_addr, &target);
282061da546Spatrick   AddressRange containing_range;
283061da546Spatrick   return GetRangeContainingAddress(load_address, containing_range);
284061da546Spatrick }
285061da546Spatrick 
GetRangeIndexContainingAddress(const Address & addr)286061da546Spatrick uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
287061da546Spatrick   Function *function = CalculateSymbolContextFunction();
288061da546Spatrick   if (function) {
289061da546Spatrick     const AddressRange &func_range = function->GetAddressRange();
290061da546Spatrick     if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
291061da546Spatrick       const addr_t addr_offset = addr.GetOffset();
292061da546Spatrick       const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
293061da546Spatrick       if (addr_offset >= func_offset &&
294061da546Spatrick           addr_offset < func_offset + func_range.GetByteSize()) {
295061da546Spatrick         addr_t offset = addr_offset - func_offset;
296061da546Spatrick         return m_ranges.FindEntryIndexThatContains(offset);
297061da546Spatrick       }
298061da546Spatrick     }
299061da546Spatrick   }
300061da546Spatrick   return UINT32_MAX;
301061da546Spatrick }
302061da546Spatrick 
GetRangeAtIndex(uint32_t range_idx,AddressRange & range)303061da546Spatrick bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
304061da546Spatrick   if (range_idx < m_ranges.GetSize()) {
305061da546Spatrick     Function *function = CalculateSymbolContextFunction();
306061da546Spatrick     if (function) {
307061da546Spatrick       const Range &vm_range = m_ranges.GetEntryRef(range_idx);
308061da546Spatrick       range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
309061da546Spatrick       range.GetBaseAddress().Slide(vm_range.GetRangeBase());
310061da546Spatrick       range.SetByteSize(vm_range.GetByteSize());
311061da546Spatrick       return true;
312061da546Spatrick     }
313061da546Spatrick   }
314061da546Spatrick   return false;
315061da546Spatrick }
316061da546Spatrick 
GetStartAddress(Address & addr)317061da546Spatrick bool Block::GetStartAddress(Address &addr) {
318061da546Spatrick   if (m_ranges.IsEmpty())
319061da546Spatrick     return false;
320061da546Spatrick 
321061da546Spatrick   Function *function = CalculateSymbolContextFunction();
322061da546Spatrick   if (function) {
323061da546Spatrick     addr = function->GetAddressRange().GetBaseAddress();
324061da546Spatrick     addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());
325061da546Spatrick     return true;
326061da546Spatrick   }
327061da546Spatrick   return false;
328061da546Spatrick }
329061da546Spatrick 
FinalizeRanges()330061da546Spatrick void Block::FinalizeRanges() {
331061da546Spatrick   m_ranges.Sort();
332061da546Spatrick   m_ranges.CombineConsecutiveRanges();
333061da546Spatrick }
334061da546Spatrick 
AddRange(const Range & range)335061da546Spatrick void Block::AddRange(const Range &range) {
336061da546Spatrick   Block *parent_block = GetParent();
337061da546Spatrick   if (parent_block && !parent_block->Contains(range)) {
338*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Symbols);
339061da546Spatrick     if (log) {
340061da546Spatrick       ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule());
341061da546Spatrick       Function *function = m_parent_scope->CalculateSymbolContextFunction();
342061da546Spatrick       const addr_t function_file_addr =
343061da546Spatrick           function->GetAddressRange().GetBaseAddress().GetFileAddress();
344061da546Spatrick       const addr_t block_start_addr = function_file_addr + range.GetRangeBase();
345061da546Spatrick       const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();
346061da546Spatrick       Type *func_type = function->GetType();
347061da546Spatrick 
348061da546Spatrick       const Declaration &func_decl = func_type->GetDeclaration();
349061da546Spatrick       if (func_decl.GetLine()) {
350061da546Spatrick         LLDB_LOGF(log,
351061da546Spatrick                   "warning: %s:%u block {0x%8.8" PRIx64
352061da546Spatrick                   "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64
353061da546Spatrick                   ") which is not contained in parent block {0x%8.8" PRIx64
354061da546Spatrick                   "} in function {0x%8.8" PRIx64 "} from %s",
355061da546Spatrick                   func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),
356061da546Spatrick                   GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
357061da546Spatrick                   block_end_addr, parent_block->GetID(), function->GetID(),
358061da546Spatrick                   module_sp->GetFileSpec().GetPath().c_str());
359061da546Spatrick       } else {
360061da546Spatrick         LLDB_LOGF(log,
361061da546Spatrick                   "warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64
362061da546Spatrick                   " - 0x%" PRIx64
363061da546Spatrick                   ") which is not contained in parent block {0x%8.8" PRIx64
364061da546Spatrick                   "} in function {0x%8.8" PRIx64 "} from %s",
365061da546Spatrick                   GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
366061da546Spatrick                   block_end_addr, parent_block->GetID(), function->GetID(),
367061da546Spatrick                   module_sp->GetFileSpec().GetPath().c_str());
368061da546Spatrick       }
369061da546Spatrick     }
370061da546Spatrick     parent_block->AddRange(range);
371061da546Spatrick   }
372061da546Spatrick   m_ranges.Append(range);
373061da546Spatrick }
374061da546Spatrick 
375061da546Spatrick // Return the current number of bytes that this object occupies in memory
MemorySize() const376061da546Spatrick size_t Block::MemorySize() const {
377061da546Spatrick   size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
378061da546Spatrick   if (m_inlineInfoSP.get())
379061da546Spatrick     mem_size += m_inlineInfoSP->MemorySize();
380061da546Spatrick   if (m_variable_list_sp.get())
381061da546Spatrick     mem_size += m_variable_list_sp->MemorySize();
382061da546Spatrick   return mem_size;
383061da546Spatrick }
384061da546Spatrick 
AddChild(const BlockSP & child_block_sp)385061da546Spatrick void Block::AddChild(const BlockSP &child_block_sp) {
386061da546Spatrick   if (child_block_sp) {
387061da546Spatrick     child_block_sp->SetParentScope(this);
388061da546Spatrick     m_children.push_back(child_block_sp);
389061da546Spatrick   }
390061da546Spatrick }
391061da546Spatrick 
SetInlinedFunctionInfo(const char * name,const char * mangled,const Declaration * decl_ptr,const Declaration * call_decl_ptr)392061da546Spatrick void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,
393061da546Spatrick                                    const Declaration *decl_ptr,
394061da546Spatrick                                    const Declaration *call_decl_ptr) {
395061da546Spatrick   m_inlineInfoSP = std::make_shared<InlineFunctionInfo>(name, mangled, decl_ptr,
396061da546Spatrick                                                         call_decl_ptr);
397061da546Spatrick }
398061da546Spatrick 
GetBlockVariableList(bool can_create)399061da546Spatrick VariableListSP Block::GetBlockVariableList(bool can_create) {
400061da546Spatrick   if (!m_parsed_block_variables) {
401061da546Spatrick     if (m_variable_list_sp.get() == nullptr && can_create) {
402061da546Spatrick       m_parsed_block_variables = true;
403061da546Spatrick       SymbolContext sc;
404061da546Spatrick       CalculateSymbolContext(&sc);
405061da546Spatrick       assert(sc.module_sp);
406061da546Spatrick       sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);
407061da546Spatrick     }
408061da546Spatrick   }
409061da546Spatrick   return m_variable_list_sp;
410061da546Spatrick }
411061da546Spatrick 
412061da546Spatrick uint32_t
AppendBlockVariables(bool can_create,bool get_child_block_variables,bool stop_if_child_block_is_inlined_function,const std::function<bool (Variable *)> & filter,VariableList * variable_list)413061da546Spatrick Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,
414061da546Spatrick                             bool stop_if_child_block_is_inlined_function,
415061da546Spatrick                             const std::function<bool(Variable *)> &filter,
416061da546Spatrick                             VariableList *variable_list) {
417061da546Spatrick   uint32_t num_variables_added = 0;
418061da546Spatrick   VariableList *block_var_list = GetBlockVariableList(can_create).get();
419061da546Spatrick   if (block_var_list) {
420061da546Spatrick     for (const VariableSP &var_sp : *block_var_list) {
421061da546Spatrick       if (filter(var_sp.get())) {
422061da546Spatrick         num_variables_added++;
423061da546Spatrick         variable_list->AddVariable(var_sp);
424061da546Spatrick       }
425061da546Spatrick     }
426061da546Spatrick   }
427061da546Spatrick 
428061da546Spatrick   if (get_child_block_variables) {
429061da546Spatrick     collection::const_iterator pos, end = m_children.end();
430061da546Spatrick     for (pos = m_children.begin(); pos != end; ++pos) {
431061da546Spatrick       Block *child_block = pos->get();
432061da546Spatrick       if (!stop_if_child_block_is_inlined_function ||
433061da546Spatrick           child_block->GetInlinedFunctionInfo() == nullptr) {
434061da546Spatrick         num_variables_added += child_block->AppendBlockVariables(
435061da546Spatrick             can_create, get_child_block_variables,
436061da546Spatrick             stop_if_child_block_is_inlined_function, filter, variable_list);
437061da546Spatrick       }
438061da546Spatrick     }
439061da546Spatrick   }
440061da546Spatrick   return num_variables_added;
441061da546Spatrick }
442061da546Spatrick 
AppendVariables(bool can_create,bool get_parent_variables,bool stop_if_block_is_inlined_function,const std::function<bool (Variable *)> & filter,VariableList * variable_list)443061da546Spatrick uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,
444061da546Spatrick                                 bool stop_if_block_is_inlined_function,
445061da546Spatrick                                 const std::function<bool(Variable *)> &filter,
446061da546Spatrick                                 VariableList *variable_list) {
447061da546Spatrick   uint32_t num_variables_added = 0;
448061da546Spatrick   VariableListSP variable_list_sp(GetBlockVariableList(can_create));
449061da546Spatrick 
450061da546Spatrick   bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
451061da546Spatrick   if (variable_list_sp) {
452061da546Spatrick     for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {
453061da546Spatrick       VariableSP variable = variable_list_sp->GetVariableAtIndex(i);
454061da546Spatrick       if (filter(variable.get())) {
455061da546Spatrick         num_variables_added++;
456061da546Spatrick         variable_list->AddVariable(variable);
457061da546Spatrick       }
458061da546Spatrick     }
459061da546Spatrick   }
460061da546Spatrick 
461061da546Spatrick   if (get_parent_variables) {
462061da546Spatrick     if (stop_if_block_is_inlined_function && is_inlined_function)
463061da546Spatrick       return num_variables_added;
464061da546Spatrick 
465061da546Spatrick     Block *parent_block = GetParent();
466061da546Spatrick     if (parent_block)
467061da546Spatrick       num_variables_added += parent_block->AppendVariables(
468061da546Spatrick           can_create, get_parent_variables, stop_if_block_is_inlined_function,
469061da546Spatrick           filter, variable_list);
470061da546Spatrick   }
471061da546Spatrick   return num_variables_added;
472061da546Spatrick }
473061da546Spatrick 
GetSymbolFile()474061da546Spatrick SymbolFile *Block::GetSymbolFile() {
475061da546Spatrick   if (ModuleSP module_sp = CalculateSymbolContextModule())
476061da546Spatrick     return module_sp->GetSymbolFile();
477061da546Spatrick   return nullptr;
478061da546Spatrick }
479061da546Spatrick 
GetDeclContext()480061da546Spatrick CompilerDeclContext Block::GetDeclContext() {
481061da546Spatrick   if (SymbolFile *sym_file = GetSymbolFile())
482061da546Spatrick     return sym_file->GetDeclContextForUID(GetID());
483061da546Spatrick   return CompilerDeclContext();
484061da546Spatrick }
485061da546Spatrick 
SetBlockInfoHasBeenParsed(bool b,bool set_children)486061da546Spatrick void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {
487061da546Spatrick   m_parsed_block_info = b;
488061da546Spatrick   if (set_children) {
489061da546Spatrick     m_parsed_child_blocks = true;
490061da546Spatrick     collection::const_iterator pos, end = m_children.end();
491061da546Spatrick     for (pos = m_children.begin(); pos != end; ++pos)
492061da546Spatrick       (*pos)->SetBlockInfoHasBeenParsed(b, true);
493061da546Spatrick   }
494061da546Spatrick }
495061da546Spatrick 
SetDidParseVariables(bool b,bool set_children)496061da546Spatrick void Block::SetDidParseVariables(bool b, bool set_children) {
497061da546Spatrick   m_parsed_block_variables = b;
498061da546Spatrick   if (set_children) {
499061da546Spatrick     collection::const_iterator pos, end = m_children.end();
500061da546Spatrick     for (pos = m_children.begin(); pos != end; ++pos)
501061da546Spatrick       (*pos)->SetDidParseVariables(b, true);
502061da546Spatrick   }
503061da546Spatrick }
504061da546Spatrick 
GetSibling() const505061da546Spatrick Block *Block::GetSibling() const {
506061da546Spatrick   if (m_parent_scope) {
507061da546Spatrick     Block *parent_block = GetParent();
508061da546Spatrick     if (parent_block)
509061da546Spatrick       return parent_block->GetSiblingForChild(this);
510061da546Spatrick   }
511061da546Spatrick   return nullptr;
512061da546Spatrick }
513061da546Spatrick // A parent of child blocks can be asked to find a sibling block given
514061da546Spatrick // one of its child blocks
GetSiblingForChild(const Block * child_block) const515061da546Spatrick Block *Block::GetSiblingForChild(const Block *child_block) const {
516061da546Spatrick   if (!m_children.empty()) {
517061da546Spatrick     collection::const_iterator pos, end = m_children.end();
518061da546Spatrick     for (pos = m_children.begin(); pos != end; ++pos) {
519061da546Spatrick       if (pos->get() == child_block) {
520061da546Spatrick         if (++pos != end)
521061da546Spatrick           return pos->get();
522061da546Spatrick         break;
523061da546Spatrick       }
524061da546Spatrick     }
525061da546Spatrick   }
526061da546Spatrick   return nullptr;
527061da546Spatrick }
528