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