Fri Apr 9 20:03:38 1993 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) * c-typeck.c (free_tree_list): New variable. (digest_init): Set free_tree_list. (process_init_constructor): Use add_double to do arithmetic with double integers instead of using fold/build to to arithmetic in type of array index. Use free_tree_list when available instead of generating a new tree_list. *** c-typeck.c.orig Thu Nov 26 12:30:00 1992 --- c-typeck.c Sat Apr 17 22:12:17 1993 *************** pedwarn_init (format, local, ofwhat) *** 4521,4526 **** --- 4521,4540 ---- pedwarn (format, buffer); } + /* Keep a pointer to the last free TREE_LIST node as we digest an initializer, + so that we can reuse it. This is set in digest_init, and used in + process_init_constructor. + + We will never keep more than one free TREE_LIST node here. This is for + two main reasons. First, we take elements off the old list and add them + to the new list one at a time, thus there should never be more than + one free TREE_LIST at a time, and thus even if there is, we will never + need more than one. Secondly, to avoid dangling pointers to freed obstacks, + we want to always ensure that we have either a pointer to a valid TREE_LIST + within the current initializer, or else a pointer to null. */ + + static tree free_tree_list = NULL_TREE; + /* Digest the parser output INIT as an initializer for type TYPE. Return a C expression of type TYPE to represent the initial value. *************** digest_init (type, init, tail, require_c *** 4554,4566 **** tree inside_init = init; /* By default, assume we use one element from a list. ! We correct this later in the sole case where it is not true. */ if (tail) { old_tail_contents = *tail; *tail = TREE_CHAIN (*tail); } if (init == error_mark_node) return init; --- 4568,4588 ---- tree inside_init = init; /* By default, assume we use one element from a list. ! We correct this later in the cases where it is not true. ! ! Thus, we update TAIL now to point to the next element, and save the ! old value in OLD_TAIL_CONTENTS. If we didn't actually use the first ! element, then we will reset TAIL before proceeding. FREE_TREE_LIST ! is handled similarly. */ if (tail) { old_tail_contents = *tail; *tail = TREE_CHAIN (*tail); + free_tree_list = old_tail_contents; } + else + free_tree_list = 0; if (init == error_mark_node) return init; *************** digest_init (type, init, tail, require_c *** 4737,4742 **** --- 4759,4765 ---- else if (tail != 0) { *tail = old_tail_contents; + free_tree_list = NULL_TREE; result = process_init_constructor (type, NULL_TREE, tail, require_constant, constructor_constant, ofwhat); *************** digest_init (type, init, tail, require_c *** 4833,4838 **** --- 4856,4862 ---- else if (tail != 0) { *tail = old_tail_contents; + free_tree_list = NULL_TREE; return process_init_constructor (type, NULL_TREE, tail, constructor_constant, constructor_constant, ofwhat); *************** process_init_constructor (type, init, el *** 4917,4954 **** if (TREE_CODE (type) == ARRAY_TYPE) { ! tree min_index, max_index, current_index, members_index; ! tree bound_type; ! tree one; /* These are non-zero only within a range initializer. */ tree start_index = 0, end_index = 0; /* Within a range, this is the value for the elts in the range. */ tree range_val = 0; /* If we have array bounds, set our bounds from that. Otherwise, ! we have a lower bound of zero and an unknown upper bound. Also ! set the type of the bounds; use "int" as default. */ if (TYPE_DOMAIN (type)) { ! min_index = members_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); - bound_type = TREE_TYPE (min_index); } else { ! min_index = members_index = integer_zero_node; max_index = 0; - bound_type = integer_type_node; } ! one = convert (bound_type, integer_one_node); /* Don't leave the loop based on index if the next item has an explicit index value that will override it. */ ! for (current_index = min_index; tail != 0 || end_index; ! current_index = fold (build (PLUS_EXPR, bound_type, ! current_index, one))) { register tree next1 = 0; --- 4941,4987 ---- if (TREE_CODE (type) == ARRAY_TYPE) { ! tree min_index, max_index; /* These are non-zero only within a range initializer. */ tree start_index = 0, end_index = 0; /* Within a range, this is the value for the elts in the range. */ tree range_val = 0; + /* Do arithmetic using double integers, but don't use fold/build, + because these allocate a new tree object everytime they are called, + thus resulting in gcc using too much memory for large + initializers. */ + union tree_node current_index_node, members_index_node; + tree current_index = ¤t_index_node; + tree members_index = &members_index_node; + TREE_TYPE (current_index) = integer_type_node; + TREE_TYPE (members_index) = integer_type_node; /* If we have array bounds, set our bounds from that. Otherwise, ! we have a lower bound of zero and an unknown upper bound. */ if (TYPE_DOMAIN (type)) { ! min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); } else { ! min_index = integer_zero_node; max_index = 0; } ! TREE_INT_CST_LOW (members_index) = TREE_INT_CST_LOW (min_index); ! TREE_INT_CST_HIGH (members_index) = TREE_INT_CST_HIGH (min_index); /* Don't leave the loop based on index if the next item has an explicit index value that will override it. */ ! for (TREE_INT_CST_LOW (current_index) = TREE_INT_CST_LOW (min_index), ! TREE_INT_CST_HIGH (current_index) = TREE_INT_CST_HIGH (min_index); ! tail != 0 || end_index; ! add_double (TREE_INT_CST_LOW (current_index), ! TREE_INT_CST_HIGH (current_index), 1, 0, ! &TREE_INT_CST_LOW (current_index), ! &TREE_INT_CST_HIGH (current_index))) { register tree next1 = 0; *************** process_init_constructor (type, init, el *** 5095,5114 **** Make the list longer if necessary. */ while (! tree_int_cst_lt (current_index, members_index)) { ! members = tree_cons (NULL_TREE, NULL_TREE, members); ! members_index = fold (build (PLUS_EXPR, bound_type, ! members_index, one)); } { tree temp; ! tree idx; temp = members; ! for (idx = fold (build (MINUS_EXPR, bound_type, ! members_index, one)); tree_int_cst_lt (current_index, idx); ! idx = fold (build (MINUS_EXPR, bound_type, idx, one))) temp = TREE_CHAIN (temp); TREE_VALUE (temp) = next1; } --- 5128,5165 ---- Make the list longer if necessary. */ while (! tree_int_cst_lt (current_index, members_index)) { ! if (free_tree_list) ! { ! TREE_CHAIN (free_tree_list) = members; ! TREE_PURPOSE (free_tree_list) = NULL_TREE; ! TREE_VALUE (free_tree_list) = NULL_TREE; ! members = free_tree_list; ! free_tree_list = NULL_TREE; ! } ! else ! members = tree_cons (NULL_TREE, NULL_TREE, members); ! add_double (TREE_INT_CST_LOW (members_index), ! TREE_INT_CST_HIGH (members_index), 1, 0, ! &TREE_INT_CST_LOW (members_index), ! &TREE_INT_CST_HIGH (members_index)); } { tree temp; ! union tree_node idx_node; ! tree idx = &idx_node; ! TREE_TYPE (idx) = integer_type_node; temp = members; ! for (add_double (TREE_INT_CST_LOW (members_index), ! TREE_INT_CST_HIGH (members_index), -1, -1, ! &TREE_INT_CST_LOW (idx), ! &TREE_INT_CST_HIGH (idx)); tree_int_cst_lt (current_index, idx); ! add_double (TREE_INT_CST_LOW (idx), ! TREE_INT_CST_HIGH (idx), -1, -1, ! &TREE_INT_CST_LOW (idx), ! &TREE_INT_CST_HIGH (idx))) temp = TREE_CHAIN (temp); TREE_VALUE (temp) = next1; } *************** process_init_constructor (type, init, el *** 5196,5202 **** Make the list longer if necessary. */ while (i >= members_length) { ! members = tree_cons (NULL_TREE, NULL_TREE, members); members_length++; } { --- 5247,5262 ---- Make the list longer if necessary. */ while (i >= members_length) { ! if (free_tree_list) ! { ! TREE_CHAIN (free_tree_list) = members; ! TREE_PURPOSE (free_tree_list) = NULL_TREE; ! TREE_VALUE (free_tree_list) = NULL_TREE; ! members = free_tree_list; ! free_tree_list = NULL_TREE; ! } ! else ! members = tree_cons (NULL_TREE, NULL_TREE, members); members_length++; } { *************** process_init_constructor (type, init, el *** 5284,5291 **** else if (!TREE_CONSTANT (next1)) allconstant = 0; else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) ! allsimple = 0; ! members = tree_cons (field, next1, members); } /* If arguments were specified as a list, just remove the ones we used. */ --- 5344,5360 ---- else if (!TREE_CONSTANT (next1)) allconstant = 0; else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) ! allsimple = 0; ! if (free_tree_list) ! { ! TREE_CHAIN (free_tree_list) = members; ! TREE_PURPOSE (free_tree_list) = field; ! TREE_VALUE (free_tree_list) = next1; ! members = free_tree_list; ! free_tree_list = NULL_TREE; ! } ! else ! members = tree_cons (field, next1, members); } /* If arguments were specified as a list, just remove the ones we used. */ *************** process_init_constructor (type, init, el *** 5316,5322 **** if (erroneous) return error_mark_node; ! result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members)); if (allconstant) TREE_CONSTANT (result) = 1; if (allconstant && allsimple) TREE_STATIC (result) = 1; return result; --- 5385,5400 ---- if (erroneous) return error_mark_node; ! if (elts) ! result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members)); ! else ! { ! result = init; ! CONSTRUCTOR_ELTS (result) = nreverse (members); ! TREE_TYPE (result) = type; ! TREE_CONSTANT (result) = 0; ! TREE_STATIC (result) = 0; ! } if (allconstant) TREE_CONSTANT (result) = 1; if (allconstant && allsimple) TREE_STATIC (result) = 1; return result;