- init_index(elem_tp);
- }
- }
- }
-
- /* Finally compute the indicees ... */
- for (i = 0; i < n_vals; ++i) {
- compound_graph_path *path = get_compound_ent_value_path(ent, i);
- int j, path_len = get_compound_graph_path_length(path);
- for (j = 0; j < path_len; ++j) {
- entity *node = get_compound_graph_path_node(path, j);
- type *owner_tp = get_entity_owner(node);
- if (is_array_type(owner_tp))
- set_compound_graph_path_array_index (path, j, get_next_index(node));
- }
- }
-
-}
-
-
-static int *resize (int *buf, int new_size) {
- int *new_buf = (int *)calloc(new_size, 4);
- memcpy(new_buf, buf, new_size>1);
- free(buf);
- return new_buf;
-}
-
-/* We sort the elements by placing them at their bit offset in an
- array where each entry represents one bit called permutation. In
- fact, we do not place the values themselves, as we would have to
- copy two things, the value and the path. We only remember the
- position in the old order. Each value should have a distinct
- position in the permutation.
-
- A second iteration now permutes the actual elements into two
- new arrays. */
-void sort_compound_ent_values(entity *ent) {
- assert(get_type_state(get_entity_type(ent)) == layout_fixed);
-
- type *tp = get_entity_type(ent);
- int i, n_vals = get_compound_ent_n_values(ent);
- int tp_size = get_type_size_bits(tp);
- int size;
- int *permutation;
-
- if (!is_compound_type(tp) ||
- (ent->variability == variability_uninitialized) ||
- (get_type_state(tp) != layout_fixed) ||
- (n_vals == 0) ) return;
-
- /* estimated upper bound for size. Better: use flexible array ... */
- size = ((tp_size > (n_vals * 32)) ? tp_size : (n_vals * 32)) * 4;
- permutation = (int *)calloc(size, 4);
- for (i = 0; i < n_vals; ++i) {
- int pos = get_compound_ent_value_offset_bits(ent, i);
- while (pos >= size) {
- size = size + size;
- permutation = resize(permutation, size);
- }
- assert(pos < size);
- assert(permutation[pos] == 0 && "two values with the same offset");
- permutation[pos] = i + 1; /* We initialized with 0, so we can not distinguish entry 0.
- So inc all entries by one. */
- //fprintf(stderr, "i: %d, pos: %d \n", i, pos);
- }
-
- int next = 0;
- ir_node **my_values = NEW_ARR_F(ir_node *, n_vals);
- compound_graph_path **my_paths = NEW_ARR_F(compound_graph_path *, n_vals);
- for (i = 0; i < size; ++i) {
- int pos = permutation[i];
- if (pos) {
- //fprintf(stderr, "pos: %d i: %d next %d \n", i, pos, next);
- assert(next < n_vals);
- pos--; /* We increased the pos by one */
- my_values[next] = get_compound_ent_value (ent, pos);
- my_paths [next] = get_compound_ent_value_path(ent, pos);
- next++;
- }
- }
- free(permutation);
+ array_infos = alloca(max_len * sizeof(array_infos[0]));
+ memset(array_infos, 0, max_len * sizeof(array_infos[0]));
+
+ for(i = 0; i < n_vals; ++i) {
+ compound_graph_path *path = get_compound_ent_value_path(ent, i);
+ int path_len = get_compound_graph_path_length(path);
+ int j;
+ int needadd = 0;
+ ir_entity *prev_node = NULL;
+
+ for(j = path_len-1; j >= 0; --j) {
+ int dim, dims;
+ int n_elems;
+ ir_entity *node = get_compound_graph_path_node(path, j);
+ const ir_type *node_type = get_entity_type(node);
+ array_info *info = &array_infos[j];
+
+ if(is_atomic_entity(node)) {
+ needadd = 1;
+ set_compound_graph_path_array_index(path, j, -1);
+ prev_node = node;
+ continue;
+ } else if(is_compound_type(node_type) && !is_Array_type(node_type)) {
+ int n_members = get_compound_n_members(node_type);
+ ir_entity *last = get_compound_member(node_type, n_members - 1);
+ if(needadd && last == prev_node) {
+ needadd = 1;
+ } else {
+ needadd = 0;
+ }
+ set_compound_graph_path_array_index(path, j, -1);
+ prev_node = node;
+ continue;
+ }
+
+ if(info->ent != node) {
+ n_elems = 1;
+ dims = get_array_n_dimensions(node_type);
+ for(dim = 0; dim < dims; ++dim) {
+ long lower_bound = 0;
+ long upper_bound = -1;
+
+ if(has_array_lower_bound(node_type, 0)) {
+ lower_bound = get_array_lower_bound_int(node_type, 0);
+ }
+ if(has_array_upper_bound(node_type, 0)) {
+ upper_bound = get_array_upper_bound_int(node_type, 0);
+ assert(upper_bound >= lower_bound);
+ n_elems *= (upper_bound - lower_bound);
+ } else {
+ assert(dim == dims-1);
+ n_elems = -1;
+ }
+ }
+
+ info->ent = node;
+ info->n_elems = n_elems;
+ info->current_elem = 0;
+ }
+
+ set_compound_graph_path_array_index(path, j, info->current_elem);
+
+ if(needadd) {
+ info->current_elem++;
+ if(info->current_elem >= info->n_elems) {
+ needadd = 1;
+ info->current_elem = 0;
+ } else {
+ needadd = 0;
+ }
+ }
+
+ prev_node = node;
+ }
+ }