1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
/* $Id$
*
* Generate intermediate code, loop specific parts.
*
* Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
* This program is free software. You can redistribute it and/or modify it
* under the terms of the GNU General Public License, either version 2 of
* the License, or (at your option) any later version. See COPYING.
*/
#ifndef __GC_LOOPS_HPP_INCLUDED
#define __GC_LOOPS_HPP_INCLUDED
#include <map>
#include "intermediate/container/CodeContainer.hpp"
#include "intermediate/operands/Operand.hpp"
#include "frontend/ast/LoopStat.hpp"
namespace ast {
//! generic class to iterate in a while loop manner
/** This class can be used to generate code in a while-loop like manner.
* high level semantics:
*
* initializeCounter();
* while (checkCondition()) {
* loopBody();
* incCounter();
* }
*
* if/goto pseudo-code:
*
* initializeCounter();
* loopCheck:
* if ! checkCondition() goto loopDone
* loopBody();
* loopInc:
* loopInc();
* goto loopCheck;
* loopDone:
*/
class WhileIterate {
public:
//! c'tor
/** @param container current code container to add code to.
*/
WhileIterate(intermediate::CodeContainer &container);
//! dummy d'tor
virtual ~WhileIterate();
//! generate code for the iteration
/** not meant to be overloaded. */
void addIteration(void);
protected:
//! generate code to initialize the counter
virtual void initializeCounter(void) = 0;
//! generate code to check the condition
/** in case the condition is false, jump to loopDone to exit the
* loop.
*/
virtual void checkCondition(void) = 0;
//! generate code for the loop body
/** the following labels can be used:
* loopInc for a continue semantic
* loopDone for a break semantic
*/
virtual void loopBody(void) = 0;
//! generate code to increase the counter
virtual void incCounter(void) = 0;
//! CodeContainer to add generated code to.
intermediate::CodeContainer &cc;
public:
/** Label after which the counters are increased
* jump here from the body, to implement a continue semantic.
*/
intermediate::Label *loopInc;
/** Label when the loop has finished.
* jump here from the body, to implement a break semantic.
*/
intermediate::Label *loopDone;
private:
//! generate code for the iteration.
/** Here, the iteration scheme is defined. Basically, this is just
* a call from addIteration, only enforcing that the iteration scheme
* is not to be modified in subclasses.
*/
void genIterateCode(void);
//! Label of the loop condition
intermediate::Label *loopCheck;
};
//! iterate over a for statement.
class ForLoopIterate : public WhileIterate {
public:
//! c'tor
/** @param condition code container to append generated code to.
* @param counter Operand referring to the loop induction variable.
* @param initializer Operand containing the initial counter value.
* @param rightBound right bound of the loop (not necessary upper
* bound).
* @param isAscending true, if the loop is a "TO" loop, false for a
* "DOWNTO" loop.
*/
ForLoopIterate(
intermediate::CodeContainer &container,
intermediate::Operand &counter,
intermediate::Operand &initializer,
intermediate::Operand &rightBound,
bool isAscending
) : WhileIterate(container),
cnt(counter),
init(initializer),
rbound(rightBound),
isAsc(isAscending) {}
protected:
//! generate code to initialize the counter
virtual void initializeCounter(void);
//! generate code to check the condition
/** in case the condition is false, jump to loopDone to exit the
* loop.
*/
virtual void checkCondition(void);
//! generate code to increase the counter
virtual void incCounter(void);
//! counter operand.
intermediate::Operand &cnt;
//! initial value of the counter.
intermediate::Operand &init;
//! right bound of the loop (inclusive)
intermediate::Operand &rbound;
//! is the loop ascending?
bool isAsc;
};
//! registry containing a mapping between LoopStat AST nodes and WhileIterate
/** This registry can be used to lookup intermediate code loop iterations from
* next and exit statements.
*/
class LoopRegistry {
public:
/** remember a loop statement with the corresponding iterate class.
* @param node AST node
* @param iterate corresponding iterate instance.
*/
void rememberLoop(LoopStat *node, WhileIterate *iterate) {
this->knownLoops[node] = iterate;
}
/** forget a mapping between loop statement and corresponding iterate
* class.
* @param node loop statement node to forget.
*/
void forgetLoop(LoopStat *node) {
std::map<LoopStat *, WhileIterate*>::iterator i =
this->knownLoops.find(node);
assert(i != this->knownLoops.end());
this->knownLoops.erase(i);
}
/** lookup the corresponding iterate instance to a loop statement.
* @param node AST loop node for which the corresponding entry should
* get looked up.
* @return corresponding entry.
*/
WhileIterate *lookup(LoopStat *node) const {
std::map<LoopStat *, WhileIterate*>::const_iterator i =
this->knownLoops.find(node);
assert(i != this->knownLoops.end());
return i->second;
}
private:
//! mapping between AST loop statements and iterate instances.
std::map<LoopStat *, WhileIterate *> knownLoops;
};
}; /* namespace ast */
#endif /* __GC_LOOPS_HPP_INCLUDED */
|