180814287SRaphael Isemann //===-- Block.cpp ---------------------------------------------------------===//
230fdc8d8SChris Lattner //
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
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/Symbol/Block.h"
106c7f5619SGreg Clayton 
1130fdc8d8SChris Lattner #include "lldb/Core/Module.h"
1230fdc8d8SChris Lattner #include "lldb/Core/Section.h"
136c7f5619SGreg Clayton #include "lldb/Symbol/Function.h"
1472e4940bSSean Callanan #include "lldb/Symbol/SymbolFile.h"
1530fdc8d8SChris Lattner #include "lldb/Symbol/VariableList.h"
16*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
176f9e6901SZachary Turner #include "lldb/Utility/Log.h"
1830fdc8d8SChris Lattner 
19796ac80bSJonas Devlieghere #include <memory>
20796ac80bSJonas Devlieghere 
2130fdc8d8SChris Lattner using namespace lldb;
2230fdc8d8SChris Lattner using namespace lldb_private;
2330fdc8d8SChris Lattner 
Block(lldb::user_id_t uid)24b9c1b51eSKate Stone Block::Block(lldb::user_id_t uid)
25b9c1b51eSKate Stone     : UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(),
26b9c1b51eSKate Stone       m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false),
27b9c1b51eSKate Stone       m_parsed_block_variables(false), m_parsed_child_blocks(false) {}
2830fdc8d8SChris Lattner 
29fd2433e1SJonas Devlieghere Block::~Block() = default;
3030fdc8d8SChris Lattner 
GetDescription(Stream * s,Function * function,lldb::DescriptionLevel level,Target * target) const31b9c1b51eSKate Stone void Block::GetDescription(Stream *s, Function *function,
32b9c1b51eSKate Stone                            lldb::DescriptionLevel level, Target *target) const {
33c9800667SGreg Clayton   *s << "id = " << ((const UserID &)*this);
34c9800667SGreg Clayton 
35ea3e7d5cSGreg Clayton   size_t num_ranges = m_ranges.GetSize();
36b9c1b51eSKate Stone   if (num_ranges > 0) {
370c5cd90dSGreg Clayton 
380c5cd90dSGreg Clayton     addr_t base_addr = LLDB_INVALID_ADDRESS;
39f5e56de0SGreg Clayton     if (target)
40b9c1b51eSKate Stone       base_addr =
41b9c1b51eSKate Stone           function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
420c5cd90dSGreg Clayton     if (base_addr == LLDB_INVALID_ADDRESS)
430b76a2c2SGreg Clayton       base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
440c5cd90dSGreg Clayton 
45c9800667SGreg Clayton     s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
46b9c1b51eSKate Stone     for (size_t i = 0; i < num_ranges; ++i) {
47ea3e7d5cSGreg Clayton       const Range &range = m_ranges.GetEntryRef(i);
481462f5a4SRaphael Isemann       DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
49b9c1b51eSKate Stone                        base_addr + range.GetRangeEnd(), 4);
50ea3e7d5cSGreg Clayton     }
510c5cd90dSGreg Clayton   }
520c5cd90dSGreg Clayton 
53b9c1b51eSKate Stone   if (m_inlineInfoSP.get() != nullptr) {
546dbd3983SGreg Clayton     bool show_fullpaths = (level == eDescriptionLevelVerbose);
556dbd3983SGreg Clayton     m_inlineInfoSP->Dump(s, show_fullpaths);
566dbd3983SGreg Clayton   }
570c5cd90dSGreg Clayton }
580c5cd90dSGreg Clayton 
Dump(Stream * s,addr_t base_addr,int32_t depth,bool show_context) const59b9c1b51eSKate Stone void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
60b9c1b51eSKate Stone                  bool show_context) const {
61b9c1b51eSKate Stone   if (depth < 0) {
620b76a2c2SGreg Clayton     Block *parent = GetParent();
63b9c1b51eSKate Stone     if (parent) {
6405097246SAdrian Prantl       // We have a depth that is less than zero, print our parent blocks first
650b76a2c2SGreg Clayton       parent->Dump(s, base_addr, depth + 1, show_context);
660b76a2c2SGreg Clayton     }
6730fdc8d8SChris Lattner   }
6830fdc8d8SChris Lattner 
69324a1036SSaleem Abdulrasool   s->Printf("%p: ", static_cast<const void *>(this));
7030fdc8d8SChris Lattner   s->Indent();
71324a1036SSaleem Abdulrasool   *s << "Block" << static_cast<const UserID &>(*this);
720c5cd90dSGreg Clayton   const Block *parent_block = GetParent();
73b9c1b51eSKate Stone   if (parent_block) {
74d01b2953SDaniel Malea     s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
7530fdc8d8SChris Lattner   }
76b9c1b51eSKate Stone   if (m_inlineInfoSP.get() != nullptr) {
776dbd3983SGreg Clayton     bool show_fullpaths = false;
786dbd3983SGreg Clayton     m_inlineInfoSP->Dump(s, show_fullpaths);
796dbd3983SGreg Clayton   }
8030fdc8d8SChris Lattner 
81b9c1b51eSKate Stone   if (!m_ranges.IsEmpty()) {
8230fdc8d8SChris Lattner     *s << ", ranges =";
83ea3e7d5cSGreg Clayton 
84ea3e7d5cSGreg Clayton     size_t num_ranges = m_ranges.GetSize();
85b9c1b51eSKate Stone     for (size_t i = 0; i < num_ranges; ++i) {
86ea3e7d5cSGreg Clayton       const Range &range = m_ranges.GetEntryRef(i);
87a6682a41SJonas Devlieghere       if (parent_block != nullptr && !parent_block->Contains(range))
8830fdc8d8SChris Lattner         *s << '!';
8930fdc8d8SChris Lattner       else
9030fdc8d8SChris Lattner         *s << ' ';
911462f5a4SRaphael Isemann       DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
92b9c1b51eSKate Stone                        base_addr + range.GetRangeEnd(), 4);
9330fdc8d8SChris Lattner     }
9430fdc8d8SChris Lattner   }
9530fdc8d8SChris Lattner   s->EOL();
9630fdc8d8SChris Lattner 
97b9c1b51eSKate Stone   if (depth > 0) {
9830fdc8d8SChris Lattner     s->IndentMore();
9930fdc8d8SChris Lattner 
100b9c1b51eSKate Stone     if (m_variable_list_sp.get()) {
1019da7bd07SGreg Clayton       m_variable_list_sp->Dump(s, show_context);
10230fdc8d8SChris Lattner     }
10330fdc8d8SChris Lattner 
104624784a9SGreg Clayton     collection::const_iterator pos, end = m_children.end();
105624784a9SGreg Clayton     for (pos = m_children.begin(); pos != end; ++pos)
106624784a9SGreg Clayton       (*pos)->Dump(s, base_addr, depth - 1, show_context);
10730fdc8d8SChris Lattner 
10830fdc8d8SChris Lattner     s->IndentLess();
10930fdc8d8SChris Lattner   }
11030fdc8d8SChris Lattner }
11130fdc8d8SChris Lattner 
FindBlockByID(user_id_t block_id)112b9c1b51eSKate Stone Block *Block::FindBlockByID(user_id_t block_id) {
1130b76a2c2SGreg Clayton   if (block_id == GetID())
1140b76a2c2SGreg Clayton     return this;
1150b76a2c2SGreg Clayton 
116d4612ad0SEd Maste   Block *matching_block = nullptr;
117624784a9SGreg Clayton   collection::const_iterator pos, end = m_children.end();
118b9c1b51eSKate Stone   for (pos = m_children.begin(); pos != end; ++pos) {
119624784a9SGreg Clayton     matching_block = (*pos)->FindBlockByID(block_id);
1200b76a2c2SGreg Clayton     if (matching_block)
1210b76a2c2SGreg Clayton       break;
1220b76a2c2SGreg Clayton   }
1230b76a2c2SGreg Clayton   return matching_block;
1240b76a2c2SGreg Clayton }
1250b76a2c2SGreg Clayton 
FindInnermostBlockByOffset(const lldb::addr_t offset)126cc9ced0eSZequan Wu Block *Block::FindInnermostBlockByOffset(const lldb::addr_t offset) {
127cc9ced0eSZequan Wu   if (!Contains(offset))
128cc9ced0eSZequan Wu     return nullptr;
129cc9ced0eSZequan Wu   for (const BlockSP &block_sp : m_children) {
130cc9ced0eSZequan Wu     if (Block *block = block_sp->FindInnermostBlockByOffset(offset))
131cc9ced0eSZequan Wu       return block;
132cc9ced0eSZequan Wu   }
133cc9ced0eSZequan Wu   return this;
134cc9ced0eSZequan Wu }
135cc9ced0eSZequan Wu 
CalculateSymbolContext(SymbolContext * sc)136b9c1b51eSKate Stone void Block::CalculateSymbolContext(SymbolContext *sc) {
1370b76a2c2SGreg Clayton   if (m_parent_scope)
1380b76a2c2SGreg Clayton     m_parent_scope->CalculateSymbolContext(sc);
13930fdc8d8SChris Lattner   sc->block = this;
14030fdc8d8SChris Lattner }
14130fdc8d8SChris Lattner 
CalculateSymbolContextModule()142b9c1b51eSKate Stone lldb::ModuleSP Block::CalculateSymbolContextModule() {
1437e9b1fd0SGreg Clayton   if (m_parent_scope)
1447e9b1fd0SGreg Clayton     return m_parent_scope->CalculateSymbolContextModule();
145e72dfb32SGreg Clayton   return lldb::ModuleSP();
1467e9b1fd0SGreg Clayton }
1477e9b1fd0SGreg Clayton 
CalculateSymbolContextCompileUnit()148b9c1b51eSKate Stone CompileUnit *Block::CalculateSymbolContextCompileUnit() {
1497e9b1fd0SGreg Clayton   if (m_parent_scope)
1507e9b1fd0SGreg Clayton     return m_parent_scope->CalculateSymbolContextCompileUnit();
151d4612ad0SEd Maste   return nullptr;
1527e9b1fd0SGreg Clayton }
1537e9b1fd0SGreg Clayton 
CalculateSymbolContextFunction()154b9c1b51eSKate Stone Function *Block::CalculateSymbolContextFunction() {
1557e9b1fd0SGreg Clayton   if (m_parent_scope)
1567e9b1fd0SGreg Clayton     return m_parent_scope->CalculateSymbolContextFunction();
157d4612ad0SEd Maste   return nullptr;
1587e9b1fd0SGreg Clayton }
1597e9b1fd0SGreg Clayton 
CalculateSymbolContextBlock()160b9c1b51eSKate Stone Block *Block::CalculateSymbolContextBlock() { return this; }
1617e9b1fd0SGreg Clayton 
DumpSymbolContext(Stream * s)162b9c1b51eSKate Stone void Block::DumpSymbolContext(Stream *s) {
1637e9b1fd0SGreg Clayton   Function *function = CalculateSymbolContextFunction();
1647e9b1fd0SGreg Clayton   if (function)
1657e9b1fd0SGreg Clayton     function->DumpSymbolContext(s);
166d01b2953SDaniel Malea   s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
16730fdc8d8SChris Lattner }
16830fdc8d8SChris Lattner 
DumpAddressRanges(Stream * s,lldb::addr_t base_addr)169b9c1b51eSKate Stone void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) {
170b9c1b51eSKate Stone   if (!m_ranges.IsEmpty()) {
171ea3e7d5cSGreg Clayton     size_t num_ranges = m_ranges.GetSize();
172b9c1b51eSKate Stone     for (size_t i = 0; i < num_ranges; ++i) {
173ea3e7d5cSGreg Clayton       const Range &range = m_ranges.GetEntryRef(i);
1741462f5a4SRaphael Isemann       DumpAddressRange(s->AsRawOstream(), base_addr + range.GetRangeBase(),
175b9c1b51eSKate Stone                        base_addr + range.GetRangeEnd(), 4);
176ea3e7d5cSGreg Clayton     }
177dde9cff3SCaroline Tice   }
178dde9cff3SCaroline Tice }
179dde9cff3SCaroline Tice 
Contains(addr_t range_offset) const180b9c1b51eSKate Stone bool Block::Contains(addr_t range_offset) const {
181d4612ad0SEd Maste   return m_ranges.FindEntryThatContains(range_offset) != nullptr;
18230fdc8d8SChris Lattner }
18330fdc8d8SChris Lattner 
Contains(const Block * block) const184b9c1b51eSKate Stone bool Block::Contains(const Block *block) const {
1856dadd508SGreg Clayton   if (this == block)
1866f00abd5SGreg Clayton     return false; // This block doesn't contain itself...
1876dadd508SGreg Clayton 
1886f00abd5SGreg Clayton   // Walk the parent chain for "block" and see if any if them match this block
1896dadd508SGreg Clayton   const Block *block_parent;
190b9c1b51eSKate Stone   for (block_parent = block->GetParent(); block_parent != nullptr;
191b9c1b51eSKate Stone        block_parent = block_parent->GetParent()) {
1926f00abd5SGreg Clayton     if (this == block_parent)
1936f00abd5SGreg Clayton       return true; // One of the parents of "block" is this object!
1946dadd508SGreg Clayton   }
1956dadd508SGreg Clayton   return false;
1966dadd508SGreg Clayton }
1976dadd508SGreg Clayton 
Contains(const Range & range) const198b9c1b51eSKate Stone bool Block::Contains(const Range &range) const {
199d4612ad0SEd Maste   return m_ranges.FindEntryThatContains(range) != nullptr;
20030fdc8d8SChris Lattner }
20130fdc8d8SChris Lattner 
GetParent() const202b9c1b51eSKate Stone Block *Block::GetParent() const {
2030b76a2c2SGreg Clayton   if (m_parent_scope)
2047e9b1fd0SGreg Clayton     return m_parent_scope->CalculateSymbolContextBlock();
205d4612ad0SEd Maste   return nullptr;
20630fdc8d8SChris Lattner }
20730fdc8d8SChris Lattner 
GetContainingInlinedBlock()208b9c1b51eSKate Stone Block *Block::GetContainingInlinedBlock() {
20995897c6aSGreg Clayton   if (GetInlinedFunctionInfo())
2109da7bd07SGreg Clayton     return this;
2119da7bd07SGreg Clayton   return GetInlinedParent();
2129da7bd07SGreg Clayton }
2139da7bd07SGreg Clayton 
GetInlinedParent()214b9c1b51eSKate Stone Block *Block::GetInlinedParent() {
2151b72fcb7SGreg Clayton   Block *parent_block = GetParent();
216b9c1b51eSKate Stone   if (parent_block) {
21795897c6aSGreg Clayton     if (parent_block->GetInlinedFunctionInfo())
2181b72fcb7SGreg Clayton       return parent_block;
2191b72fcb7SGreg Clayton     else
2201b72fcb7SGreg Clayton       return parent_block->GetInlinedParent();
2211b72fcb7SGreg Clayton   }
222d4612ad0SEd Maste   return nullptr;
2231b72fcb7SGreg Clayton }
2241b72fcb7SGreg Clayton 
GetContainingInlinedBlockWithCallSite(const Declaration & find_call_site)2258a777920SGreg Clayton Block *Block::GetContainingInlinedBlockWithCallSite(
2268a777920SGreg Clayton     const Declaration &find_call_site) {
227a83e94ebSFangrui Song   Block *inlined_block = GetContainingInlinedBlock();
2288a777920SGreg Clayton 
2298a777920SGreg Clayton   while (inlined_block) {
230a83e94ebSFangrui Song     const auto *function_info = inlined_block->GetInlinedFunctionInfo();
2318a777920SGreg Clayton 
2328a777920SGreg Clayton     if (function_info &&
2338a777920SGreg Clayton         function_info->GetCallSite().FileAndLineEqual(find_call_site))
2348a777920SGreg Clayton       return inlined_block;
2358a777920SGreg Clayton     inlined_block = inlined_block->GetInlinedParent();
2368a777920SGreg Clayton   }
2378a777920SGreg Clayton   return nullptr;
2388a777920SGreg Clayton }
2398a777920SGreg Clayton 
GetRangeContainingOffset(const addr_t offset,Range & range)240b9c1b51eSKate Stone bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) {
241ea3e7d5cSGreg Clayton   const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
242b9c1b51eSKate Stone   if (range_ptr) {
243ea3e7d5cSGreg Clayton     range = *range_ptr;
2449da7bd07SGreg Clayton     return true;
2459da7bd07SGreg Clayton   }
2469da7bd07SGreg Clayton   range.Clear();
2479da7bd07SGreg Clayton   return false;
2489da7bd07SGreg Clayton }
2499da7bd07SGreg Clayton 
GetRangeContainingAddress(const Address & addr,AddressRange & range)250b9c1b51eSKate Stone bool Block::GetRangeContainingAddress(const Address &addr,
251b9c1b51eSKate Stone                                       AddressRange &range) {
2527e9b1fd0SGreg Clayton   Function *function = CalculateSymbolContextFunction();
253b9c1b51eSKate Stone   if (function) {
2547e9b1fd0SGreg Clayton     const AddressRange &func_range = function->GetAddressRange();
255b9c1b51eSKate Stone     if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
2561b72fcb7SGreg Clayton       const addr_t addr_offset = addr.GetOffset();
2571b72fcb7SGreg Clayton       const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
258b9c1b51eSKate Stone       if (addr_offset >= func_offset &&
259b9c1b51eSKate Stone           addr_offset < func_offset + func_range.GetByteSize()) {
2601b72fcb7SGreg Clayton         addr_t offset = addr_offset - func_offset;
2611b72fcb7SGreg Clayton 
262ea3e7d5cSGreg Clayton         const Range *range_ptr = m_ranges.FindEntryThatContains(offset);
263ea3e7d5cSGreg Clayton 
264b9c1b51eSKate Stone         if (range_ptr) {
2651b72fcb7SGreg Clayton           range.GetBaseAddress() = func_range.GetBaseAddress();
266b9c1b51eSKate Stone           range.GetBaseAddress().SetOffset(func_offset +
267b9c1b51eSKate Stone                                            range_ptr->GetRangeBase());
268ea3e7d5cSGreg Clayton           range.SetByteSize(range_ptr->GetByteSize());
2691b72fcb7SGreg Clayton           return true;
2701b72fcb7SGreg Clayton         }
2711b72fcb7SGreg Clayton       }
2721b72fcb7SGreg Clayton     }
2731b72fcb7SGreg Clayton   }
2741b72fcb7SGreg Clayton   range.Clear();
2751b72fcb7SGreg Clayton   return false;
2761b72fcb7SGreg Clayton }
2771b72fcb7SGreg Clayton 
GetRangeContainingLoadAddress(lldb::addr_t load_addr,Target & target,AddressRange & range)278b9c1b51eSKate Stone bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr,
279b9c1b51eSKate Stone                                           Target &target, AddressRange &range) {
280fcb59bcfSJim Ingham   Address load_address;
281fcb59bcfSJim Ingham   load_address.SetLoadAddress(load_addr, &target);
282fcb59bcfSJim Ingham   AddressRange containing_range;
283fcb59bcfSJim Ingham   return GetRangeContainingAddress(load_address, containing_range);
284fcb59bcfSJim Ingham }
285fcb59bcfSJim Ingham 
GetRangeIndexContainingAddress(const Address & addr)286b9c1b51eSKate Stone uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
287ea3e7d5cSGreg Clayton   Function *function = CalculateSymbolContextFunction();
288b9c1b51eSKate Stone   if (function) {
289ea3e7d5cSGreg Clayton     const AddressRange &func_range = function->GetAddressRange();
290b9c1b51eSKate Stone     if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) {
291ea3e7d5cSGreg Clayton       const addr_t addr_offset = addr.GetOffset();
292ea3e7d5cSGreg Clayton       const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
293b9c1b51eSKate Stone       if (addr_offset >= func_offset &&
294b9c1b51eSKate Stone           addr_offset < func_offset + func_range.GetByteSize()) {
295ea3e7d5cSGreg Clayton         addr_t offset = addr_offset - func_offset;
296ea3e7d5cSGreg Clayton         return m_ranges.FindEntryIndexThatContains(offset);
297ea3e7d5cSGreg Clayton       }
298ea3e7d5cSGreg Clayton     }
299ea3e7d5cSGreg Clayton   }
300ea3e7d5cSGreg Clayton   return UINT32_MAX;
301ea3e7d5cSGreg Clayton }
302ea3e7d5cSGreg Clayton 
GetRangeAtIndex(uint32_t range_idx,AddressRange & range)303b9c1b51eSKate Stone bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
304b9c1b51eSKate Stone   if (range_idx < m_ranges.GetSize()) {
3057e9b1fd0SGreg Clayton     Function *function = CalculateSymbolContextFunction();
306b9c1b51eSKate Stone     if (function) {
307ea3e7d5cSGreg Clayton       const Range &vm_range = m_ranges.GetEntryRef(range_idx);
3087e9b1fd0SGreg Clayton       range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
309ea3e7d5cSGreg Clayton       range.GetBaseAddress().Slide(vm_range.GetRangeBase());
310ea3e7d5cSGreg Clayton       range.SetByteSize(vm_range.GetByteSize());
3117e14f91dSGreg Clayton       return true;
3127e14f91dSGreg Clayton     }
3137e14f91dSGreg Clayton   }
3147e14f91dSGreg Clayton   return false;
3157e14f91dSGreg Clayton }
316d7e05469SGreg Clayton 
GetStartAddress(Address & addr)317b9c1b51eSKate Stone bool Block::GetStartAddress(Address &addr) {
318ea3e7d5cSGreg Clayton   if (m_ranges.IsEmpty())
319d7e05469SGreg Clayton     return false;
320d7e05469SGreg Clayton 
3217e9b1fd0SGreg Clayton   Function *function = CalculateSymbolContextFunction();
322b9c1b51eSKate Stone   if (function) {
3237e9b1fd0SGreg Clayton     addr = function->GetAddressRange().GetBaseAddress();
324ea3e7d5cSGreg Clayton     addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase());
325d7e05469SGreg Clayton     return true;
326d7e05469SGreg Clayton   }
327d7e05469SGreg Clayton   return false;
328d7e05469SGreg Clayton }
329d7e05469SGreg Clayton 
FinalizeRanges()330b9c1b51eSKate Stone void Block::FinalizeRanges() {
331ea3e7d5cSGreg Clayton   m_ranges.Sort();
332ea3e7d5cSGreg Clayton   m_ranges.CombineConsecutiveRanges();
333ea3e7d5cSGreg Clayton }
334ea3e7d5cSGreg Clayton 
AddRange(const Range & range)335b9c1b51eSKate Stone void Block::AddRange(const Range &range) {
3366c7f5619SGreg Clayton   Block *parent_block = GetParent();
337b9c1b51eSKate Stone   if (parent_block && !parent_block->Contains(range)) {
338a007a6d8SPavel Labath     Log *log = GetLog(LLDBLog::Symbols);
339b9c1b51eSKate Stone     if (log) {
340e72dfb32SGreg Clayton       ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule());
3416c7f5619SGreg Clayton       Function *function = m_parent_scope->CalculateSymbolContextFunction();
342b9c1b51eSKate Stone       const addr_t function_file_addr =
343b9c1b51eSKate Stone           function->GetAddressRange().GetBaseAddress().GetFileAddress();
344ea3e7d5cSGreg Clayton       const addr_t block_start_addr = function_file_addr + range.GetRangeBase();
345ea3e7d5cSGreg Clayton       const addr_t block_end_addr = function_file_addr + range.GetRangeEnd();
3466c7f5619SGreg Clayton       Type *func_type = function->GetType();
3476c7f5619SGreg Clayton 
3486c7f5619SGreg Clayton       const Declaration &func_decl = func_type->GetDeclaration();
349b9c1b51eSKate Stone       if (func_decl.GetLine()) {
35063e5fb76SJonas Devlieghere         LLDB_LOGF(log,
35163e5fb76SJonas Devlieghere                   "warning: %s:%u block {0x%8.8" PRIx64
352b9c1b51eSKate Stone                   "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64
353b9c1b51eSKate Stone                   ") which is not contained in parent block {0x%8.8" PRIx64
354b9c1b51eSKate Stone                   "} in function {0x%8.8" PRIx64 "} from %s",
355b9c1b51eSKate Stone                   func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(),
356b9c1b51eSKate Stone                   GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
357b9c1b51eSKate Stone                   block_end_addr, parent_block->GetID(), function->GetID(),
358b5ad4ec7SGreg Clayton                   module_sp->GetFileSpec().GetPath().c_str());
359b9c1b51eSKate Stone       } else {
36063e5fb76SJonas Devlieghere         LLDB_LOGF(log,
36163e5fb76SJonas Devlieghere                   "warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64
36263e5fb76SJonas Devlieghere                   " - 0x%" PRIx64
363b9c1b51eSKate Stone                   ") which is not contained in parent block {0x%8.8" PRIx64
364b9c1b51eSKate Stone                   "} in function {0x%8.8" PRIx64 "} from %s",
365b9c1b51eSKate Stone                   GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr,
366b9c1b51eSKate Stone                   block_end_addr, parent_block->GetID(), function->GetID(),
367b5ad4ec7SGreg Clayton                   module_sp->GetFileSpec().GetPath().c_str());
3686c7f5619SGreg Clayton       }
3696c7f5619SGreg Clayton     }
370ea3e7d5cSGreg Clayton     parent_block->AddRange(range);
3716c7f5619SGreg Clayton   }
372ea3e7d5cSGreg Clayton   m_ranges.Append(range);
37330fdc8d8SChris Lattner }
37430fdc8d8SChris Lattner 
37530fdc8d8SChris Lattner // Return the current number of bytes that this object occupies in memory
MemorySize() const376b9c1b51eSKate Stone size_t Block::MemorySize() const {
377ea3e7d5cSGreg Clayton   size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
37830fdc8d8SChris Lattner   if (m_inlineInfoSP.get())
37930fdc8d8SChris Lattner     mem_size += m_inlineInfoSP->MemorySize();
3809da7bd07SGreg Clayton   if (m_variable_list_sp.get())
3819da7bd07SGreg Clayton     mem_size += m_variable_list_sp->MemorySize();
38230fdc8d8SChris Lattner   return mem_size;
38330fdc8d8SChris Lattner }
38430fdc8d8SChris Lattner 
AddChild(const BlockSP & child_block_sp)385b9c1b51eSKate Stone void Block::AddChild(const BlockSP &child_block_sp) {
386b9c1b51eSKate Stone   if (child_block_sp) {
3870b76a2c2SGreg Clayton     child_block_sp->SetParentScope(this);
3880b76a2c2SGreg Clayton     m_children.push_back(child_block_sp);
3890b76a2c2SGreg Clayton   }
39030fdc8d8SChris Lattner }
39130fdc8d8SChris Lattner 
SetInlinedFunctionInfo(const char * name,const char * mangled,const Declaration * decl_ptr,const Declaration * call_decl_ptr)392b9c1b51eSKate Stone void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,
393b9c1b51eSKate Stone                                    const Declaration *decl_ptr,
394b9c1b51eSKate Stone                                    const Declaration *call_decl_ptr) {
395796ac80bSJonas Devlieghere   m_inlineInfoSP = std::make_shared<InlineFunctionInfo>(name, mangled, decl_ptr,
396796ac80bSJonas Devlieghere                                                         call_decl_ptr);
39730fdc8d8SChris Lattner }
39830fdc8d8SChris Lattner 
GetBlockVariableList(bool can_create)399b9c1b51eSKate Stone VariableListSP Block::GetBlockVariableList(bool can_create) {
400a6682a41SJonas Devlieghere   if (!m_parsed_block_variables) {
401b9c1b51eSKate Stone     if (m_variable_list_sp.get() == nullptr && can_create) {
4020b76a2c2SGreg Clayton       m_parsed_block_variables = true;
403e1be14dfSJim Ingham       SymbolContext sc;
404e1be14dfSJim Ingham       CalculateSymbolContext(&sc);
405e1be14dfSJim Ingham       assert(sc.module_sp);
406465eae36SPavel Labath       sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);
407e1be14dfSJim Ingham     }
4080b76a2c2SGreg Clayton   }
409c662ec8bSGreg Clayton   return m_variable_list_sp;
410c662ec8bSGreg Clayton }
411e1be14dfSJim Ingham 
412c662ec8bSGreg Clayton 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)413b9c1b51eSKate Stone Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,
414c662ec8bSGreg Clayton                             bool stop_if_child_block_is_inlined_function,
41572ac8a84STamas Berghammer                             const std::function<bool(Variable *)> &filter,
416b9c1b51eSKate Stone                             VariableList *variable_list) {
417c662ec8bSGreg Clayton   uint32_t num_variables_added = 0;
418c662ec8bSGreg Clayton   VariableList *block_var_list = GetBlockVariableList(can_create).get();
419b9c1b51eSKate Stone   if (block_var_list) {
420d1782133SRaphael Isemann     for (const VariableSP &var_sp : *block_var_list) {
421d1782133SRaphael Isemann       if (filter(var_sp.get())) {
42272ac8a84STamas Berghammer         num_variables_added++;
423d1782133SRaphael Isemann         variable_list->AddVariable(var_sp);
42472ac8a84STamas Berghammer       }
42572ac8a84STamas Berghammer     }
426c662ec8bSGreg Clayton   }
427e1be14dfSJim Ingham 
428b9c1b51eSKate Stone   if (get_child_block_variables) {
429624784a9SGreg Clayton     collection::const_iterator pos, end = m_children.end();
430b9c1b51eSKate Stone     for (pos = m_children.begin(); pos != end; ++pos) {
431624784a9SGreg Clayton       Block *child_block = pos->get();
432a6682a41SJonas Devlieghere       if (!stop_if_child_block_is_inlined_function ||
433b9c1b51eSKate Stone           child_block->GetInlinedFunctionInfo() == nullptr) {
434b9c1b51eSKate Stone         num_variables_added += child_block->AppendBlockVariables(
435b9c1b51eSKate Stone             can_create, get_child_block_variables,
436b9c1b51eSKate Stone             stop_if_child_block_is_inlined_function, filter, variable_list);
437e1be14dfSJim Ingham       }
438e1be14dfSJim Ingham     }
439e1be14dfSJim Ingham   }
440c662ec8bSGreg Clayton   return num_variables_added;
441e1be14dfSJim Ingham }
442e1be14dfSJim Ingham 
AppendVariables(bool can_create,bool get_parent_variables,bool stop_if_block_is_inlined_function,const std::function<bool (Variable *)> & filter,VariableList * variable_list)443b9c1b51eSKate Stone uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,
4441b72fcb7SGreg Clayton                                 bool stop_if_block_is_inlined_function,
44572ac8a84STamas Berghammer                                 const std::function<bool(Variable *)> &filter,
446b9c1b51eSKate Stone                                 VariableList *variable_list) {
447e1be14dfSJim Ingham   uint32_t num_variables_added = 0;
448c662ec8bSGreg Clayton   VariableListSP variable_list_sp(GetBlockVariableList(can_create));
449e1be14dfSJim Ingham 
450d4612ad0SEd Maste   bool is_inlined_function = GetInlinedFunctionInfo() != nullptr;
451b9c1b51eSKate Stone   if (variable_list_sp) {
452b9c1b51eSKate Stone     for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) {
45372ac8a84STamas Berghammer       VariableSP variable = variable_list_sp->GetVariableAtIndex(i);
454b9c1b51eSKate Stone       if (filter(variable.get())) {
45572ac8a84STamas Berghammer         num_variables_added++;
45672ac8a84STamas Berghammer         variable_list->AddVariable(variable);
45772ac8a84STamas Berghammer       }
45872ac8a84STamas Berghammer     }
459e1be14dfSJim Ingham   }
460e1be14dfSJim Ingham 
461b9c1b51eSKate Stone   if (get_parent_variables) {
4621b72fcb7SGreg Clayton     if (stop_if_block_is_inlined_function && is_inlined_function)
4631b72fcb7SGreg Clayton       return num_variables_added;
4641b72fcb7SGreg Clayton 
465e1be14dfSJim Ingham     Block *parent_block = GetParent();
466e1be14dfSJim Ingham     if (parent_block)
467b9c1b51eSKate Stone       num_variables_added += parent_block->AppendVariables(
468b9c1b51eSKate Stone           can_create, get_parent_variables, stop_if_block_is_inlined_function,
469b9c1b51eSKate Stone           filter, variable_list);
470e1be14dfSJim Ingham   }
471e1be14dfSJim Ingham   return num_variables_added;
472e1be14dfSJim Ingham }
473e1be14dfSJim Ingham 
GetSymbolFile()4744b36f791SVedant Kumar SymbolFile *Block::GetSymbolFile() {
4754b36f791SVedant Kumar   if (ModuleSP module_sp = CalculateSymbolContextModule())
47623f70e83SPavel Labath     return module_sp->GetSymbolFile();
4774b36f791SVedant Kumar   return nullptr;
4784b36f791SVedant Kumar }
4794b36f791SVedant Kumar 
GetDeclContext()480b9c1b51eSKate Stone CompilerDeclContext Block::GetDeclContext() {
4814b36f791SVedant Kumar   if (SymbolFile *sym_file = GetSymbolFile())
48299558cc4SGreg Clayton     return sym_file->GetDeclContextForUID(GetID());
48399558cc4SGreg Clayton   return CompilerDeclContext();
48472e4940bSSean Callanan }
48572e4940bSSean Callanan 
SetBlockInfoHasBeenParsed(bool b,bool set_children)486b9c1b51eSKate Stone void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) {
4870b76a2c2SGreg Clayton   m_parsed_block_info = b;
488b9c1b51eSKate Stone   if (set_children) {
4890b76a2c2SGreg Clayton     m_parsed_child_blocks = true;
490624784a9SGreg Clayton     collection::const_iterator pos, end = m_children.end();
491624784a9SGreg Clayton     for (pos = m_children.begin(); pos != end; ++pos)
492624784a9SGreg Clayton       (*pos)->SetBlockInfoHasBeenParsed(b, true);
49330fdc8d8SChris Lattner   }
49430fdc8d8SChris Lattner }
495c662ec8bSGreg Clayton 
SetDidParseVariables(bool b,bool set_children)496b9c1b51eSKate Stone void Block::SetDidParseVariables(bool b, bool set_children) {
497c662ec8bSGreg Clayton   m_parsed_block_variables = b;
498b9c1b51eSKate Stone   if (set_children) {
499624784a9SGreg Clayton     collection::const_iterator pos, end = m_children.end();
500624784a9SGreg Clayton     for (pos = m_children.begin(); pos != end; ++pos)
501624784a9SGreg Clayton       (*pos)->SetDidParseVariables(b, true);
502c662ec8bSGreg Clayton   }
503c662ec8bSGreg Clayton }
504c662ec8bSGreg Clayton 
GetSibling() const505b9c1b51eSKate Stone Block *Block::GetSibling() const {
506b9c1b51eSKate Stone   if (m_parent_scope) {
5076c7f5619SGreg Clayton     Block *parent_block = GetParent();
508624784a9SGreg Clayton     if (parent_block)
509624784a9SGreg Clayton       return parent_block->GetSiblingForChild(this);
510624784a9SGreg Clayton   }
511d4612ad0SEd Maste   return nullptr;
512624784a9SGreg Clayton }
513624784a9SGreg Clayton // A parent of child blocks can be asked to find a sibling block given
514624784a9SGreg Clayton // one of its child blocks
GetSiblingForChild(const Block * child_block) const515b9c1b51eSKate Stone Block *Block::GetSiblingForChild(const Block *child_block) const {
516b9c1b51eSKate Stone   if (!m_children.empty()) {
517624784a9SGreg Clayton     collection::const_iterator pos, end = m_children.end();
518b9c1b51eSKate Stone     for (pos = m_children.begin(); pos != end; ++pos) {
519b9c1b51eSKate Stone       if (pos->get() == child_block) {
520624784a9SGreg Clayton         if (++pos != end)
521624784a9SGreg Clayton           return pos->get();
522624784a9SGreg Clayton         break;
523624784a9SGreg Clayton       }
524624784a9SGreg Clayton     }
525624784a9SGreg Clayton   }
526d4612ad0SEd Maste   return nullptr;
527624784a9SGreg Clayton }
528