OpenASIP  2.0
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 
41 using std::string;
42 using namespace TTAMachine;
43 
44 namespace TTAProgram {
45 
46 const int Procedure::INSTRUCTION_INDEX_ALIGNMENT = 1;
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  */
59 Procedure::Procedure(
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  */
81 }
82 
83 /**
84  * Returns the alignment.
85  *
86  * @return The alignment.
87  */
88 int
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  */
100 Address
101 Procedure::address(const Instruction& ins) const {
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  */
159 void
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  */
192 void
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
218  throw IllegalRegistration(
219  __FILE__,__LINE__,__func__,"pos not in this procedure");
220 
221  } else {
222  throw IllegalRegistration(
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  */
241 void
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 {
274  throw IllegalRegistration(
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  */
296 void
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  */
344 void
346  int insCount = instructionCount();
348 
349  if (parent_ != NULL && this != &parent_->lastProcedure()) {
351  parent_->nextProcedure(*this), -insCount);
352  }
353 }
354 
355 }
TTAProgram
Definition: Estimator.hh:65
UIntWord
Word UIntWord
Definition: BaseType.hh:144
InstructionAddress
UInt32 InstructionAddress
Definition: BaseType.hh:175
TTAProgram::CodeSnippet::firstInstruction
virtual Instruction & firstInstruction() const
Definition: CodeSnippet.cc:216
NullProcedure.hh
TTAProgram::Address
Definition: Address.hh:51
TTAMachine::AddressSpace
Definition: AddressSpace.hh:51
TTAProgram::Procedure::remove
void remove(Instruction &ins)
Definition: Procedure.cc:297
TTAProgram::CodeSnippet::clear
virtual void clear()
Definition: CodeSnippet.cc:89
TTAProgram::Instruction
Definition: Instruction.hh:57
Procedure.hh
TTAProgram::NullProcedure::instance
static NullProcedure & instance()
Definition: NullProcedure.cc:68
TTAProgram::Address::space
const TTAMachine::AddressSpace & space() const
TTAProgram::Procedure::address
Address address(const Instruction &ins) const
Definition: Procedure.cc:101
TTAProgram::Procedure::insertAfter
void insertAfter(const Instruction &pos, Instruction *ins)
Definition: Procedure.cc:193
TTAProgram::Procedure::name_
const TCEString name_
The name of the procedure.
Definition: Procedure.hh:97
TTAProgram::Procedure::copy
CodeSnippet * copy() const
Definition: Procedure.cc:137
TTAProgram::Procedure::alignment_
int alignment_
The alignment of instructions.
Definition: Procedure.hh:99
GlobalScope.hh
assert
#define assert(condition)
Definition: Application.hh:86
TTAProgram::Program::nextProcedure
Procedure & nextProcedure(const Procedure &proc) const
Definition: Program.cc:250
TTAProgram::Program::moveProcedure
void moveProcedure(Procedure &proc, int howMuch)
Definition: Program.cc:588
TTAProgram::CodeSnippet::instructionCount
virtual int instructionCount() const
Definition: CodeSnippet.cc:205
TTAProgram::Instruction::copy
Instruction * copy() const
Definition: Instruction.cc:379
TTAProgram::InstructionReferenceManager::hasReference
bool hasReference(Instruction &ins) const
Definition: InstructionReferenceManager.cc:143
TTAProgram::Procedure::~Procedure
virtual ~Procedure()
Definition: Procedure.cc:80
NullInstruction.hh
__func__
#define __func__
Definition: Application.hh:67
TTAProgram::Instruction::parent
CodeSnippet & parent() const
Definition: Instruction.cc:109
TTAProgram::Procedure::clear
void clear()
Definition: Procedure.cc:345
TTAProgram::Address::location
InstructionAddress location() const
TTAProgram::Procedure::insertBefore
void insertBefore(const Instruction &pos, Instruction *ins)
Definition: Procedure.cc:242
TTAProgram::GlobalScope::removeCodeLabels
virtual void removeCodeLabels(InstructionAddress address)
Definition: GlobalScope.cc:363
TTAProgram::CodeSnippet
Definition: CodeSnippet.hh:59
IllegalRegistration
Definition: Exception.hh:532
TTAProgram::Instruction::setParent
void setParent(CodeSnippet &proc)
Definition: Instruction.cc:124
TTAProgram::Instruction::isInProcedure
bool isInProcedure() const
Definition: Instruction.cc:135
TTAProgram::Procedure::add
void add(Instruction *ins)
Definition: Procedure.cc:160
TTAProgram::InstructionReferenceManager
Definition: InstructionReferenceManager.hh:82
TTAProgram::Program::instructionReferenceManager
InstructionReferenceManager & instructionReferenceManager() const
Definition: Program.cc:688
Program.hh
TTAProgram::CodeSnippet::parent
virtual Program & parent() const
Definition: CodeSnippet.cc:118
TCEString
Definition: TCEString.hh:53
TTAProgram::Procedure::Procedure
Procedure(const TCEString &name, const TTAMachine::AddressSpace &space)
Definition: Procedure.cc:59
TTAProgram::CodeSnippet::parent_
Program * parent_
The parent program of the procedure.
Definition: CodeSnippet.hh:128
InstructionReferenceManager.hh
TTAProgram::CodeSnippet::instructionAtIndex
virtual Instruction & instructionAtIndex(int index) const
Definition: CodeSnippet.cc:285
TTAProgram::Program::lastProcedure
Procedure & lastProcedure() const
Definition: Program.cc:230
TTAProgram::Program::globalScope
GlobalScope & globalScope()
Definition: Program.cc:180
TTAMachine
Definition: Assembler.hh:48
NullProgram.hh
TTAProgram::CodeSnippet::instructions_
InsList instructions_
The instructions in this procedure.
Definition: CodeSnippet.hh:126
TTAProgram::Procedure
Definition: Procedure.hh:55
TTAProgram::CodeSnippet::startAddr_
Address startAddr_
The start (lowest) address of the procedure.
Definition: CodeSnippet.hh:130
TTAProgram::Instruction::hasFinalAddress
bool hasFinalAddress() const
Definition: Instruction.hh:100
TTAProgram::Instruction::address
Address address() const
Definition: Instruction.cc:327
TTAProgram::Procedure::alignment
int alignment() const
Definition: Procedure.cc:89
TTAProgram::CodeSnippet::isInProgram
virtual bool isInProgram() const
Definition: CodeSnippet.cc:151