File: GCLoops.hpp

package info (click to toggle)
fauhdlc 20180504-3.1
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 3,064 kB
  • sloc: cpp: 23,188; ansic: 6,077; yacc: 3,764; lex: 763; makefile: 605; python: 412; xml: 403; sh: 61
file content (197 lines) | stat: -rw-r--r-- 5,354 bytes parent folder | download | duplicates (3)
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 */