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);
/**
* @defgroup array_type Array
*
* The array type represents rectangular multi dimensional arrays.
* The constants representing the bounds must be allocated to
* get_const_code_irg().
* The array type represents linear arrangement of objects of the same type.
*
* - n_dimensions: Number of array dimensions.
* - *lower_bound: Lower bounds of dimensions. Usually all 0.
* - *upper_bound: Upper bounds or dimensions.
* - *size: number of elements in the array.
* - *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.
*
* 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);
/** Create a new type array. */
FIRM_API ir_type *new_type_array(ir_type *element_type);
/** Returns the number of array dimensions of this type. */
FIRM_API size_t get_array_n_dimensions(const ir_type *array);
/**
* 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);
/** Sets the size (number of elements) of the array, i.e. [0,size[ */
FIRM_API void set_array_size(ir_type *array, ir_node *size);
/** Allocates Const nodes of mode_Is for the lower bound of an array
dimension, i.e. [lower,upper[ */
FIRM_API void set_array_lower_bound_int(ir_type *array, size_t dimension,
int lower_bound);
/** Sets array size of @p array to @p size elements. */
FIRM_API void set_array_size_int(ir_type *array, unsigned size);
/** Sets the upper bound for one array dimension, i.e. [lower,upper[ */
FIRM_API void set_array_upper_bound(ir_type *array, size_t dimension,
ir_node *upper_bound);
/** 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);
/** returns true if lower size != Unknown */
FIRM_API int has_array_size(const ir_type *array);
/** Returns the size (number of elements) of an array. */
FIRM_API ir_node *get_array_size(const ir_type *array);
/** 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);
/** 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);
FIRM_API unsigned get_array_size_int(const ir_type *array);
/** Sets the array element type. */
FIRM_API void set_array_element_type(ir_type *array, ir_type *tp);
......
......@@ -607,9 +607,6 @@ static void emit_array_type_abbrev(void)
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);
emit_type(element_type);
......@@ -617,8 +614,8 @@ static void emit_array_type(const ir_type *type)
emit_uleb128(abbrev_array_type);
emit_type_address(element_type);
if (has_array_upper_bound(type, 0)) {
int bound = get_array_upper_bound_int(type, 0);
if (has_array_size(type)) {
unsigned bound = get_array_size_int(type);
emit_uleb128(abbrev_subrange_type);
emit_uleb128(bound);
}
......
......@@ -349,9 +349,9 @@ static ir_type *make_array_type(ir_type *tp)
{
unsigned alignment = get_type_alignment_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_array_bounds_int(res, 0, 0, 2);
set_array_size_int(res, 2);
if (alignment > size)
size = alignment;
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
case tpo_array:
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);
for (i = get_array_n_dimensions(tp); i > 0;) {
ir_node *upper, *lower;
--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);
}
ir_node *size = get_array_size(tp);
print_node_type_edge(F, size, tp, "label: \"size\"");
dump_const_expression(F, size);
break;
case tpo_pointer:
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)
fprintf(F, "\n array ");
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, "[");
const ir_node *lower = get_array_lower_bound(tp, i);
if (is_Const(lower)) {
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 {
dump_node_opcode(F, upper);
fprintf(F, " %ld]", get_irn_node_nr(upper));
}
fprintf(F, "[");
const ir_node *size = get_array_size(tp);
if (is_Const(size)) {
fprintf(F, "%ld", get_tarval_long(get_Const_tarval(size)));
} else {
dump_node_opcode(F, size);
fprintf(F, " %ld", get_irn_node_nr(size));
}
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));
ir_fprintf(F, "] of <%+F>", elem_tp);
fprintf(F, "\n");
if (verbosity & dump_verbosity_fields) {
......
......@@ -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++) {
ir_type *tp = get_irp_type(i);
if (is_Array_type(tp)) {
size_t j, n_dim = get_array_n_dimensions(tp);
for (j = 0; j < n_dim; j++) {
ir_node *n = get_array_lower_bound(tp, j);
if (n) irg_walk(n, pre, post, env);
n = get_array_upper_bound(tp, j);
if (n) irg_walk(n, pre, post, env);
}
ir_node *size = get_array_size(tp);
if (size != NULL)
irg_walk(size, pre, post, env);
}
}
......
......@@ -601,25 +601,14 @@ static void write_type_array(write_env_t *env, ir_type *tp)
write_type(env, element_type);
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);
for (size_t i = 0; i < n_dimensions; i++) {
ir_node *lower = get_array_lower_bound(tp, i);
ir_node *upper = get_array_upper_bound(tp, i);
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");
else
panic("Upper array bound is not constant");
}
ir_node *size = get_array_size(tp);
if (is_Const(size))
write_long(env, get_tarval_long(get_Const_tarval(size)));
else if (is_Unknown(size))
write_symbol(env, "unknown");
else
panic("Upper array bound is not constant");
/* note that we just write a reference to the element entity
* but never the entity itself */
ir_entity *element_entity = get_array_element_entity(tp);
......@@ -1648,25 +1637,14 @@ static void read_type(read_env_t *env)
switch (tpop) {
case tpo_array: {
size_t n_dimensions = read_size_t(env);
ir_type *elemtype = read_type_ref(env);
type = new_type_array(n_dimensions, elemtype);
for (size_t i = 0; i < n_dimensions; i++) {
char *str = read_word(env);
if (strcmp(str, "unknown") != 0) {
long lowerbound = atol(str);
set_array_lower_bound_int(type, i, lowerbound);
}
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);
ir_type *elemtype = read_type_ref(env);
type = new_type_array(elemtype);
char *str = read_word(env);
if (strcmp(str, "unknown") != 0) {
long size = atol(str);
set_array_size_int(type, size);
}
obstack_free(&env->obst, str);
long element_entity_nr = read_long(env);
ir_entity *element_entity = get_array_element_entity(type);
......
......@@ -396,8 +396,8 @@ static ir_entity *new_array_entity(ident *name, int size)
uint_type = new_type_primitive(mode_Iu);
set_type_alignment_bytes(uint_type, get_type_size_bytes(uint_type));
array_type = new_type_array(1, uint_type);
set_array_bounds_int(array_type, 0, 0, size);
array_type = new_type_array(uint_type);
set_array_size_int(array_type, size);
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_state(array_type, layout_fixed);
......@@ -418,14 +418,14 @@ static ir_entity *new_static_string_entity(ident *name, const char *string)
ir_entity *result;
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;
size_t i, length = strlen(string)+1;
/* 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_alignment_bytes(string_type, 1);
set_type_state(string_type, layout_fixed);
......
......@@ -41,7 +41,6 @@ static void lower_sel(ir_node *sel)
/* an Array access */
ir_type *basetyp = get_entity_type(ent);
ir_mode *basemode;
ir_node *index;
if (is_Primitive_type(basetyp))
basemode = get_type_mode(basetyp);
else
......@@ -49,92 +48,22 @@ static void lower_sel(ir_node *sel)
assert(basemode && "no mode for lowering Sel");
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)) {
ir_type *arr_ty = owner;
size_t dims = get_array_n_dimensions(arr_ty);
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)
ir_mode *mode_int = get_reference_mode_unsigned_eq(mode);
assert(get_Sel_n_indexs(sel) == 1
&& "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 */
tv = new_tarval_from_long(get_type_size_bytes(basetyp), mode_Int);
last_size = new_rd_Const(dbg, irg, tv);
/*
* We compute the offset part of dimension d_i recursively
* with the the offset part of dimension d_{i-1}
*
* off_0 = sizeof(array_element_type);
* 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);
}
unsigned size = get_type_size_bytes(basetyp);
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);
ir_node *mul = new_rd_Mul(dbg, bl, ind, el_size, mode_int);
ir_node *ptr = get_Sel_ptr(sel);
newn = new_rd_Add(dbg, bl, ptr, mul, mode);
} else {
/* no array type */
ir_mode *idx_mode = get_irn_mode(index);
......
......@@ -241,30 +241,22 @@ static ir_entity *find_constant_entity(ir_node *ptr)
if (is_Array_type(tp)) {
/* check bounds */
for (int i = 0, n = get_Sel_n_indexs(ptr); i < n; ++i) {
ir_node *index = get_Sel_index(ptr, i);
ir_tarval *tv = computed_value(index);
ir_node *index = get_Sel_index(ptr, 0);
ir_tarval *tv = computed_value(index);
/* check if the index is constant */
if (!tarval_is_constant(tv))
return NULL;
/* check if the index is constant */
if (!tarval_is_constant(tv))
return NULL;
ir_node *lower = get_array_lower_bound(tp, i);
ir_tarval *tlower = computed_value(lower);
ir_node *upper = get_array_upper_bound(tp, i);
ir_tarval *tupper = computed_value(upper);
ir_node *size = get_array_size(tp);
ir_tarval *tsize = computed_value(size);
if (!tarval_is_constant(tlower)
|| !tarval_is_constant(tupper))
return NULL;
if (!tarval_is_constant(tsize))
return NULL;
if (tarval_cmp(tv, tlower) == ir_relation_less)
return NULL;
if (tarval_cmp(tupper, tv) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
}
if (tarval_cmp(tv, tsize) != ir_relation_less)
return NULL;
/* ok, bounds check finished */
}
if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT)
......
......@@ -530,34 +530,22 @@ static ir_entity *find_constant_entity(ir_node *ptr)
if (is_Array_type(tp)) {
/* check bounds */
int i, n;
ir_node *index = get_Sel_index(ptr, 0);
ir_tarval *tv = computed_value(index);
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);
/* check if the index is constant */
if (!tarval_is_constant(tv))
return NULL;
/* check if the index is constant */
if (!tarval_is_constant(tv))
return NULL;
ir_node *size = get_array_size(tp);
ir_tarval *tsize = computed_value(size);
bound = get_array_lower_bound(tp, i);
tlower = computed_value(bound);
bound = get_array_upper_bound(tp, i);
tupper = computed_value(bound);
if (!tarval_is_constant(tsize))
return NULL;
if (!tarval_is_constant(tlower)
|| !tarval_is_constant(tupper))
return NULL;
if (tarval_cmp(tv, tlower) == ir_relation_less)
return NULL;
if (tarval_cmp(tupper, tv) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
}
if (tarval_cmp(tv, tsize) != ir_relation_less)
return NULL;
/* ok, bounds check finished */
}
if (get_entity_linkage(ent) == IR_LINKAGE_CONSTANT)
......
......@@ -92,7 +92,7 @@ static const tp_op_ops
},
/** tpop operations for array types */
array_ops = {
free_array_attrs,
NULL,
free_array_entities,
free_array_automatic_entities,
NULL,
......
......@@ -60,20 +60,6 @@ static bool check_compound_type(const ir_type *tp)
return fine;
}
static bool check_array_type(const ir_type *tp)
{
bool fine = true;
size_t n_dim = get_array_n_dimensions(tp);
for (size_t i = 0; i < n_dim; ++i) {
if (!has_array_lower_bound(tp, i) && !has_array_upper_bound(tp, i)) {
report_error("missing array bound in %+F in dimension %zu", tp, i);
fine = false;
}
}
return fine;
}
static bool check_type_mode(const ir_type *tp)
{
bool fine = true;
......@@ -100,9 +86,9 @@ int check_type(const ir_type *tp)
case tpo_union:
case tpo_struct:
case tpo_class: return check_compound_type(tp);
case tpo_array: return check_array_type(tp);
case tpo_primitive: return check_primitive_type(tp);
case tpo_pointer: return check_pointer_type(tp);
case tpo_array:
case tpo_method:
case tpo_uninitialized:
case tpo_unknown:
......
......@@ -954,26 +954,15 @@ int is_segment_type(const ir_type *type)
return (type->flags & tf_segment) != 0;
}
ir_type *new_type_array(size_t n_dimensions, ir_type *element_type)
ir_type *new_type_array(ir_type *element_type)
{
assert(!is_Method_type(element_type));
ir_type *res = new_type(type_array, NULL);
res->attr.aa.n_dimensions = n_dimensions;
res->attr.aa.lower_bound = XMALLOCNZ(ir_node*, n_dimensions);
res->attr.aa.upper_bound = XMALLOCNZ(ir_node*, n_dimensions);
res->attr.aa.order = XMALLOCNZ(size_t, n_dimensions);
ir_graph *irg = get_const_code_irg();
ir_node *unk = new_r_Unknown(irg, mode_Iu);
for (size_t i = 0; i < n_dimensions; i++) {
res->attr.aa.lower_bound[i] =
res->attr.aa.upper_bound[i] = unk;
res->attr.aa.order[i] = i;
}
ir_type *res = new_type(type_array, NULL);
res->attr.aa.element_type = element_type;
res->attr.aa.size = new_r_Unknown(get_const_code_irg(), mode_Iu);
ident *const id = new_id_from_chars("elem_ent", 8);
res->attr.aa.element_type = element_type;
res->attr.aa.element_ent = new_entity(res, id, element_type);
hook_new_type(res);
......@@ -992,131 +981,38 @@ void free_array_entities(ir_type *array)
assert(array->type_op == type_array);
}
void free_array_attrs(ir_type *array)
{
assert(array->type_op == type_array);
free(array->attr.aa.lower_bound);
free(array->attr.aa.upper_bound);
free(array->attr.aa.order);
}
size_t get_array_n_dimensions(const ir_type *array)
{
assert(array->type_op == type_array);
return array->attr.aa.n_dimensions;
}
void set_array_bounds(ir_type *array, size_t dimension, ir_node *lower_bound,
ir_node *upper_bound)
{
assert(array->type_op == type_array);
assert(lower_bound != NULL);
assert(upper_bound != NULL);
assert(dimension < array->attr.aa.n_dimensions);
array->attr.</