blob: ab998cb179546d5b9907e667a8dd21297463bfa8 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Block.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#include "lldb/Symbol/Block.h"
11#include "lldb/Symbol/Function.h"
12#include "lldb/Core/Module.h"
13#include "lldb/Core/Section.h"
14#include "lldb/Symbol/SymbolVendor.h"
15#include "lldb/Symbol/VariableList.h"
16
17using namespace lldb;
18using namespace lldb_private;
19
20Block::Block(user_id_t uid, uint32_t depth, BlockList* blocks) :
21 UserID(uid),
22 m_block_list(blocks),
23 m_depth(depth),
24 m_ranges(),
25 m_inlineInfoSP(),
26 m_variables()
27{
28}
29
30Block::Block(const Block& rhs) :
31 UserID(rhs),
32 m_block_list(rhs.m_block_list),
33 m_depth(rhs.m_depth),
34 m_ranges(rhs.m_ranges),
35 m_inlineInfoSP(rhs.m_inlineInfoSP),
36 m_variables(rhs.m_variables)
37{
38}
39
40const Block&
41Block::operator= (const Block& rhs)
42{
43 if (this != &rhs)
44 {
45 UserID::operator= (rhs);
46 m_block_list = rhs.m_block_list;
47 m_depth = rhs.m_depth;
48 m_ranges = rhs.m_ranges;
49 m_inlineInfoSP = rhs.m_inlineInfoSP;
50 m_variables = rhs.m_variables;
51 }
52 return *this;
53}
54
55Block::~Block ()
56{
57}
58
59void
Greg Clayton12bec712010-06-28 21:30:43 +000060Block::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process) const
61{
62 size_t num_ranges = m_ranges.size();
63 if (num_ranges)
64 {
65
66 addr_t base_addr = LLDB_INVALID_ADDRESS;
67 if (process)
68 base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
69 if (base_addr == LLDB_INVALID_ADDRESS)
70 base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetFileAddress();
71
72 s->Printf("range%s = ", num_ranges > 1 ? "s" : "");
73 std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
74 for (pos = m_ranges.begin(); pos != end; ++pos)
75 pos->Dump(s, base_addr, 4);
76 }
77 *s << ", id = " << ((const UserID&)*this);
78
79 if (m_inlineInfoSP.get() != NULL)
80 m_inlineInfoSP->Dump(s);
81}
82
83void
Chris Lattner24943d22010-06-08 16:52:24 +000084Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
85{
86 if (depth < 0)
87 {
88 // We have a depth that is less than zero, print our parent blocks
89 // first
90 m_block_list->Dump(s, GetParentUID(), depth + 1, show_context);
91 }
92
93 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
94 s->Indent();
95 *s << "Block" << ((const UserID&)*this);
Greg Clayton12bec712010-06-28 21:30:43 +000096 const Block* parent_block = GetParent();
97 if (parent_block)
Chris Lattner24943d22010-06-08 16:52:24 +000098 {
Greg Clayton12bec712010-06-28 21:30:43 +000099 s->Printf(", parent = {0x%8.8x}", parent_block->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000100 }
101 if (m_inlineInfoSP.get() != NULL)
102 m_inlineInfoSP->Dump(s);
103
104 if (!m_ranges.empty())
105 {
106 *s << ", ranges =";
107 std::vector<VMRange>::const_iterator pos;
108 std::vector<VMRange>::const_iterator end = m_ranges.end();
109 for (pos = m_ranges.begin(); pos != end; ++pos)
110 {
111 if (parent_block != NULL && parent_block->Contains(*pos) == false)
112 *s << '!';
113 else
114 *s << ' ';
115 pos->Dump(s, base_addr);
116 }
117 }
118 s->EOL();
119
120 if (depth > 0)
121 {
122 s->IndentMore();
123
124 if (m_variables.get())
125 {
126 m_variables->Dump(s, show_context);
127 }
128
129 uint32_t blockID = m_block_list->GetFirstChild(GetID());
130 while (blockID != Block::InvalidID)
131 {
132 m_block_list->Dump(s, blockID, depth - 1, show_context);
133
134 blockID = m_block_list->GetSibling(blockID);
135 }
136
137 s->IndentLess();
138 }
139
140}
141
142
143void
144Block::CalculateSymbolContext(SymbolContext* sc)
145{
146 sc->block = this;
147 m_block_list->GetFunction()->CalculateSymbolContext(sc);
148}
149
150void
151Block::DumpStopContext (Stream *s, const SymbolContext *sc)
152{
Greg Clayton12bec712010-06-28 21:30:43 +0000153 Block* parent_block = GetParent();
Chris Lattner24943d22010-06-08 16:52:24 +0000154
155 InlineFunctionInfo* inline_info = InlinedFunctionInfo ();
156 if (inline_info)
157 {
158 const Declaration &call_site = inline_info->GetCallSite();
159 if (sc)
160 {
161 // First frame, dump the first inline call site
162// if (call_site.IsValid())
163// {
164// s->PutCString(" at ");
165// call_site.DumpStopContext (s);
166// }
167 s->PutCString (" [inlined]");
168 }
169 s->EOL();
170 inline_info->DumpStopContext (s);
171 if (sc == NULL)
172 {
173 if (call_site.IsValid())
174 {
175 s->PutCString(" at ");
176 call_site.DumpStopContext (s);
177 }
178 }
179 }
180
181 if (sc)
182 {
183 // If we have any inlined functions, this will be the deepest most
184 // inlined location
185 if (sc->line_entry.IsValid())
186 {
187 s->PutCString(" at ");
188 sc->line_entry.DumpStopContext (s);
189 }
190 }
191 if (parent_block)
192 parent_block->Block::DumpStopContext (s, NULL);
193}
194
195
196void
197Block::DumpSymbolContext(Stream *s)
198{
199 m_block_list->GetFunction()->DumpSymbolContext(s);
200 s->Printf(", Block{0x%8.8x}", GetID());
201}
202
203bool
204Block::Contains (addr_t range_offset) const
205{
206 return VMRange::ContainsValue(m_ranges, range_offset);
207}
208
209bool
210Block::Contains (const VMRange& range) const
211{
212 return VMRange::ContainsRange(m_ranges, range);
213}
214
215
216
217bool
218BlockList::BlockContainsBlockWithID (const user_id_t block_id, const user_id_t find_block_id) const
219{
220 if (block_id == Block::InvalidID)
221 return false;
222
223 if (block_id == find_block_id)
224 return true;
225 else
226 {
227 user_id_t child_block_id = GetFirstChild(block_id);
228 while (child_block_id != Block::InvalidID)
229 {
230 if (BlockContainsBlockWithID (child_block_id, find_block_id))
231 return true;
232 child_block_id = GetSibling(child_block_id);
233 }
234 }
235
236 return false;
237}
238
239bool
240Block::ContainsBlockWithID (user_id_t block_id) const
241{
242 return m_block_list->BlockContainsBlockWithID (GetID(), block_id);
243}
244
245
246void
247Block::AddRange(addr_t start_offset, addr_t end_offset)
248{
249 m_ranges.resize(m_ranges.size()+1);
250 m_ranges.back().Reset(start_offset, end_offset);
251}
252
253InlineFunctionInfo*
254Block::InlinedFunctionInfo ()
255{
256 return m_inlineInfoSP.get();
257}
258
259const InlineFunctionInfo*
260Block::InlinedFunctionInfo () const
261{
262 return m_inlineInfoSP.get();
263}
264
265// Return the current number of bytes that this object occupies in memory
266size_t
267Block::MemorySize() const
268{
269 size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
270 if (m_inlineInfoSP.get())
271 mem_size += m_inlineInfoSP->MemorySize();
272 if (m_variables.get())
273 mem_size += m_variables->MemorySize();
274 return mem_size;
275
276}
277
Greg Clayton12bec712010-06-28 21:30:43 +0000278Block *
279Block::GetParent () const
280{
281 return m_block_list->GetBlockByID (m_block_list->GetParent(GetID()));
282}
283
284Block *
285Block::GetSibling () const
286{
287 return m_block_list->GetBlockByID (m_block_list->GetSibling(GetID()));
288}
289
290Block *
291Block::GetFirstChild () const
292{
293 return m_block_list->GetBlockByID (m_block_list->GetFirstChild(GetID()));
294}
295
Chris Lattner24943d22010-06-08 16:52:24 +0000296user_id_t
297Block::GetParentUID() const
298{
299 return m_block_list->GetParent(GetID());
300}
301
302user_id_t
303Block::GetSiblingUID() const
304{
305 return m_block_list->GetSibling(GetID());
306}
307
308user_id_t
309Block::GetFirstChildUID() const
310{
311 return m_block_list->GetFirstChild(GetID());
312}
313
314user_id_t
315Block::AddChild(user_id_t userID)
316{
317 return m_block_list->AddChild(GetID(), userID);
318}
319
320void
321Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
322{
323 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
324}
325
326BlockList::BlockList(Function *function, const AddressRange& range) :
327 m_function(function),
328 m_range(range),
329 m_blocks()
330{
331}
332
333BlockList::~BlockList()
334{
335}
336
337AddressRange &
338BlockList::GetAddressRange()
339{
340 return m_range;
341}
342
343const AddressRange &
344BlockList::GetAddressRange() const
345{
346 return m_range;
347}
348
349void
350BlockList::Dump(Stream *s, user_id_t blockID, uint32_t depth, bool show_context) const
351{
352 const Block* block = GetBlockByID(blockID);
353 if (block)
354 block->Dump(s, m_range.GetBaseAddress().GetFileAddress(), depth, show_context);
355}
356
357Function *
358BlockList::GetFunction()
359{
360 return m_function;
361}
362
363
364const Function *
365BlockList::GetFunction() const
366{
367 return m_function;
368}
369
370user_id_t
371BlockList::GetParent(user_id_t blockID) const
372{
373 collection::const_iterator end = m_blocks.end();
374 collection::const_iterator begin = m_blocks.begin();
375 collection::const_iterator pos = std::find_if(begin, end, UserID::IDMatches(blockID));
376
377 if (pos != end && pos != begin && pos->Depth() > 0)
378 {
379 const uint32_t parent_depth = pos->Depth() - 1;
380
381 while (--pos >= begin)
382 {
383 if (pos->Depth() == parent_depth)
384 return pos->GetID();
385 }
386 }
387 return Block::InvalidID;
388}
389
390user_id_t
391BlockList::GetSibling(user_id_t blockID) const
392{
393 collection::const_iterator end = m_blocks.end();
394 collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
395
396 if (pos != end)
397 {
398 const uint32_t sibling_depth = pos->Depth();
399 while (++pos != end)
400 {
401 uint32_t depth = pos->Depth();
402 if (depth == sibling_depth)
403 return pos->GetID();
404 if (depth < sibling_depth)
405 break;
406 }
407 }
408 return Block::InvalidID;
409}
410
411user_id_t
412BlockList::GetFirstChild(user_id_t blockID) const
413{
414 if (!m_blocks.empty())
415 {
416 if (blockID == Block::RootID)
417 {
418 return m_blocks.front().GetID();
419 }
420 else
421 {
422 collection::const_iterator end = m_blocks.end();
423 collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
424
425 if (pos != end)
426 {
427 collection::const_iterator child_pos = pos + 1;
428 if (child_pos != end)
429 {
430 if (child_pos->Depth() == pos->Depth() + 1)
431 return child_pos->GetID();
432 }
433 }
434 }
435 }
436 return Block::InvalidID;
437}
438
439
440// Return the current number of bytes that this object occupies in memory
441size_t
442BlockList::MemorySize() const
443{
444 size_t mem_size = sizeof(BlockList);
445
446 collection::const_iterator pos, end = m_blocks.end();
447 for (pos = m_blocks.begin(); pos != end; ++pos)
448 mem_size += pos->MemorySize(); // Each block can vary in size
449
450 return mem_size;
451
452}
453
454user_id_t
455BlockList::AddChild (user_id_t parentID, user_id_t childID)
456{
457 bool added = false;
458 if (parentID == Block::RootID)
459 {
460 assert(m_blocks.empty());
461 Block block(childID, 0, this);
462 m_blocks.push_back(block);
463 added = true;
464 }
465 else
466 {
467 collection::iterator end = m_blocks.end();
468 collection::iterator parent_pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(parentID));
469 assert(parent_pos != end);
470 if (parent_pos != end)
471 {
472 const uint32_t parent_sibling_depth = parent_pos->Depth();
473
474 collection::iterator insert_pos = parent_pos;
475 collection::iterator prev_sibling = end;
476 while (++insert_pos != end)
477 {
478 if (insert_pos->Depth() <= parent_sibling_depth)
479 break;
480 }
481
482 Block child_block(childID, parent_pos->Depth() + 1, this);
483 collection::iterator child_pos = m_blocks.insert(insert_pos, child_block);
484 added = true;
485 }
486 }
487 if (added)
488 return childID;
489 return Block::InvalidID;
490}
491
492const Block *
493BlockList::GetBlockByID(user_id_t blockID) const
494{
Greg Clayton12bec712010-06-28 21:30:43 +0000495 if (m_blocks.empty() || blockID == Block::InvalidID)
Chris Lattner24943d22010-06-08 16:52:24 +0000496 return NULL;
497
498 if (blockID == Block::RootID)
499 blockID = m_blocks.front().GetID();
500
501 collection::const_iterator end = m_blocks.end();
502 collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
503 if (pos != end)
504 return &(*pos);
505 return NULL;
506}
507
508Block *
509BlockList::GetBlockByID(user_id_t blockID)
510{
Greg Clayton12bec712010-06-28 21:30:43 +0000511 if (m_blocks.empty() || blockID == Block::InvalidID)
Chris Lattner24943d22010-06-08 16:52:24 +0000512 return NULL;
513
514 if (blockID == Block::RootID)
515 blockID = m_blocks.front().GetID();
516
517 collection::iterator end = m_blocks.end();
518 collection::iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
519 if (pos != end)
520 return &(*pos);
521 return NULL;
522}
523
524bool
525BlockList::AddRange(user_id_t blockID, addr_t start_offset, addr_t end_offset)
526{
527 Block *block = GetBlockByID(blockID);
528
529 if (block)
530 {
531 block->AddRange(start_offset, end_offset);
532 return true;
533 }
534 return false;
535}
536//
537//const Block *
538//BlockList::FindDeepestBlockForAddress (const Address &addr)
539//{
540// if (m_range.Contains(addr))
541// {
542// addr_t block_offset = addr.GetFileAddress() - m_range.GetBaseAddress().GetFileAddress();
543// collection::const_iterator pos, end = m_blocks.end();
544// collection::const_iterator deepest_match_pos = end;
545// for (pos = m_blocks.begin(); pos != end; ++pos)
546// {
547// if (pos->Contains (block_offset))
548// {
549// if (deepest_match_pos == end || deepest_match_pos->Depth() < pos->Depth())
550// deepest_match_pos = pos;
551// }
552// }
553// if (deepest_match_pos != end)
554// return &(*deepest_match_pos);
555// }
556// return NULL;
557//}
558//
559bool
560BlockList::SetInlinedFunctionInfo(user_id_t blockID, const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
561{
562 Block *block = GetBlockByID(blockID);
563
564 if (block)
565 {
566 block->SetInlinedFunctionInfo(name, mangled, decl_ptr, call_decl_ptr);
567 return true;
568 }
569 return false;
570}
571
572VariableListSP
573BlockList::GetVariableList(user_id_t blockID, bool get_child_variables, bool can_create)
574{
575 VariableListSP variable_list_sp;
576 Block *block = GetBlockByID(blockID);
577 if (block)
578 variable_list_sp = block->GetVariableList(get_child_variables, can_create);
579 return variable_list_sp;
580}
581
582bool
583BlockList::IsEmpty() const
584{
585 return m_blocks.empty();
586}
587
588
589
590bool
591BlockList::SetVariableList(user_id_t blockID, VariableListSP& variables)
592{
593 Block *block = GetBlockByID(blockID);
594 if (block)
595 {
596 block->SetVariableList(variables);
597 return true;
598 }
599 return false;
600
601}
602
603
604VariableListSP
605Block::GetVariableList (bool get_child_variables, bool can_create)
606{
607 VariableListSP variable_list_sp;
608 if (m_variables.get() == NULL && can_create)
609 {
610 SymbolContext sc;
611 CalculateSymbolContext(&sc);
612 assert(sc.module_sp);
613 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
614 }
615
616 if (m_variables.get())
617 {
618 variable_list_sp.reset(new VariableList());
619 if (variable_list_sp.get())
620 variable_list_sp->AddVariables(m_variables.get());
621
622 if (get_child_variables)
623 {
Greg Clayton12bec712010-06-28 21:30:43 +0000624 Block *child_block = GetFirstChild();
625 while (child_block)
Chris Lattner24943d22010-06-08 16:52:24 +0000626 {
Chris Lattner24943d22010-06-08 16:52:24 +0000627 VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create));
628 if (child_block_variable_list.get())
629 variable_list_sp->AddVariables(child_block_variable_list.get());
Greg Clayton12bec712010-06-28 21:30:43 +0000630 child_block = child_block->GetSibling();
Chris Lattner24943d22010-06-08 16:52:24 +0000631 }
632 }
633 }
634
635 return variable_list_sp;
636}
637
638uint32_t
639Block::AppendVariables (bool can_create, bool get_parent_variables, VariableList *variable_list)
640{
641 uint32_t num_variables_added = 0;
642 VariableListSP variable_list_sp(GetVariableList(false, can_create));
643
644 if (variable_list_sp.get())
645 {
646 num_variables_added = variable_list_sp->GetSize();
647 variable_list->AddVariables(variable_list_sp.get());
648 }
649
650 if (get_parent_variables)
651 {
Greg Clayton12bec712010-06-28 21:30:43 +0000652 Block* parent_block = GetParent();
653 if (parent_block)
654 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, variable_list);
Chris Lattner24943d22010-06-08 16:52:24 +0000655 }
656 return num_variables_added;
657}
658
659
660void
661Block::SetVariableList(VariableListSP& variables)
662{
663 m_variables = variables;
664}
665
666uint32_t
667Block::Depth () const
668{
669 return m_depth;
670}
671