File: GCArrays.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 (238 lines) | stat: -rw-r--r-- 7,467 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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/* $Id$ 
 *
 * Generate intermediate code, array 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_ARRAYS_HPP_INCLUDED
#define __GC_ARRAYS_HPP_INCLUDED

#include <utility>
#include "intermediate/container/CodeContainer.hpp"
#include "intermediate/container/LabelFactory.hpp"
#include "intermediate/operands/Register.hpp"
#include "frontend/ast/TypeDeclaration.hpp"
#include "frontend/visitor/GCTypes.hpp"

namespace ast {

//! ArrayHandling can subscribe to arrays.
class ArrayHandling {
public:
	/** @param at array type declaration (should be an unconstraint array)
	 *  @param b base pointer of the array.
	 *  @param container container to add generated code to.
	 *  @param lbounds operands containing the left bounds for each
	 *         dimension of the unconstraint array.
	 *  @param rbounds operands containing the right bounds for
	 *         each dimension of the unconstraint array.
	 *  @param directs operands containing the direction (1/-1) for each
	 *         dimension of the unconstraint array.
	 */
	ArrayHandling(
		TypeDeclaration *at,
		intermediate::Operand *b,
		intermediate::CodeContainer &container,
		std::list<intermediate::Operand *> lbounds,
		std::list<intermediate::Operand *> rbounds,
		std::list<intermediate::Operand *> directs);


	//! d'tor
	~ArrayHandling();

	intermediate::Register *
	subscribe(std::list<intermediate::Operand *> relativeIndices);

private:
	/** calculate the list of factors */
	void factorize(void);

	/** factors with which each dimennsion must be multiplied. */
	std::list<intermediate::Operand *> dimensionFactors;

protected:
	/** array type */
	TypeDeclaration *arrayType;
private:
	/** pointer to start of array */
	intermediate::Operand *base;
protected:
	/** container, to which code will be added */
	intermediate::CodeContainer &cc;
	/** list of left bounds for each dimension */
	std::list<intermediate::Operand *> leftBounds;
	/** list of right bounds for each dimension */
	std::list<intermediate::Operand *> rightBounds;
	/** list of directions (1=to, -1=downto) for each dimenstion */
	std::list<intermediate::Operand *> directions;
private:
	/** intermediate code type of array */
	intermediate::Type *itype;
protected:
	/** type of final elements. (doesn't necessary match resulting type
	 *  of a subscription, e.g. in cases of an array of an array, where 
	 *  only the first array is subscribed. This always refers to a type
	 *  which is not an array. */
	TypeDeclaration *elementType;
	/** list of indices */
	std::list<DiscreteRange*> indices;

public:
	/** transform the index to a zero-based index (useful for ConstArray)
	 *  based on the IndexConstraint of arrayType.
	 *  @param arrayType type of the constraint array.
	 *  @param idx index relative to constraint type.
	 *  @return zero-based index, suitable for ConstArray.
	 */
	static universal_integer 
	transform_idx(
		const TypeDeclaration *arrayType, 
		universal_integer idx
	);
};


//! generic array handling to iterate over all elements of an array.
/** Generic array handling which can iterate over all elements of an array,
 *  in case the bounds are statically known.
 *  Abstract class, implementors need to implement iterateBody.
 */
class StaticArrayIterate : public ArrayHandling {
public:
	/** c'tor
	 *  @param at Array type declaration (must not be an unonstraint array
	 *  @param b register with the base pointer of the array
	 *  @param container container to add generated code to.
	 */
	StaticArrayIterate(
		TypeDeclaration *at,
		intermediate::Operand *b,
		intermediate::CodeContainer &container
		) : 	ArrayHandling(
				at, 
				b, 
				container, 
				std::list<intermediate::Operand *>(),
				std::list<intermediate::Operand *>(),
				std::list<intermediate::Operand *>()) {}
	
	/** dummy virtual d'tor */
	virtual ~StaticArrayIterate() {}
	
	/** iterate over all elements of the array, calling iterateBody for 
	 *  each
	 */
	void iterate(void);

protected:
	/** called for each element during for an iteration. 
	 *  @param element pointer to the element in question.
	 *  @param indices list of indices denoting the element.
	 */
	virtual void 
	iterateBody(
		intermediate::Register *element, 
		std::list<universal_integer> indices
		) = 0;

private:
	/** check if all counters have reached ubounds.
	 *  @param counters loop counters.
	 *  @param rbounds right bounds of the array.
	 *  @param directions directions of the array (-1, 1).
	 *  @return true, if all counters are the same as the respective
	 *          right bounds, otherwise false.
	 */
	static bool 
	checkLoop(
		const std::list<universal_integer> &counters,
		const std::list<universal_integer> &rbounds,
		const std::list<universal_integer> &directions);

	/** increase the counters to advance to the next element.
	 *  @param counters loop counters to be increased.
	 *  @param lbounds corresponding left bounds.
	 *  @param rbounds corresponding right bounds.
	 *  @param directions directions (-1, 1) of the array, which are
	 *         used as a step factor here.
	 */
	static void
	incCounters(
		std::list<universal_integer> &counters,
		const std::list<universal_integer> &lbounds,
		const std::list<universal_integer> &rbounds,
		const std::list<universal_integer> &directions);
};

//! iterate over arrays
/** This class can generate loop code to iterate over an array.
 *  It works for both arrays, where the bounds are known statically, as 
 *  well for ones where the bounds are known dynamically.
 */
class ArrayIterate : public ArrayHandling {
public:
	/** @param at array type declaration (should be an unconstraint array)
	 *  @param b base pointer of the array.
	 *  @param container container to add generated code to.
	 *  @param lbounds operands containing the left bounds for each
	 *         dimension of the unconstraint array.
	 *  @param rbounds operands containing the right bounds for
	 *         each dimension of the unconstraint array.
	 *  @param directs directions (-1, 1) of the dimensions.
	 */
	ArrayIterate(
		TypeDeclaration *at,
		intermediate::Operand *b,
		intermediate::CodeContainer &container,
		std::list<intermediate::Operand *> lbounds,
		std::list<intermediate::Operand *> rbounds,
		std::list<intermediate::Operand *> directs
		) : 	ArrayHandling(at, 
					b, 
					container, 
					lbounds, 
					rbounds,
					directs),
			loop(intermediate::LabelFactory::getLabel("loop")) {}

	//! dummy d'tor
	virtual ~ArrayIterate() {}

	/** iterate over all elements of the array */
	void iterate(void);

protected:
	/** called for one element of the iteration in the place of the body
	 *  of the iteration.
	 *  @param element pointer to the element in question.
	 *  @param indices list of indices denoting the element (rel. offsets)
	 */
	virtual void 
	iterateBody(
		intermediate::Register *element, 
		std::list<intermediate::Register *> indices
		) = 0;

private:
	//! initialize the counters with the left bounds.
	void initCounters(void);

	//! increase the counters
	void incCounters(void);

	/** list of counters for dimensions. */
	std::list<intermediate::Register *> counters;

	/** loop label. */
	intermediate::Label *loop;

};

}; /* namespace ast */

#endif /* __GC_ARRAYS_HPP_INCLUDED */