OpenASIP 2.2
Loading...
Searching...
No Matches
Procedure.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file Procedure.cc
26 *
27 * Implementation of Procedure class.
28 *
29 * @author Ari Metsähalme 2005 (ari.metsahalme-no.spam-tut.fi)
30 * @note rating: red
31 */
32
33#include "Procedure.hh"
34#include "Program.hh"
35#include "NullProgram.hh"
36#include "NullProcedure.hh"
37#include "NullInstruction.hh"
39#include "GlobalScope.hh"
40
41using std::string;
42using namespace TTAMachine;
43
44namespace TTAProgram {
45
47
48/**
49 * Constructor.
50 *
51 * Create an empty procedure in given address space. Automatically
52 * create an empty procedure scope to store all program symbols that
53 * are local to this procedure. The default value zero will be used
54 * for the start location. Alignment is 1 MAU.
55 *
56 * @param name Name of the procedure.
57 * @param space The address space of the procedure.
58 */
60 const TCEString& name, const AddressSpace& space):
61 CodeSnippet(Address(0, space)), name_(name) {
62}
63
64/**
65 * Alternative constructor that takes the start location of the procedure.
66 *
67 * @param name Name of the procedure.
68 * @param space The address space of the procedure.
69 * @param startLocation The start location of the procedure.
70 */
72 const TCEString& name, const AddressSpace& space,
73 UIntWord startLocation):
74 CodeSnippet(Address(startLocation, space)), name_(name) {
75}
76
77/**
78 * Destructor
79 */
82
83/**
84 * Returns the alignment.
85 *
86 * @return The alignment.
87 */
88int
90 return alignment_;
91}
92
93/**
94 * Returns the address of the given instruction.
95 *
96 * @return The address of the given instruction.
97 * @exception IllegalRegistration if the instruction does not belong to
98 * this procedure.
99 */
102 if (isInProgram() && ins.hasFinalAddress())
103 return ins.address();
104
105 assert (!isInProgram() || parent().isInstructionPerAddress());
106
107 // In case the instruction does not have a fixed final address,
108 // compute it according to its current position in the instruction.
109 unsigned int i = 0;
110
111 /* This loop is executed very often so
112 uses pre-computed size and [] for performance reasons.
113 TO CLEANUP: std::find() ? */
114 const unsigned int size = instructions_.size();
115 while (i < size && instructions_[i] != &ins) {
116 i++;
117 }
118
119 if (i < instructions_.size()) {
120 Address insAddress(
122 return insAddress;
123 } else {
124 throw IllegalRegistration(__FILE__, __LINE__);
125 }
126}
127
128/**
129 * Make a complete copy of the procedure.
130 *
131 * The copy is identical, except that it is not registered to the
132 * program of the original procedure.
133 *
134 * @return A complete copy of the procedure.
135 */
138
139 Procedure* newProc = new Procedure(
141 for (int i = 0; i < instructionCount(); i++) {
142 Instruction* insCopy = instructionAtIndex(i).copy();
143 newProc->add(insCopy);
144 }
145 return newProc;
146}
147
148/**
149 * Adds an instruction as the last instruction in the procedure.
150 *
151 * Remaining procedures in the parent program will be relocated as
152 * needed. The ownership of the instruction will be passed to the
153 * procedure.
154 *
155 * @param ins The instruction to add.
156 * @exception IllegalRegistration if the instruction is already registered
157 * in another procedure.
158 */
159void
161 if (!ins->isInProcedure() || &ins->parent() == this) {
162
163 if (instructions_.size() == instructions_.capacity()) {
164 instructions_.reserve(instructions_.size() * 2);
165 }
166
167 ins->setParent(*this);
168 instructions_.push_back(ins);
169
170 // if registered to a program, tell to move the procedures
171 // after the added instruction
172 if (parent_ != NULL && this != &parent_->lastProcedure()) {
174 parent_->nextProcedure(*this), 1);
175 }
176
177 } else {
178 throw IllegalRegistration(__FILE__, __LINE__);
179 }
180}
181
182/**
183 * Insert the given instruction after the given position.
184 *
185 * Instructions from pos are relocated to make room for the new instruction.
186 *
187 * @param pos The position.
188 * @param ins The instruction to insert.
189 * @exception IllegalRegistration if pos does not belong to the procedure
190 * or ins already belongs to a procedure.
191 */
192void
194 if (!ins->isInProcedure()) {
195 for (InsList::iterator iter = instructions_.begin();
196 iter != instructions_.end(); iter++) {
197
198 if ((*iter) == &pos) {
199 iter++;
200 if (iter != instructions_.end()) {
201 ins->setParent(*this);
202 instructions_.insert(iter, ins);
203
204 // if registered to a program, tell to move the procedures
205 // after this procedure
206 if (parent_ != NULL && this != &parent_->lastProcedure()) {
208 parent_->nextProcedure(*this), 1);
209 }
210 return;
211 } else { // end of procedure
212 add(ins);
213 return;
214 }
215 }
216 }
217 // should not go here in any case
219 __FILE__,__LINE__,__func__,"pos not in this procedure");
220
221 } else {
223 __FILE__, __LINE__, "CodeSnippet::insertInstructionBefore",
224 "Instruction already belongs to a procedure.");
225 }
226}
227
228/**
229 * Insert the given instruction before the given position.
230 *
231 * Instructions from and including pos are relocated to make room for
232 * the new instruction.
233 *
234 * @todo Refactor and share implementation with insertInstructionAfter()
235 *
236 * @param pos The position.
237 * @param ins The instruction to insert.
238 * @exception IllegalRegistration if pos does not belong to the procedure
239 * or ins already belongs to a procedure.
240 */
241void
243 if (!ins->isInProcedure()) {
244
245 InsList::iterator iter = instructions_.begin();
246 const Instruction& next = pos;
247
248 while (iter != instructions_.end()) {
249
250 if ((*iter) == &next) {
251
252 ins->setParent(*this);
253
254 iter = instructions_.insert(iter, ins);
255
256 iter++;
257
258 // if registered to a program, tell to move the procedures
259 // after this procedure
260 if (parent_ != NULL && this != &parent_->lastProcedure()) {
262 parent_->nextProcedure(*this), 1);
263 }
264 return;
265 }
266
267 iter++;
268 }
269
270 // should not go here in any case
271 assert(false);
272
273 } else {
275 __FILE__, __LINE__, "CodeSnippet::insertInstructionBefore",
276 "Instruction already belongs to a procedure.");
277 }
278}
279
280/**
281 * Remove instruction from the procedure.
282 *
283 * The instruction becomes independent (it is not deleted). All
284 * instructions following the removed procedure are relocated
285 * appropriately. All code labels attached to the removed instruction
286 * are deleted from the Program.
287 *
288 * @note Possible references to the instruction elsewhere
289 * in the program are not automatically fixed! It's a responsibility of
290 * the caller to fix the Program back to a consistent state.
291 *
292 * @param ins Instruction to remove.
293 * @exception IllegalRegistration If instruction does not belong to the
294 * procedure.
295 */
296void
298 bool first = false;
299 bool refs = false;
300
301 if( parent_ != NULL ) {
304 refs = irm.hasReference(ins);
305 }
306
307 if (!ins.isInProcedure() || !(&ins.parent() == this)) {
308 string msg = "Instruction doesn't belong to the procedure.";
309 throw IllegalRegistration(__FILE__, __LINE__, __func__, msg);
310 }
311
312 if (&ins == &firstInstruction()) {
313 first = true;
314 }
315
316 int insIndex = 0;
317 for (InsList::iterator iter = instructions_.begin();
318 iter != instructions_.end(); iter++, insIndex++) {
319 if ((*iter) == &ins) {
320
321 iter = instructions_.erase(iter);
322 const InstructionAddress addr = startAddr_.location() + insIndex;
323
324 // remove code label of first instruction only if empty
325 if ((!first && refs) || instructions_.empty()) {
327 }
328
330
331 if (parent_ != NULL && this != &parent_->lastProcedure()) {
333 parent_->nextProcedure(*this), -1);
334 }
335
336 return;
337 }
338 }
339}
340
341/**
342 * Clears a procedure, updates addresses of following addresses.
343 */
344void
346 int insCount = instructionCount();
348
349 if (parent_ != NULL && this != &parent_->lastProcedure()) {
351 parent_->nextProcedure(*this), -insCount);
352 }
353}
354
355}
#define __func__
#define assert(condition)
Word UIntWord
Definition BaseType.hh:144
UInt32 InstructionAddress
Definition BaseType.hh:175
const TTAMachine::AddressSpace & space() const
InstructionAddress location() const
Address startAddr_
The start (lowest) address of the procedure.
virtual Instruction & firstInstruction() const
virtual bool isInProgram() const
Program * parent_
The parent program of the procedure.
virtual int instructionCount() const
InsList instructions_
The instructions in this procedure.
virtual Program & parent() const
virtual Instruction & instructionAtIndex(int index) const
virtual void removeCodeLabels(InstructionAddress address)
Instruction * copy() const
Address address() const
bool hasFinalAddress() const
CodeSnippet & parent() const
void setParent(CodeSnippet &proc)
static NullProcedure & instance()
void add(Instruction *ins)
Definition Procedure.cc:160
int alignment() const
Definition Procedure.cc:89
CodeSnippet * copy() const
Definition Procedure.cc:137
Address address(const Instruction &ins) const
Definition Procedure.cc:101
Procedure(const TCEString &name, const TTAMachine::AddressSpace &space)
Definition Procedure.cc:59
int alignment_
The alignment of instructions.
Definition Procedure.hh:99
void remove(Instruction &ins)
Definition Procedure.cc:297
const TCEString name_
The name of the procedure.
Definition Procedure.hh:97
void insertAfter(const Instruction &pos, Instruction *ins)
Definition Procedure.cc:193
void insertBefore(const Instruction &pos, Instruction *ins)
Definition Procedure.cc:242
static const int INSTRUCTION_INDEX_ALIGNMENT
The default alignment of instructions.
Definition Procedure.hh:101
GlobalScope & globalScope()
Definition Program.cc:180
void moveProcedure(Procedure &proc, int howMuch)
Definition Program.cc:588
Procedure & nextProcedure(const Procedure &proc) const
Definition Program.cc:250
InstructionReferenceManager & instructionReferenceManager() const
Definition Program.cc:688
Procedure & lastProcedure() const
Definition Program.cc:230