1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "DisassembledCode.h"
8
9#include <stdlib.h>
10#include <string.h>
11
12#include <new>
13
14#include <String.h>
15
16#include "SourceLanguage.h"
17#include "Statement.h"
18
19
20struct DisassembledCode::Line {
21	BString					line;
22	ContiguousStatement*	statement;
23
24	Line(const BString& line, ContiguousStatement* statement)
25		:
26		line(line),
27		statement(statement)
28	{
29	}
30};
31
32
33DisassembledCode::DisassembledCode(SourceLanguage* language)
34	:
35	fLanguage(language),
36	fLines(20, true)
37{
38	fLanguage->AcquireReference();
39}
40
41
42DisassembledCode::~DisassembledCode()
43{
44	for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++)
45		statement->ReleaseReference();
46
47	fLanguage->ReleaseReference();
48}
49
50
51bool
52DisassembledCode::Lock()
53{
54	// We're immutable, so no locking required.
55	return true;
56}
57
58
59void
60DisassembledCode::Unlock()
61{
62}
63
64
65SourceLanguage*
66DisassembledCode::GetSourceLanguage() const
67{
68	return fLanguage;
69}
70
71
72int32
73DisassembledCode::CountLines() const
74{
75	return fLines.CountItems();
76}
77
78
79const char*
80DisassembledCode::LineAt(int32 index) const
81{
82	Line* line = fLines.ItemAt(index);
83	return line != NULL ? line->line.String() : NULL;
84}
85
86
87int32
88DisassembledCode::LineLengthAt(int32 index) const
89{
90	Line* line = fLines.ItemAt(index);
91	return line != NULL ? line->line.Length() : 0;
92}
93
94
95bool
96DisassembledCode::GetStatementLocationRange(const SourceLocation& location,
97	SourceLocation& _start, SourceLocation& _end) const
98{
99	Line* line = fLines.ItemAt(location.Line());
100	if (line == NULL || line->statement == NULL)
101		return false;
102
103	_start = line->statement->StartSourceLocation();
104	_end = SourceLocation(_start.Line() + 1);
105		// TODO: Multi-line instructions!
106	return true;
107}
108
109
110LocatableFile*
111DisassembledCode::GetSourceFile() const
112{
113	return NULL;
114}
115
116
117Statement*
118DisassembledCode::StatementAtLocation(const SourceLocation& location) const
119{
120	Line* line = fLines.ItemAt(location.Line());
121	return line != NULL ? line->statement : NULL;
122}
123
124
125Statement*
126DisassembledCode::StatementAtAddress(target_addr_t address) const
127{
128	return fStatements.BinarySearchByKey(address, &_CompareAddressStatement);
129}
130
131
132TargetAddressRange
133DisassembledCode::StatementAddressRange() const
134{
135	if (fStatements.IsEmpty())
136		return TargetAddressRange();
137
138	ContiguousStatement* first = fStatements.ItemAt(0);
139	ContiguousStatement* last
140		= fStatements.ItemAt(fStatements.CountItems() - 1);
141	return TargetAddressRange(first->AddressRange().Start(),
142		last->AddressRange().End());
143}
144
145
146bool
147DisassembledCode::AddCommentLine(const BString& line)
148{
149	return _AddLine(line, NULL);
150}
151
152
153bool
154DisassembledCode::AddInstructionLine(const BString& line, target_addr_t address,
155	target_size_t size)
156{
157	int32 lineIndex = fLines.CountItems();
158
159	ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
160		SourceLocation(lineIndex), TargetAddressRange(address, size));
161	if (statement == NULL)
162		return false;
163
164	if (!fStatements.AddItem(statement)) {
165		delete statement;
166		return false;
167	}
168
169	if (!_AddLine(line, statement))
170		return false;
171
172	return true;
173}
174
175
176bool
177DisassembledCode::_AddLine(const BString& _line, ContiguousStatement* statement)
178{
179	Line* line = new(std::nothrow) Line(_line, statement);
180	if (line == NULL)
181		return false;
182
183	if (!fLines.AddItem(line)) {
184		delete line;
185		return false;
186	}
187
188	return true;
189}
190
191
192/*static*/ int
193DisassembledCode::_CompareAddressStatement(const target_addr_t* address,
194	const ContiguousStatement* statement)
195{
196	const TargetAddressRange& range = statement->AddressRange();
197
198	if (*address < range.Start())
199		return -1;
200	return *address < range.End() ? 0 : 1;
201}
202
203