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 */
|