OpenASIP 2.2
Loading...
Searching...
No Matches
CodeSnippet.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 CodeSnippet.cc
26 *
27 * Implementation of CodeSnippet class.
28 *
29 * @author Ari Metsähalme 2005 (ari.metsahalme-no.spam-tut.fi)
30 * @note rating: red
31 */
32
33#include "CodeSnippet.hh"
34#include "ContainerTools.hh"
35#include "POMDisassembler.hh"
36
37#include "NullAddressSpace.hh"
38#include "NullInstruction.hh"
40#include "NullProgram.hh"
41#include "NullProcedure.hh"
42#include "Conversion.hh"
43
44using std::string;
45
46namespace TTAProgram {
47
48/////////////////////////////////////////////////////////////////////////////
49// CodeSnippet
50/////////////////////////////////////////////////////////////////////////////
51
52/**
53 * Constructor.
54 */
56 parent_(NULL),
57 startAddr_(0, TTAMachine::NullAddressSpace::instance()),
58 endAddr_((InstructionAddress)-1,
59 TTAMachine::NullAddressSpace::instance()) {
60}
61
62/**
63 * Constructor.
64 */
66 parent_(NULL), startAddr_(start), endAddr_(start) {
67}
68
69
70/**
71 * The destructor.
72 */
74 for (unsigned int i = 0; i < instructions_.size(); i++) {
76 delete instructions_.at(i);
77 }
78 }
79 instructions_.clear();
80}
81
82/**
83 * Clears the code snippet.
84 *
85 * Removes all instruction references inside the snippet and deletes
86 * the instructions.
87 */
88void
90 for (unsigned int i = 0; i < instructions_.size(); i++) {
92 delete instructions_.at(i);
93 }
94 }
97
98/**
99 * Remove one instruction from the end of the code snippet.
100 *
101 * Nothing happens if the code snippet is empty.
102 */
103void
105 if (!instructions_.empty()) {
106 instructions_.pop_back();
107 }
108}
110/**
111 * Return the parent program that contains the code snippet.
113 * @return The parent program that contains the code snippet
114 * @exception IllegalRegistration If the code snippet is not registered
115 * anywhere.
116 */
117Program&
119 if (parent_ != NULL) {
120 return *parent_;
121 } else {
122 throw IllegalRegistration(__FILE__, __LINE__,__func__,"no parent");
123 }
124}
125
126/**
127 * Sets the parent program of the code snippet.
128 *
129 * @note This method does not check that the code snippet actually belongs to
130 * the given program. It should, therefore be called only be
131 * Program::addProcedure().
132 *
133 * @param prog The new parent program.
134 */
135void
137 if (&prog == &NullProgram::instance()) {
138 parent_ = NULL;
139 } else {
140 parent_ = &prog;
141 }
142}
143
144/**
145 * Tells whether the code snippet belongs to a program.
146 *
147 * @return True if the code snippet belongs to a program (it is registered),
148 * false otherwise.
149 */
150bool
152 return (parent_ != NULL && parent_ != &NullProgram::instance());
153}
154
155/**
156 * Returns the address of the given instruction.
157 *
158 * @return The address of the given instruction.
159 * @exception IllegalRegistration if the instruction does not belong to
160 * this code snippet.
161 */
164 if (ins.hasFinalAddress()) return ins.address();
165
166 unsigned int i = 0;
167
168 /* this loop is executed very often, so it
169 uses a pre-computed size and [] for performance reasons.
170 TO CLEANUP: why not use std::find()? */
171 const unsigned int size = instructions_.size();
172 while (i < size && instructions_[i] != &ins) {
173 i++;
174 }
175
176 if (i != instructions_.size()) {
177 Address insAddress(
179 return insAddress;
180 } else {
182 __FILE__, __LINE__, __func__, "Instruction not in CodeSnippet");
183 }
184}
185
186/**
187 * Sets the start address of the code snippet.
188 */
189void
193
194void
198
199/**
200 * Returns the number of instructions in this code snippet.
201 *
202 * @return the number of instructions in this code snippet.
203 */
204int
206 return instructions_.size();
207}
208
209/**
210 * Returns the first instruction in the code snippet.
211 *
212 * @return The first instruction in the code snippet.
213 * @exception InstanceNotFound if there are no instructions in the code snippet.
214 */
217 if (!instructions_.empty()) {
218 return *instructions_.at(0);
219 } else {
220 throw InstanceNotFound(
221 __FILE__, __LINE__, __func__, "No instructions.");
222 }
223}
224
225/**
226 * Returns the explicit instruction at a given address.
227 *
228 * The address space of the address is implied, since there is only
229 * one address space for instructions. In case there are multiple
230 * instructions at the given address, only one of them is considered
231 * explicit, others implicit. The implicit instructions are detected
232 * by having a size of 0.
233 *
234 * @param address The instruction address.
235 * @note This is a slow method to traverse instructions, it's O(N).
236 * @exception KeyNotFound if given address is illegal.
237 * @todo Rename to instruction() to match Program::procedure() and
238 * Instruction::move().
239 */
242 if (isInProgram() && !parent().isInstructionPerAddress()) {
243 // In the finalized program, there might not be one instruction
244 // per index, thus we have to find the instruction by an
245 // exhaustive search. @todo optimize this in case it's a
246 // bottleneck somewhere.
247
248 for (size_t i = 0; i < instructions_.size(); ++i) {
249 Instruction* ins = instructions_.at(i);
250 if (ins->address().location() == address &&
251 ins->size() > 0)
252 return *ins;
253 }
254 } else {
255 int index = (address - startAddr_.location());
256 if (index >= 0 && static_cast<unsigned int>(index) <
257 instructions_.size()) {
258 Instruction* ins = instructions_.at(index);
259 if (ins == &NullInstruction::instance()) {
260 throw KeyNotFound(__FILE__, __LINE__);
261 } else {
262 return *ins;
263 }
264 }
265 }
266 std::string msg = "Address " + Conversion::toString(address) +
267 " not in this codesnippet( " +
270 instructions_.size()-1)
271 + " )";
272 throw KeyNotFound(__FILE__, __LINE__, __func__, msg );
273}
274
275/**
276 * Returns the instruction at a given index in the container of instructions.
277 *
278 * This method is for quickly traversing through all the instructions within
279 * time critical loops.
280 *
281 * @param index The instruction index in the list of instructions.
282 * @return The Instruction at the given index.
283 */
286 return *instructions_.at(index);
287}
288
290CodeSnippet::operator[](size_t index) const {
291 return *instructions_[index];
292}
293
294/**
295 * Tells whether the given instruction is the last instruction of the
296 * code snippet or not.
297 *
298 * @param ins The instruction to compare.
299 * @return True if the given instruction is not the last instruction in
300 * the code snippet, false otherwise.
301 */
302bool
306
307/**
308 * Returns the next instruction in the instruction stream.
309 *
310 * @return The next instruction in the instruction stream or a special
311 * null instruction if the given instruction is the last instruction
312 * of the code snippet.
313 *
314 * @exception IllegalRegistration If given instruction does not belong
315 * to the code snippet.
316 */
319 if (&ins.parent() != this)
320 throw IllegalRegistration(__FILE__, __LINE__);
321
322 if (isInProgram() && !parent().isInstructionPerAddress()) {
323 InsList::const_iterator pos =
324 std::find(instructions_.begin(), instructions_.end(), &ins);
325 if (pos == instructions_.end() || pos+1 == instructions_.end())
327 else
328 return **(pos+1);
329 } else {
330 int insAddress = ins.address().location();
331
332 unsigned int current = (insAddress - startAddr_.location());
333 unsigned int next = current + 1;
334
335 if (next < instructions_.size())
336 return *instructions_.at(next);
337 else
339 }
340}
341
342/**
343 * Return the previous instruction in the instruction stream.
344 *
345 * @return The previous instruction in the instruction stream or a special
346 * null instruction if the given instruction is the first instruction
347 * of the code snippet.
348 * @exception IllegalRegistration If given instruction does not belong
349 * to the code snippet.
350 */
353 if (&ins.parent() != this)
354 throw IllegalRegistration(__FILE__, __LINE__, __func__);
355
356 if (isInProgram() && !parent().isInstructionPerAddress()) {
357 InsList::const_iterator pos =
358 std::find(instructions_.begin(), instructions_.end(), &ins);
359
360 if (pos == instructions_.begin())
362
363 return *const_cast<Instruction*>(*(--pos));
364 } else {
365 int insAddress =
366 (ins.address().location() - startAddr_.location()) - 1;
367 while (insAddress >= 0) {
368 Instruction& prevIns = *instructions_.at(insAddress);
369 if (&prevIns != &NullInstruction::instance()) {
370 return prevIns;
371 } else {
372 insAddress--;
373 }
374 }
376 }
377}
378
379/**
380 * Returns the last instruction in the code snippet.
381 *
382 * @return The last instruction in the code snippet.
383 * @exception IllegalRegistration if there are no instructions in the
384 * code snippet.
385 */
388 if (!instructions_.empty()) {
389 return *instructions_.back();
390 } else {
391 throw IllegalRegistration(__FILE__, __LINE__);
392 }
393}
394
395/**
396 * Adds an instruction as the first instruction in the code snippet.
397 *
398 * The ownership of the instruction will be passed to the
399 * code snippet.
400 *
401 * @param ins The instruction to add.
402 * @exception IllegalRegistration if the instruction is already registered
403 * in another code snippet.
404 */
405void
407 if (!ins->isInProcedure()) {
408
409 if (instructions_.size() == instructions_.capacity()) {
410 instructions_.reserve(instructions_.size() * 2);
411 }
412
413 ins->setParent(*this);
414 instructions_.insert(instructions_.begin(), ins);
415
416 } else {
417 throw IllegalRegistration(__FILE__, __LINE__);
418 }
419}
420
421/**
422 * Adds an instruction as the last instruction in the code snippet.
423 *
424 * The ownership of the instruction will be passed to the
425 * code snippet.
426 *
427 * @param ins The instruction to add.
428 * @exception IllegalRegistration if the instruction is already registered
429 * in another code snippet.
430 */
431void
433 if (!ins->isInProcedure()) {
434
435 if (instructions_.size() == instructions_.capacity()) {
436 instructions_.reserve(instructions_.size() * 2);
437 }
438
439 ins->setParent(*this);
440 instructions_.push_back(ins);
441
442 } else {
443 throw IllegalRegistration(__FILE__, __LINE__, __func__,
444 "Instruction: " +
446 + " allready has parent:\n " +
447 ins->parent().disassembly());
448 }
449}
450
451/**
452 * Insert the given instruction after the given position.
453 *
454 * Instructions from pos are relocated to make room for the new instruction.
455 *
456 * @param pos The position.
457 * @param ins The instruction to insert.
458 * @exception IllegalRegistration if pos does not belong to the code snippet
459 * or ins already belongs to a code snippet.
460 */
461void
463 if (!ins->isInProcedure()) {
464
465 if (hasNextInstruction(pos)) {
466
467 InsList::iterator iter = instructions_.begin();
468 Instruction& next = nextInstruction(pos);
469
470 while (iter != instructions_.end()) {
471
472 if ((*iter) == &next) {
473
474 ins->setParent(*this);
475
476 iter = instructions_.insert(iter, ins);
477
478 iter++;
479
480 return;
481 }
482
483 iter++;
484 }
485
486 // should not go here in any case
487 assert(false);
488
489 } else {
490 add(ins);
491 }
492
493 } else {
495 __FILE__, __LINE__, "CodeSnippet::insertInstructionBefore",
496 "Instruction already belongs to a procedure.");
497 }
498}
499
500/**
501 * Insert the given instruction before the given position.
502 *
503 * Instructions from and including pos are relocated to make room for
504 * the new instruction.
505 *
506 * @todo Refactor and share implementation with insertInstructionAfter()
507 *
508 * @param pos The position.
509 * @param ins The instruction to insert.
510 * @exception IllegalRegistration if pos does not belong to the code snippet
511 * or ins already belongs to a code snippet.
512 */
513void
515 if (!ins->isInProcedure()) {
516
517 InsList::iterator iter = instructions_.begin();
518 const Instruction& next = pos;
519
520 while (iter != instructions_.end()) {
521
522 if ((*iter) == &next) {
523
524 ins->setParent(*this);
525 iter = instructions_.insert(iter, ins);
526 iter++;
527 return;
528 }
529 iter++;
530 }
531 // should not go here in any case
532 assert(false);
533 } else {
535 __FILE__, __LINE__, "CodeSnippet::insertInstructionBefore",
536 "Instruction already belongs to a procedure.");
537 }
538}
539
540/**
541 * Remove instruction from the code snippet.
542 *
543 * The instruction becomes independent (it is not deleted). All
544 * instructions following the removed code snippet are relocated
545 * appropriately.
546 *
547 * The instructions should not have code labels attached to them.
548 *
549 * @note Possible references to the instruction elsewhere
550 * in the program are not automatically fixed! It's a responsibility of
551 * the caller to fix the Program back to a consistent state.
552 *
553 * @param ins Instruction to remove.
554 * @exception IllegalRegistration If instruction does not belong to the
555 * code snippet.
556 */
557void
559 if (!ins.isInProcedure() || !(&ins.parent() == this)) {
560 string msg = "Instruction doesn't belong to the procedure.";
561 throw IllegalRegistration(__FILE__, __LINE__, __func__, msg);
562 }
563
564 InsList::iterator iter = instructions_.begin();
565
566 for (; iter != instructions_.end(); iter++) {
567 if ((*iter) == &ins) {
568
569 iter = instructions_.erase(iter);
571
572 return;
573 }
574 }
575}
576
577/**
578 * Remove instruction from the code snippet at the given address and delete it.
579 *
580 * All instructions following the removed code snippet are relocated
581 * appropriately. All code labels attached to the removed instruction
582 * are deleted from the Program.
583 *
584 * @note Possible references to the instruction elsewhere
585 * in the program are not automatically fixed! It's a responsibility of
586 * the caller to fix the Program back to a consistent state.
587 *
588 * @param address Index of the instruction to remove.
589 * @exception IllegalRegistration If instruction does not belong to the
590 * code snippet.
591 */
592void
595 remove(instr);
596 delete &instr;
597}
598
599/**
600 * Make a complete copy of the code snippet.
601 *
602 * The copy is identical, except that it is not registered to the
603 * program of the original code snippet.
604 *
605 * @return A complete copy of the code snippet.
606 */
609
610 CodeSnippet* newProc = new CodeSnippet(startAddr_);
611 if (instructionCount() > 0) {
613 while (ins != &NullInstruction::instance()) {
614 newProc->add(ins->copy());
615 ins = &nextInstruction(*ins);
616 }
617 }
618 return newProc;
619}
620
621/**
622 * Inserts a whole code snippet into this code snippet
623 * just before specified instruction.
624 *
625 * This function does not remove the instruction references
626 * from the code snippet.
627 *
628 * @param ins The succeeding the place where to insert he instructions.
629 * @param cs CodeSnippet containing the instructions being inserted.
630 */
631void
633 const Instruction& pos, const CodeSnippet& cs) {
634 for( int i = 0; i < cs.instructionCount(); i++ ) {
636 }
637 }
638
639
640/**
641 * Inserts a whole code snippet into this code snippet
642 * just before specified instruction.
643 * This function moves the ownership of the moves and deletes the
644 * another code snippet.
645 *
646 * @param ins The succeeding the place where to insert he instructions.
647 * @param cs CodeSnippet containing the instructions being inserted.
648 */
649void
651 const Instruction& pos, CodeSnippet* cs) {
652 for( int i = 0, count = cs->instructionCount(); i < count; i++ ) {
653 Instruction& ins = cs->instructionAtIndex(0);
654 cs->remove(ins);
655 insertBefore(pos, &ins);
656 }
657 delete cs;
658 }
659
660/**
661 * Inserts a whole code snippet into this code snippet
662 * just after specified instruction.
663 *
664 * This function does not remove the instruction references
665 * from the code snippet.
666 *
667 * @param ins The succeeding the place where to insert he instructions.
668 * @param cs CodeSnippet containing the instructions being inserted.
669 */
670 void
672 const Instruction& pos, const CodeSnippet& cs) {
673
674 for (int i = cs.instructionCount()-1; i >= 0 ; i-- ) {
675 insertAfter(pos, cs.instructionAtIndex(i).copy());
676 }
677}
678
679/**
680 * Inserts a whole code snippet into this code snippet
681 * just after specified instruction.
682 *
683 * This function moves the ownership of the moves and deletes the
684 * another code snippet.
685 *
686 * @param ins The succeeding the place where to insert he instructions.
687 * @param cs CodeSnippet containing the instructions being inserted.
688 */
689 void
691 const Instruction& pos, CodeSnippet* cs) {
692
693 for (int i = cs->instructionCount()-1; i >= 0 ; i-- ) {
694 Instruction& ins = cs->instructionAtIndex(i);
695 cs->remove(ins);
696 insertAfter(pos, &ins);
697 }
698 delete cs;
699}
700
701
702/**
703 * Inserts a whole code snippet at end of this code snippet.
704 *
705 * This function does not remove the instruction references
706 * from the code snippet.
707 *
708 * @param cs CodeSnippet containing the instructions being inserted.
709 */
710 void
712 const CodeSnippet& cs) {
713 for( int i = 0; i < cs.instructionCount(); i++ ) {
714 add(cs.instructionAtIndex(i).copy());
715 }
716 }
717
718
719/**
720 * Inserts a whole code snippet at the end of this code snippet.
721 *
722 * This function moves the ownership of instructions from the old code snippet
723 * into the new one, and deletes the given code snippet.
724 *
725 * @TODO: This routine is O(n^2). Optimize!
726 *
727 * @param cs CodeSnippet containing the instructions being inserted.
728 */
729void
731 for (int i = 0, count = cs->instructionCount(); i < count ; i++) {
732 Instruction &ins = cs->instructionAtIndex(0);
733 cs->remove(ins);
734 add(&ins);
735 }
736 delete cs;
737}
738
739/**
740 * Inserts a whole code snippet at the beginning of this code snippet.
741 *
742 * This function does not remove the instruction references
743 * from the code snippet.
744 *
745 * @param cs CodeSnippet containing the instructions being inserted.
746 */
747void
749 for (int i = cs.instructionCount()-1; i >= 0 ; i--) {
751 }
752}
753
754/**
755 * Inserts a whole code snippet at the beginning of this code snippet.
756 *
757 * This function moves the ownership of instructions from the old code snippet
758 * into the new one, and deletes the given code snippet.
759 *
760 * @TODO: This routine is O(n^2). Optimize!
761 *
762 * @param cs CodeSnippet containing the instructions being inserted.
763 */
764void
766 for (int i = cs->instructionCount()-1; i >= 0 ; i--) {
767 Instruction &ins = cs->instructionAtIndex(i);
768 cs->remove(ins);
769 addFront(&ins);
770 }
771 delete cs;
772}
773
774/**
775 * Returns the start address of the code snippet.
776 *
777 * @return The start (lowest) address of the code snippet.
778 */
781 return startAddr_;
782}
783
784/**
785 * Returns the first address that is outside of the code snippet.
786 */
789
790 if (isInProgram() && parent().isFinalized()) {
791 return endAddr_;
792 } else {
793 InstructionAddress endLocation =
795 return Address(endLocation, startAddr_.space());
796 }
797}
798
799/**
800 * Returns true in case there is at least one procedure return in the
801 * code snippet.
802 */
803bool
805 const int iCount = instructionCount();
806 for (int i = 0; i < iCount; ++i) {
807 if (instructionAtIndex(i).hasReturn()) {
808 return true;
809 }
810 }
811 return false;
812}
813
814/**
815 * Returns the disassembly of the basic block as string.
816 *
817 * @return The disassembly of the basic block.
818 */
819std::string
821
822 std::string content = "";
823 const int iCount = instructionCount();
824 for (int i = 0; i < iCount; ++i) {
826 content += POMDisassembler::disassemble(instr);
827 content += "\n";
828 }
829 return content;
830}
831
832}
833
#define __func__
#define assert(condition)
Word UIntWord
Definition BaseType.hh:144
UInt32 InstructionAddress
Definition BaseType.hh:175
static std::string toString(const T &source)
static std::string disassemble(const TTAProgram::Move &move)
const TTAMachine::AddressSpace & space() const
InstructionAddress location() const
virtual Instruction & nextInstruction(const Instruction &ins) const
virtual void addFront(Instruction *ins)
virtual Instruction & previousInstruction(const Instruction &ins) const
virtual void setParent(Program &prog)
Address endAddr_
The highest address of the procedure.
virtual Address endAddress() const
Address startAddr_
The start (lowest) address of the procedure.
virtual Instruction & firstInstruction() const
virtual bool isInProgram() const
virtual void append(const CodeSnippet &cs)
virtual void insertAfter(const Instruction &pos, Instruction *ins)
Program * parent_
The parent program of the procedure.
virtual Address address(const Instruction &ins) const
virtual void add(Instruction *ins)
virtual void prepend(const CodeSnippet &cs)
virtual int instructionCount() const
virtual std::string disassembly() const
virtual void setStartAddress(Address start)
virtual Instruction & instructionAt(UIntWord address) const
virtual void remove(Instruction &ins)
InsList instructions_
The instructions in this procedure.
virtual CodeSnippet * copy() const
virtual void deleteInstructionAt(InstructionAddress address)
virtual Program & parent() const
virtual void removeLastInstruction()
virtual Address startAddress() const
virtual void insertBefore(const Instruction &pos, Instruction *ins)
virtual Instruction & lastInstruction() const
virtual void setEndAddress(Address end)
virtual Instruction & instructionAtIndex(int index) const
virtual Instruction & operator[](size_t index) const
virtual bool hasNextInstruction(const Instruction &ins) const
Instruction * copy() const
Address address() const
bool hasFinalAddress() const
CodeSnippet & parent() const
void setParent(CodeSnippet &proc)
static NullInstruction & instance()
static NullProcedure & instance()
static NullProgram & instance()