Commit d8e80b8b authored by Matthias Braun's avatar Matthias Braun
Browse files

simplify array types: They're always 1-dimensional with lower-bound 0

parent d44e2e93
...@@ -1519,82 +1519,28 @@ FIRM_API const tp_op *get_tpop_method(void); ...@@ -1519,82 +1519,28 @@ FIRM_API const tp_op *get_tpop_method(void);
/** /**
* @defgroup array_type Array * @defgroup array_type Array
* *
* The array type represents rectangular multi dimensional arrays. * The array type represents linear arrangement of objects of the same type.
* The constants representing the bounds must be allocated to
* get_const_code_irg().
* *
* - n_dimensions: Number of array dimensions. * - *size: number of elements in the array.
* - *lower_bound: Lower bounds of dimensions. Usually all 0.
* - *upper_bound: Upper bounds or dimensions.
* - *element_type: The type of the array elements. * - *element_type: The type of the array elements.
* - *element_ent: An entity for the array elements to be used for
* element selection with Sel.
* @{ * @{
*/ */
/** Create a new type array. /** Create a new type array. */
* FIRM_API ir_type *new_type_array(ir_type *element_type);
* Sets n_dimension to dimension and all dimension entries to NULL.
* Initializes order to the order of the dimensions.
* The entity for array elements is built automatically.
* Sets dimension sizes after call to constructor with set_* routines.
*/
FIRM_API ir_type *new_type_array(size_t n_dims, ir_type *element_type);
/** Returns the number of array dimensions of this type. */ /** Sets the size (number of elements) of the array, i.e. [0,size[ */
FIRM_API size_t get_array_n_dimensions(const ir_type *array); FIRM_API void set_array_size(ir_type *array, ir_node *size);
/**
* Allocates Const nodes of mode_Is for one array dimension.
* Upper bound in Firm is the element next to the last, i.e. [lower,upper[
*/
FIRM_API void set_array_bounds_int(ir_type *array, size_t dimension,
int lower_bound, int upper_bound);
/**
* Sets the bounds for one array dimension.
* Upper bound in Firm is the element next to the last, i.e. [lower,upper[
*/
FIRM_API void set_array_bounds(ir_type *array, size_t dimension,
ir_node *lower_bound, ir_node *upper_bound);
/** Sets the lower bound for one array dimension, i.e. [lower,upper[ */
FIRM_API void set_array_lower_bound(ir_type *array, size_t dimension,
ir_node *lower_bound);
/** Allocates Const nodes of mode_Is for the lower bound of an array /** Sets array size of @p array to @p size elements. */
dimension, i.e. [lower,upper[ */ FIRM_API void set_array_size_int(ir_type *array, unsigned size);
FIRM_API void set_array_lower_bound_int(ir_type *array, size_t dimension,
int lower_bound);
/** Sets the upper bound for one array dimension, i.e. [lower,upper[ */ /** returns true if lower size != Unknown */
FIRM_API void set_array_upper_bound(ir_type *array, size_t dimension, FIRM_API int has_array_size(const ir_type *array);
ir_node *upper_bound); /** Returns the size (number of elements) of an array. */
FIRM_API ir_node *get_array_size(const ir_type *array);
/** Allocates Const nodes of mode_Is for the upper bound of an array
dimension, i.e. [lower,upper[. */
FIRM_API void set_array_upper_bound_int(ir_type *array, size_t dimension,
int upper_bound);
/** Returns true if lower bound != Unknown. */
FIRM_API int has_array_lower_bound(const ir_type *array, size_t dimension);
/** Returns the lower bound of an array. */
FIRM_API ir_node *get_array_lower_bound(const ir_type *array, size_t dimension);
/** Works only if bound is Const node with tarval that can be converted to long. */
FIRM_API long get_array_lower_bound_int(const ir_type *array, size_t dimension);
/** returns true if lower bound != Unknown */
FIRM_API int has_array_upper_bound(const ir_type *array, size_t dimension);
/** Returns the upper bound of an array. */
FIRM_API ir_node *get_array_upper_bound(const ir_type *array, size_t dimension);
/** Works only if bound is Const node with tarval that can be converted to long. */ /** Works only if bound is Const node with tarval that can be converted to long. */
FIRM_API long get_array_upper_bound_int(const ir_type *array, size_t dimension); FIRM_API unsigned get_array_size_int(const ir_type *array);
/** Sets an array dimension to a specific order. */
FIRM_API void set_array_order(ir_type *array, size_t dimension, size_t order);
/** Returns the order of an array dimension. */
FIRM_API size_t get_array_order(const ir_type *array, size_t dimension);
/** Find the array dimension that is placed at order order. */
FIRM_API size_t find_array_dimension(const ir_type *array, size_t order);
/** Sets the array element type. */ /** Sets the array element type. */
FIRM_API void set_array_element_type(ir_type *array, ir_type *tp); FIRM_API void set_array_element_type(ir_type *array, ir_type *tp);
......
...@@ -607,9 +607,6 @@ static void emit_array_type_abbrev(void) ...@@ -607,9 +607,6 @@ static void emit_array_type_abbrev(void)
static void emit_array_type(const ir_type *type) static void emit_array_type(const ir_type *type)
{ {
if (get_array_n_dimensions(type) != 1)
panic("multidimensional arrays no supported yet");
ir_type *element_type = get_array_element_type(type); ir_type *element_type = get_array_element_type(type);
emit_type(element_type); emit_type(element_type);
...@@ -617,8 +614,8 @@ static void emit_array_type(const ir_type *type) ...@@ -617,8 +614,8 @@ static void emit_array_type(const ir_type *type)
emit_uleb128(abbrev_array_type); emit_uleb128(abbrev_array_type);
emit_type_address(element_type); emit_type_address(element_type);
if (has_array_upper_bound(type, 0)) { if (has_array_size(type)) {
int bound = get_array_upper_bound_int(type, 0); unsigned bound = get_array_size_int(type);
emit_uleb128(abbrev_subrange_type); emit_uleb128(abbrev_subrange_type);
emit_uleb128(bound); emit_uleb128(bound);
} }
......
...@@ -349,9 +349,9 @@ static ir_type *make_array_type(ir_type *tp) ...@@ -349,9 +349,9 @@ static ir_type *make_array_type(ir_type *tp)
{ {
unsigned alignment = get_type_alignment_bytes(tp); unsigned alignment = get_type_alignment_bytes(tp);
unsigned size = get_type_size_bytes(tp); unsigned size = get_type_size_bytes(tp);
ir_type *res = new_type_array(1, tp); ir_type *res = new_type_array(tp);
set_type_alignment_bytes(res, alignment); set_type_alignment_bytes(res, alignment);
set_array_bounds_int(res, 0, 0, 2); set_array_size_int(res, 2);
if (alignment > size) if (alignment > size)
size = alignment; size = alignment;
set_type_size_bytes(res, 2 * size); set_type_size_bytes(res, 2 * size);
......
...@@ -1622,17 +1622,9 @@ static void dump_type_info(ir_type *const tp, ir_entity *const ent, void *const ...@@ -1622,17 +1622,9 @@ static void dump_type_info(ir_type *const tp, ir_entity *const ent, void *const
case tpo_array: case tpo_array:
print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR); print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR); print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
for (i = get_array_n_dimensions(tp); i > 0;) { ir_node *size = get_array_size(tp);
ir_node *upper, *lower; print_node_type_edge(F, size, tp, "label: \"size\"");
dump_const_expression(F, size);
--i;
upper = get_array_upper_bound(tp, i);
lower = get_array_lower_bound(tp, i);
print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
dump_const_expression(F, upper);
dump_const_expression(F, lower);
}
break; break;
case tpo_pointer: case tpo_pointer:
print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR); print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
......
...@@ -692,32 +692,15 @@ void dump_type_to_file(FILE *const F, const ir_type *const tp) ...@@ -692,32 +692,15 @@ void dump_type_to_file(FILE *const F, const ir_type *const tp)
fprintf(F, "\n array "); fprintf(F, "\n array ");
const ir_type *elem_tp = get_array_element_type(tp); const ir_type *elem_tp = get_array_element_type(tp);
size_t n_dim = get_array_n_dimensions(tp);
for (size_t i = 0; i < n_dim; ++i) {
fprintf(F, "["); fprintf(F, "[");
const ir_node *size = get_array_size(tp);
const ir_node *lower = get_array_lower_bound(tp, i); if (is_Const(size)) {
if (is_Const(lower)) { fprintf(F, "%ld", get_tarval_long(get_Const_tarval(size)));
fprintf(F, "%ld .. ", get_tarval_long(get_Const_tarval(lower)));
} else {
dump_node_opcode(F, lower);
fprintf(F, " %ld .. ", get_irn_node_nr(lower));
}
const ir_node *upper = get_array_upper_bound(tp, i);
if (is_Const(upper)) {
fprintf(F, "%ld]", get_tarval_long(get_Const_tarval(lower)));
} else { } else {
dump_node_opcode(F, upper); dump_node_opcode(F, size);
fprintf(F, " %ld]", get_irn_node_nr(upper)); fprintf(F, " %ld", get_irn_node_nr(size));
} }
} ir_fprintf(F, "] of <%+F>", elem_tp);
ir_fprintf(F, " of <%+F>", elem_tp);
fprintf(F, "\n order: ");
for (size_t i = 0; i < n_dim; ++i)
fprintf(F, "<%zu>", get_array_order(tp, i));
fprintf(F, "\n"); fprintf(F, "\n");
if (verbosity & dump_verbosity_fields) { if (verbosity & dump_verbosity_fields) {
......
...@@ -401,13 +401,9 @@ void walk_const_code(irg_walk_func *pre, irg_walk_func *post, void *env) ...@@ -401,13 +401,9 @@ void walk_const_code(irg_walk_func *pre, irg_walk_func *post, void *env)
for (i = 0; i < n_types; i++) { for (i = 0; i < n_types; i++) {
ir_type *tp = get_irp_type(i); ir_type *tp = get_irp_type(i);
if (is_Array_type(tp)) { if (is_Array_type(tp)) {
size_t j, n_dim = get_array_n_dimensions(tp); ir_node *size = get_array_size(tp);
for (j = 0; j < n_dim; j++) { if (size != NULL)
ir_node *n = get_array_lower_bound(tp, j); irg_walk(size, pre, post, env);
if (n) irg_walk(n, pre, post, env);
n = get_array_upper_bound(tp, j);
if (n) irg_walk(n, pre, post, env);
}
} }
} }
......
...@@ -601,25 +601,14 @@ static void write_type_array(write_env_t *env, ir_type *tp) ...@@ -601,25 +601,14 @@ static void write_type_array(write_env_t *env, ir_type *tp)
write_type(env, element_type); write_type(env, element_type);
write_type_common(env, tp); write_type_common(env, tp);
size_t n_dimensions = get_array_n_dimensions(tp);
write_size_t(env, n_dimensions);
write_type_ref(env, element_type); write_type_ref(env, element_type);
for (size_t i = 0; i < n_dimensions; i++) { ir_node *size = get_array_size(tp);
ir_node *lower = get_array_lower_bound(tp, i); if (is_Const(size))
ir_node *upper = get_array_upper_bound(tp, i); write_long(env, get_tarval_long(get_Const_tarval(size)));
else if (is_Unknown(size))
if (is_Const(lower))
write_long(env, get_tarval_long(get_Const_tarval(lower)));
else
panic("Lower array bound is not constant");
if (is_Const(upper))
write_long(env, get_tarval_long(get_Const_tarval(upper)));
else if (is_Unknown(upper))
write_symbol(env, "unknown"); write_symbol(env, "unknown");
else else
panic("Upper array bound is not constant"); panic("Upper array bound is not constant");
}
/* note that we just write a reference to the element entity /* note that we just write a reference to the element entity
* but never the entity itself */ * but never the entity itself */
ir_entity *element_entity = get_array_element_entity(tp); ir_entity *element_entity = get_array_element_entity(tp);
...@@ -1648,26 +1637,15 @@ static void read_type(read_env_t *env) ...@@ -1648,26 +1637,15 @@ static void read_type(read_env_t *env)
switch (tpop) { switch (tpop) {
case tpo_array: { case tpo_array: {
size_t n_dimensions = read_size_t(env);
ir_type *elemtype = read_type_ref(env); ir_type *elemtype = read_type_ref(env);
type = new_type_array(elemtype);
type = new_type_array(n_dimensions, elemtype);
for (size_t i = 0; i < n_dimensions; i++) {
char *str = read_word(env); char *str = read_word(env);
if (strcmp(str, "unknown") != 0) { if (strcmp(str, "unknown") != 0) {
long lowerbound = atol(str); long size = atol(str);
set_array_lower_bound_int(type, i, lowerbound); set_array_size_int(type, size);
} }
obstack_free(&env->obst, str); obstack_free(&env->obst, str);
str = read_word(env);
if (strcmp(str, "unknown") != 0) {
long upperbound = atol(str);
set_array_upper_bound_int(type, i, upperbound);
}
obstack_free(&env->obst, str);
}
long element_entity_nr = read_long(env); long element_entity_nr = read_long(env);
ir_entity *element_entity = get_array_element_entity(type); ir_entity *element_entity = get_array_element_entity(type);
set_id(env, element_entity_nr, element_entity); set_id(env, element_entity_nr, element_entity);
......
...@@ -396,8 +396,8 @@ static ir_entity *new_array_entity(ident *name, int size) ...@@ -396,8 +396,8 @@ static ir_entity *new_array_entity(ident *name, int size)
uint_type = new_type_primitive(mode_Iu); uint_type = new_type_primitive(mode_Iu);
set_type_alignment_bytes(uint_type, get_type_size_bytes(uint_type)); set_type_alignment_bytes(uint_type, get_type_size_bytes(uint_type));
array_type = new_type_array(1, uint_type); array_type = new_type_array(uint_type);
set_array_bounds_int(array_type, 0, 0, size); set_array_size_int(array_type, size);
set_type_size_bytes(array_type, size * get_mode_size_bytes(mode_Iu)); set_type_size_bytes(array_type, size * get_mode_size_bytes(mode_Iu));
set_type_alignment_bytes(array_type, get_mode_size_bytes(mode_Iu)); set_type_alignment_bytes(array_type, get_mode_size_bytes(mode_Iu));
set_type_state(array_type, layout_fixed); set_type_state(array_type, layout_fixed);
...@@ -418,14 +418,14 @@ static ir_entity *new_static_string_entity(ident *name, const char *string) ...@@ -418,14 +418,14 @@ static ir_entity *new_static_string_entity(ident *name, const char *string)
ir_entity *result; ir_entity *result;
ir_type *char_type = new_type_primitive(mode_Bs); ir_type *char_type = new_type_primitive(mode_Bs);
ir_type *string_type = new_type_array(1, char_type); ir_type *string_type = new_type_array(char_type);
ir_initializer_t *contents; ir_initializer_t *contents;
size_t i, length = strlen(string)+1; size_t i, length = strlen(string)+1;
/* Create the type for a fixed-length string */ /* Create the type for a fixed-length string */
set_array_bounds_int(string_type, 0, 0, length); set_array_size_int(string_type, length);
set_type_size_bytes(string_type, length); set_type_size_bytes(string_type, length);
set_type_alignment_bytes(string_type, 1); set_type_alignment_bytes(string_type, 1);
set_type_state(string_type, layout_fixed); set_type_state(string_type, layout_fixed);
......
...@@ -41,7 +41,6 @@ static void lower_sel(ir_node *sel) ...@@ -41,7 +41,6 @@ static void lower_sel(ir_node *sel)
/* an Array access */ /* an Array access */
ir_type *basetyp = get_entity_type(ent); ir_type *basetyp = get_entity_type(ent);
ir_mode *basemode; ir_mode *basemode;
ir_node *index;
if (is_Primitive_type(basetyp)) if (is_Primitive_type(basetyp))
basemode = get_type_mode(basetyp); basemode = get_type_mode(basetyp);
else else
...@@ -49,92 +48,22 @@ static void lower_sel(ir_node *sel) ...@@ -49,92 +48,22 @@ static void lower_sel(ir_node *sel)
assert(basemode && "no mode for lowering Sel"); assert(basemode && "no mode for lowering Sel");
assert((get_mode_size_bits(basemode) % 8 == 0) && "can not deal with unorthodox modes"); assert((get_mode_size_bits(basemode) % 8 == 0) && "can not deal with unorthodox modes");
index = get_Sel_index(sel, 0); ir_node *index = get_Sel_index(sel, 0);
if (is_Array_type(owner)) { if (is_Array_type(owner)) {
ir_type *arr_ty = owner; ir_mode *mode_int = get_reference_mode_unsigned_eq(mode);
size_t dims = get_array_n_dimensions(arr_ty); assert(get_Sel_n_indexs(sel) == 1
size_t *map = ALLOCAN(size_t, dims);
ir_mode *mode_Int = get_reference_mode_signed_eq(mode);
ir_tarval *tv;
ir_node *last_size;
size_t i;
assert(dims == (size_t)get_Sel_n_indexs(sel)
&& "array dimension must match number of indices of Sel node"); && "array dimension must match number of indices of Sel node");
for (i = 0; i < dims; i++) {
size_t order = get_array_order(arr_ty, i);
assert(order < dims &&
"order of a dimension must be smaller than the arrays dim");
map[order] = i;
}
newn = get_Sel_ptr(sel);
/* Size of the array element */ /* Size of the array element */
tv = new_tarval_from_long(get_type_size_bytes(basetyp), mode_Int); unsigned size = get_type_size_bytes(basetyp);
last_size = new_rd_Const(dbg, irg, tv); ir_tarval *tv = new_tarval_from_long(size, mode_int);
ir_node *el_size = new_rd_Const(dbg, irg, tv);
/* ir_node *ind = new_rd_Conv(dbg, bl, index, mode_int);
* We compute the offset part of dimension d_i recursively ir_node *mul = new_rd_Mul(dbg, bl, ind, el_size, mode_int);
* with the the offset part of dimension d_{i-1}
* ir_node *ptr = get_Sel_ptr(sel);
* off_0 = sizeof(array_element_type); newn = new_rd_Add(dbg, bl, ptr, mul, mode);
* off_i = (u_i - l_i) * off_{i-1} ; i >= 1
*
* whereas u_i is the upper bound of the current dimension
* and l_i the lower bound of the current dimension.
*/
for (i = dims; i > 0;) {
size_t dim = map[--i];
ir_node *lb, *ub, *elms, *n, *ind;
elms = NULL;
lb = get_array_lower_bound(arr_ty, dim);
ub = get_array_upper_bound(arr_ty, dim);
if (! is_Unknown(lb))
lb = new_rd_Conv(dbg, bl, duplicate_subgraph(get_irn_dbg_info(sel), lb, bl), mode_Int);
else
lb = NULL;
if (! is_Unknown(ub))
ub = new_rd_Conv(dbg, bl, duplicate_subgraph(get_irn_dbg_info(sel), ub, bl), mode_Int);
else
ub = NULL;
/*
* If the array has more than one dimension, lower and upper
* bounds have to be set in the non-last dimension.
*/
if (i > 0) {
assert(lb != NULL && "lower bound has to be set in multi-dim array");
assert(ub != NULL && "upper bound has to be set in multi-dim array");
/* Elements in one Dimension */
elms = new_rd_Sub(dbg, bl, ub, lb, mode_Int);
}
ind = new_rd_Conv(dbg, bl, get_Sel_index(sel, dim), mode_Int);
/*
* Normalize index, id lower bound is set, also assume
* lower bound == 0
*/
if (lb != NULL)
ind = new_rd_Sub(dbg, bl, ind, lb, mode_Int);
n = new_rd_Mul(dbg, bl, ind, last_size, mode_Int);
/*
* see comment above.
*/
if (i > 0)
last_size = new_rd_Mul(dbg, bl, last_size, elms, mode_Int);
newn = new_rd_Add(dbg, bl, newn, n, mode);
}
} else { } else {
/* no array type */ /* no array type */
ir_mode *idx_mode = get_irn_mode(index); ir_mode *idx_mode = get_irn_mode(index);
......
...@@ -241,31 +241,23 @@ static ir_entity *find_constant_entity(ir_node *ptr) ...@@ -241,31 +241,23 @@ static ir_entity *find_constant_entity(ir_node *ptr)
if (is_Array_type(tp)) { if (is_Array_type(tp)) {
/* check bounds */ /* check bounds */
for (int i = 0, n = get_Sel_n_indexs(ptr); i < n; ++i) { ir_node *index = get_Sel_index(ptr, 0);
ir_node *index = get_Sel_index(ptr, i);
ir_tarval *tv = computed_value(index); ir_tarval *tv = computed_value(index);
/* check if the index is constant */ /* check if the index is constant */
if (!tarval_is_constant(tv)) if (!tarval_is_constant(tv))
return NULL; return NULL;
ir_node *lower = get_array_lower_bound(tp, i); ir_node *size = get_array_size(tp);
ir_tarval *tlower = computed_value(lower); ir_tarval *tsize = computed_value(size);
ir_node *upper = get_array_upper_bound(tp, i);
ir_tarval *tupper = computed_value(upper);
if (!tarval_is_constant(tlower) if (!tarval_is_constant(tsize))
|| !tarval_is_constant(tupper))
return NULL; return NULL;
if (tarval_cmp(tv, tlower) == ir_relation_less) if (tarval_cmp(tv, tsize) != ir_relation_less)
return NULL;
if (tarval_cmp(tupper, tv) == ir_relation_less)
return NULL; return NULL;
/* ok, bounds check finished */ /* ok, bounds check finished */
} }
}
if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT) if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT)
return ent; return ent;
......
...@@ -530,35 +530,23 @@ static ir_entity *find_constant_entity(ir_node *ptr) ...@@ -530,35 +530,23 @@ static ir_entity *find_constant_entity(ir_node *ptr)
if (is_Array_type(tp)) { if (is_Array_type(tp)) {
/* check bounds */ /* check bounds */
int i, n; ir_node *index = get_Sel_index(ptr, 0);
for (i = 0, n = get_Sel_n_indexs(ptr); i < n; ++i) {
ir_node *bound;
ir_tarval *tlower, *tupper;
ir_node *index = get_Sel_index(ptr, i);
ir_tarval *tv = computed_value(index); ir_tarval *tv = computed_value(index);
/* check if the index is constant */ /* check if the index is constant */
if (!tarval_is_constant(tv)) if (!tarval_is_constant(tv))
return NULL; return NULL;
bound = get_array_lower_bound(tp, i); ir_node *size = get_array_size(tp);
tlower = computed_value(bound); ir_tarval *tsize = computed_value(size);
bound = get_array_upper_bound(tp, i);
tupper = computed_value(bound);
if (!tarval_is_constant(tlower) if (!tarval_is_constant(tsize))
|| !tarval_is_constant(tupper))
return NULL; return NULL;
if (tarval_cmp(tv, tlower) == ir_relation_less) if (tarval_cmp(tv, tsize) != ir_relation_less)
return NULL;
if (tarval_cmp(tupper, tv) == ir_relation_less)
return NULL; return NULL;
/* ok, bounds check finished */ /* ok, bounds check finished */
} }
}
if (get_entity_linkage(ent) == IR_LINKAGE_CONSTANT) if (get_entity_linkage(ent) == IR_LINKAGE_CONSTANT)
return ent; return ent;
......
...@@ -92,7 +92,7 @@ static const tp_op_ops ...@@ -92,7 +92,7 @@ static const tp_op_ops
}, },
/** tpop operations for array types */ /** tpop operations for array types */
array_ops = { array_ops = {
free_array_attrs, NULL,