1//===-- LineEntry.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/LineEntry.h"
11#include "lldb/Symbol/CompileUnit.h"
12#include "lldb/Target/Process.h"
13#include "lldb/Target/Target.h"
14
15using namespace lldb_private;
16
17LineEntry::LineEntry() :
18    range(),
19    file(),
20    line(0),
21    column(0),
22    is_start_of_statement(0),
23    is_start_of_basic_block(0),
24    is_prologue_end(0),
25    is_epilogue_begin(0),
26    is_terminal_entry(0)
27{
28}
29
30LineEntry::LineEntry
31(
32    const lldb::SectionSP &section_sp,
33    lldb::addr_t section_offset,
34    lldb::addr_t byte_size,
35    const FileSpec &_file,
36    uint32_t _line,
37    uint16_t _column,
38    bool _is_start_of_statement,
39    bool _is_start_of_basic_block,
40    bool _is_prologue_end,
41    bool _is_epilogue_begin,
42    bool _is_terminal_entry
43) :
44    range(section_sp, section_offset, byte_size),
45    file(_file),
46    line(_line),
47    column(_column),
48    is_start_of_statement(_is_start_of_statement),
49    is_start_of_basic_block(_is_start_of_basic_block),
50    is_prologue_end(_is_prologue_end),
51    is_epilogue_begin(_is_epilogue_begin),
52    is_terminal_entry(_is_terminal_entry)
53{
54}
55
56void
57LineEntry::Clear()
58{
59    range.Clear();
60    file.Clear();
61    line = 0;
62    column = 0;
63    is_start_of_statement = 0;
64    is_start_of_basic_block = 0;
65    is_prologue_end = 0;
66    is_epilogue_begin = 0;
67    is_terminal_entry = 0;
68}
69
70
71bool
72LineEntry::IsValid() const
73{
74    return range.GetBaseAddress().IsValid() && line != 0;
75}
76
77bool
78LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const
79{
80    bool result = false;
81    if (file)
82    {
83        if (show_fullpaths)
84            file.Dump (s);
85        else
86            file.GetFilename().Dump (s);
87
88        if (line)
89            s->PutChar(':');
90        result = true;
91    }
92    if (line)
93        s->Printf ("%u", line);
94    else
95        result = false;
96
97    return result;
98}
99
100bool
101LineEntry::Dump
102(
103    Stream *s,
104    Target *target,
105    bool show_file,
106    Address::DumpStyle style,
107    Address::DumpStyle fallback_style,
108    bool show_range
109) const
110{
111    if (show_range)
112    {
113        // Show address range
114        if (!range.Dump(s, target, style, fallback_style))
115            return false;
116    }
117    else
118    {
119        // Show address only
120        if (!range.GetBaseAddress().Dump(s,
121                                         target,
122                                         style,
123                                         fallback_style))
124            return false;
125    }
126    if (show_file)
127        *s << ", file = " << file;
128    if (line)
129        s->Printf(", line = %u", line);
130    if (column)
131        s->Printf(", column = %u", column);
132    if (is_start_of_statement)
133        *s << ", is_start_of_statement = TRUE";
134
135    if (is_start_of_basic_block)
136        *s << ", is_start_of_basic_block = TRUE";
137
138    if (is_prologue_end)
139        *s << ", is_prologue_end = TRUE";
140
141    if (is_epilogue_begin)
142        *s << ", is_epilogue_begin = TRUE";
143
144    if (is_terminal_entry)
145        *s << ", is_terminal_entry = TRUE";
146    return true;
147}
148
149bool
150LineEntry::GetDescription (Stream *s, lldb::DescriptionLevel level, CompileUnit* cu, Target *target, bool show_address_only) const
151{
152
153    if (level == lldb::eDescriptionLevelBrief || level == lldb::eDescriptionLevelFull)
154    {
155        if (show_address_only)
156        {
157            range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
158        }
159        else
160        {
161            range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
162        }
163
164        *s << ": " << file;
165
166        if (line)
167        {
168            s->Printf(":%u", line);
169            if (column)
170                s->Printf(":%u", column);
171        }
172
173
174        if (level == lldb::eDescriptionLevelFull)
175        {
176            if (is_start_of_statement)
177                *s << ", is_start_of_statement = TRUE";
178
179            if (is_start_of_basic_block)
180                *s << ", is_start_of_basic_block = TRUE";
181
182            if (is_prologue_end)
183                *s << ", is_prologue_end = TRUE";
184
185            if (is_epilogue_begin)
186                *s << ", is_epilogue_begin = TRUE";
187
188            if (is_terminal_entry)
189                *s << ", is_terminal_entry = TRUE";
190        }
191        else
192        {
193            if (is_terminal_entry)
194                s->EOL();
195        }
196    }
197    else
198    {
199        return Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
200    }
201    return true;
202}
203
204
205bool
206lldb_private::operator< (const LineEntry& a, const LineEntry& b)
207{
208    return LineEntry::Compare (a, b) < 0;
209}
210
211int
212LineEntry::Compare (const LineEntry& a, const LineEntry& b)
213{
214    int result = Address::CompareFileAddress (a.range.GetBaseAddress(), b.range.GetBaseAddress());
215    if (result != 0)
216        return result;
217
218    const lldb::addr_t a_byte_size = a.range.GetByteSize();
219    const lldb::addr_t b_byte_size = b.range.GetByteSize();
220
221    if (a_byte_size < b_byte_size)
222        return -1;
223    if (a_byte_size > b_byte_size)
224        return +1;
225
226    // Check for an end sequence entry mismatch after we have determined
227    // that the address values are equal. If one of the items is an end
228    // sequence, we don't care about the line, file, or column info.
229    if (a.is_terminal_entry > b.is_terminal_entry)
230        return -1;
231    if (a.is_terminal_entry < b.is_terminal_entry)
232        return +1;
233
234    if (a.line < b.line)
235        return -1;
236    if (a.line > b.line)
237        return +1;
238
239    if (a.column < b.column)
240        return -1;
241    if (a.column > b.column)
242        return +1;
243
244    return FileSpec::Compare (a.file, b.file, true);
245}
246
247