* Makefile.in (ggc-simple.o): Depend on varray.h.
(rtl.o): Depend on ggc.h.
(genattrtab.o): Depend on ggc.h.
(print-tree.o): Likewise.
(fold-const.o): Likewise.
* emit-rtl.c (sequence_element_free_list): Remove, and all references.
(make_insn_raw): Don't cache insns when GC'ing.
(emit_insn_before): Likewise.
(emit_insn_after): Likewise.
(emit_insn): Likewise.
(start_sequence): Use xmalloc to allocate the sequence_stack.
(end_sequence): Add free to free it.
(gen_sequence): Don't cache insns when GC'ing.
(clear_emit_caches): Don't use sequence_element_free_list.
(init_emit): Use xcalloc, not xmalloc+bzero.
* fold-const.c (size_int_wide): Kill the cache, when GC'ing.
* function.c (pop_function_context_from): Use free to free the
fixup_var_refs_queue.
(put_reg_into_stack): Allocate it with xmalloc.
* genattrtab.c: Include ggc.h.
(operate_exp): Don't use obstack_free when GC'ing.
(simplify_cond): Likewise.
(simplify_text_exp): Likewise.
(optimize_attrs): Likewise.
* gengentrtl.c (gendef): Use ggc_alloc_rtx to allocate RTL, when
GC'ing.
(gencode): Generate a #include for ggc.h.
* ggc-callbacks.c (ggc_p): Define it to zero.
* ggc-none.c (ggc_p): Likewise.
* ggc-simple.c: Include varray.h.
(ggc_mark_tree_varray): New function.
(ggc_add_tree_varray_root): Likewise.
(ggc_mark_tree_varray_ptr): Likewise.
* ggc.h (ggc_p): Declare.
(varray_head_tag): Likewise.
(ggc_add_tree_varray_root): Declare.
* print-tree.c (print_node): Don't check for TREE_PERMANENT
inconsistencies when GC'ing.
* rtl.c: Include ggc.h.
(rtvec_alloc): Use ggc_alloc_rtvec when GC'ing.
(rtx_alloc): Use ggc_alloc_rtx when GC'ing.
(rtx_free): Don't call obstack_free when GC'ing.
* toplev.c (rest_of_compilation): Call ggc_collect after every
pass, if GC'ing.
* tree.c (push_obstacks): Do nothing, if GC'ing.
(pop_obstacks_nochange): Likewise.
(pop_obstacks): Likewise.
(make_node): Use ggc_alloc_tree when GC'ing.
(copy_node): Likewise.
(get_identifier): Use ggc_alloc_string when GC'ing.
(build_string): Likewise.
(make_tree_vec): Use ggc_alloc_tree when GC'ing.
(tree_cons): Likewise.
(build1): Likewise.
(type_hash_canon): Don't call obstack_free when GC'ing.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29125
+Sun Sep 5 00:35:17 1999 Richard Henderson <rth@cygnus.com>
+ Bernd Schmidt <bernds@cygnus.co.uk>
+ Mark Mitchell <mark@codesourcery.com>
+
+ * Makefile.in (ggc-simple.o): Depend on varray.h.
+ (rtl.o): Depend on ggc.h.
+ (genattrtab.o): Depend on ggc.h.
+ (print-tree.o): Likewise.
+ (fold-const.o): Likewise.
+ * emit-rtl.c (sequence_element_free_list): Remove, and all references.
+ (make_insn_raw): Don't cache insns when GC'ing.
+ (emit_insn_before): Likewise.
+ (emit_insn_after): Likewise.
+ (emit_insn): Likewise.
+ (start_sequence): Use xmalloc to allocate the sequence_stack.
+ (end_sequence): Add free to free it.
+ (gen_sequence): Don't cache insns when GC'ing.
+ (clear_emit_caches): Don't use sequence_element_free_list.
+ (init_emit): Use xcalloc, not xmalloc+bzero.
+ * fold-const.c (size_int_wide): Kill the cache, when GC'ing.
+ * function.c (pop_function_context_from): Use free to free the
+ fixup_var_refs_queue.
+ (put_reg_into_stack): Allocate it with xmalloc.
+ * genattrtab.c: Include ggc.h.
+ (operate_exp): Don't use obstack_free when GC'ing.
+ (simplify_cond): Likewise.
+ (simplify_text_exp): Likewise.
+ (optimize_attrs): Likewise.
+ * gengentrtl.c (gendef): Use ggc_alloc_rtx to allocate RTL, when
+ GC'ing.
+ (gencode): Generate a #include for ggc.h.
+ * ggc-callbacks.c (ggc_p): Define it to zero.
+ * ggc-none.c (ggc_p): Likewise.
+ * ggc-simple.c: Include varray.h.
+ (ggc_mark_tree_varray): New function.
+ (ggc_add_tree_varray_root): Likewise.
+ (ggc_mark_tree_varray_ptr): Likewise.
+ * ggc.h (ggc_p): Declare.
+ (varray_head_tag): Likewise.
+ (ggc_add_tree_varray_root): Declare.
+ * print-tree.c (print_node): Don't check for TREE_PERMANENT
+ inconsistencies when GC'ing.
+ * rtl.c: Include ggc.h.
+ (rtvec_alloc): Use ggc_alloc_rtvec when GC'ing.
+ (rtx_alloc): Use ggc_alloc_rtx when GC'ing.
+ (rtx_free): Don't call obstack_free when GC'ing.
+ * toplev.c (rest_of_compilation): Call ggc_collect after every
+ pass, if GC'ing.
+ * tree.c (push_obstacks): Do nothing, if GC'ing.
+ (pop_obstacks_nochange): Likewise.
+ (pop_obstacks): Likewise.
+ (make_node): Use ggc_alloc_tree when GC'ing.
+ (copy_node): Likewise.
+ (get_identifier): Use ggc_alloc_string when GC'ing.
+ (build_string): Likewise.
+ (make_tree_vec): Use ggc_alloc_tree when GC'ing.
+ (tree_cons): Likewise.
+ (build1): Likewise.
+ (type_hash_canon): Don't call obstack_free when GC'ing.
+
Sat Sep 4 21:52:32 1999 Richard Henderson <rth@cygnus.com>
* haifa-sched.c (schedule_block): Use next_nonnote_insn instead
version.o: version.c
-ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) flags.h ggc.h
+ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) flags.h \
+ ggc.h varray.h
ggc-none.o: ggc-none.c $(CONFIG_H) $(RTL_BASE_H) ggc.h
tree.o : tree.c $(CONFIG_H) system.h $(TREE_H) flags.h function.h toplev.h \
ggc.h
-print-tree.o : print-tree.c $(CONFIG_H) system.h $(TREE_H)
+print-tree.o : print-tree.c $(CONFIG_H) system.h $(TREE_H) ggc.h
stor-layout.o : stor-layout.c $(CONFIG_H) system.h $(TREE_H) flags.h \
function.h $(EXPR_H) $(RTL_H) toplev.h ggc.h
fold-const.o : fold-const.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h \
- $(RTL_H)
+ $(RTL_H) ggc.h
toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) function.h \
flags.h input.h insn-attr.h xcoffout.h defaults.h output.h \
insn-codes.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h dwarfout.h \
-DTARGET_NAME=\"$(target_alias)\" \
-c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
-rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
+rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h ggc.h
print-rtl.o : print-rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h basic-block.h
rtlanal.o : rtlanal.c $(CONFIG_H) system.h $(RTL_H)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_RTLANAL) $(HOST_LIBS)
-genattrtab.o : genattrtab.c $(RTL_H) $(build_xm_file) system.h insn-config.h errors.h
+genattrtab.o : genattrtab.c $(RTL_H) $(build_xm_file) system.h insn-config.h errors.h ggc.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c
genoutput : genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
/* start_sequence and gen_sequence can make a lot of rtx expressions which are
shortly thrown away. We use two mechanisms to prevent this waste:
- First, we keep a list of the expressions used to represent the sequence
- stack in sequence_element_free_list.
-
- Second, for sizes up to 5 elements, we keep a SEQUENCE and its associated
- rtvec for use by gen_sequence. One entry for each size is sufficient
- because most cases are calls to gen_sequence followed by immediately
- emitting the SEQUENCE. Reuse is safe since emitting a sequence is
- destructive on the insn in it anyway and hence can't be redone.
+ For sizes up to 5 elements, we keep a SEQUENCE and its associated
+ rtvec for use by gen_sequence. One entry for each size is
+ sufficient because most cases are calls to gen_sequence followed by
+ immediately emitting the SEQUENCE. Reuse is safe since emitting a
+ sequence is destructive on the insn in it anyway and hence can't be
+ redone.
We do not bother to save this cached data over nested function calls.
Instead, we just reinitialize them. */
#define SEQUENCE_RESULT_SIZE 5
-static struct sequence_stack *sequence_element_free_list;
static rtx sequence_result[SEQUENCE_RESULT_SIZE];
/* During RTL generation, we also keep a list of free INSN rtl codes. */
register rtx insn;
/* If in RTL generation phase, see if FREE_INSN can be used. */
- if (free_insn != 0 && rtx_equal_function_value_matters)
+ if (!ggc_p && free_insn != 0 && rtx_equal_function_value_matters)
{
insn = free_insn;
free_insn = NEXT_INSN (free_insn);
insn = XVECEXP (pattern, 0, i);
add_insn_before (insn, before);
}
- if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
+ if (!ggc_p && XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
add_insn_after (insn, after);
after = insn;
}
- if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
+ if (!ggc_p && XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
insn = XVECEXP (pattern, 0, i);
add_insn (insn);
}
- if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
+ if (!ggc_p && XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
{
struct sequence_stack *tem;
- if (sequence_element_free_list)
- {
- /* Reuse a previously-saved struct sequence_stack. */
- tem = sequence_element_free_list;
- sequence_element_free_list = tem->next;
- }
- else
- tem = (struct sequence_stack *) permalloc (sizeof (struct sequence_stack));
+ tem = (struct sequence_stack *) xmalloc (sizeof (struct sequence_stack));
tem->next = seq_stack;
tem->first = first_insn;
seq_rtl_expr = tem->sequence_rtl_expr;
seq_stack = tem->next;
- tem->next = sequence_element_free_list;
- sequence_element_free_list = tem;
+ free (tem);
}
/* Return 1 if currently emitting into a sequence. */
|| (GET_CODE (first_insn) == CALL_INSN
&& CALL_INSN_FUNCTION_USAGE (first_insn) == NULL_RTX)))
{
- NEXT_INSN (first_insn) = free_insn;
- free_insn = first_insn;
+ if (!ggc_p)
+ {
+ NEXT_INSN (first_insn) = free_insn;
+ free_insn = first_insn;
+ }
return PATTERN (first_insn);
}
/* Put them in a vector. See if we already have a SEQUENCE of the
appropriate length around. */
- if (len < SEQUENCE_RESULT_SIZE && (result = sequence_result[len]) != 0)
+ if (!ggc_p && len < SEQUENCE_RESULT_SIZE
+ && (result = sequence_result[len]) != 0)
sequence_result[len] = 0;
else
{
int i;
/* Clear the start_sequence/gen_sequence cache. */
- sequence_element_free_list = 0;
for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
sequence_result[i] = 0;
free_insn = 0;
f->emit->regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101;
f->emit->regno_pointer_flag
- = (char *) xmalloc (f->emit->regno_pointer_flag_length);
- bzero (f->emit->regno_pointer_flag, f->emit->regno_pointer_flag_length);
+ = (char *) xcalloc (f->emit->regno_pointer_flag_length, sizeof (char));
f->emit->regno_pointer_align
- = (char *) xmalloc (f->emit->regno_pointer_flag_length);
- bzero (f->emit->regno_pointer_align, f->emit->regno_pointer_flag_length);
+ = (char *) xcalloc (f->emit->regno_pointer_flag_length,
+ sizeof (char));
regno_reg_rtx
- = (rtx *) xmalloc (f->emit->regno_pointer_flag_length * sizeof (rtx));
- bzero ((char *) regno_reg_rtx,
- f->emit->regno_pointer_flag_length * sizeof (rtx));
+ = (rtx *) xcalloc (f->emit->regno_pointer_flag_length * sizeof (rtx),
+ sizeof (rtx));
/* Put copies of all the virtual register rtx into regno_reg_rtx. */
init_virtual_regs (f->emit);
#include "tree.h"
#include "rtl.h"
#include "toplev.h"
+#include "ggc.h"
static void encode PROTO((HOST_WIDE_INT *,
HOST_WIDE_INT, HOST_WIDE_INT));
unsigned HOST_WIDE_INT number, high;
int bit_p;
{
- register tree t;
- /* Type-size nodes already made for small sizes. */
- static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1][2];
-
- if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high
- && size_table[number][bit_p] != 0)
- return size_table[number][bit_p];
- if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high)
- {
- push_obstacks_nochange ();
- /* Make this a permanent node. */
- end_temporary_allocation ();
- t = build_int_2 (number, 0);
- TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
- size_table[number][bit_p] = t;
- pop_obstacks ();
- }
- else
+ tree t;
+
+ if (!ggc_p)
{
- t = build_int_2 (number, high);
- TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
- TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
+ /* Type-size nodes already made for small sizes. */
+ static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1][2];
+
+ if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high
+ && size_table[number][bit_p] != 0)
+ return size_table[number][bit_p];
+ if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high)
+ {
+ push_obstacks_nochange ();
+ /* Make this a permanent node. */
+ end_temporary_allocation ();
+ t = build_int_2 (number, 0);
+ TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
+ size_table[number][bit_p] = t;
+ pop_obstacks ();
+ return t;
+ }
}
+
+ t = build_int_2 (number, high);
+ TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
+ TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
return t;
}
{
struct function *p = outer_function_chain;
struct var_refs_queue *queue;
+ struct var_refs_queue *next;
current_function = p;
outer_function_chain = p->next;
/* Finish doing put_var_into_stack for any of our variables
which became addressable during the nested function. */
- for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
- fixup_var_refs (queue->modified, queue->promoted_mode,
- queue->unsignedp, 0);
+ for (queue = p->fixup_var_refs_queue; queue; queue = next)
+ {
+ next = queue->next;
+ fixup_var_refs (queue->modified, queue->promoted_mode,
+ queue->unsignedp, 0);
+ free (queue);
+ }
+ p->fixup_var_refs_queue = 0;
/* Reset variables that have known state during rtx generation. */
rtx_equal_function_value_matters = 1;
{
struct var_refs_queue *temp;
- /* Variable is inherited; fix it up when we get back to its function. */
- push_obstacks (function->function_obstack,
- function->function_maybepermanent_obstack);
-
- /* See comment in restore_tree_status in tree.c for why this needs to be
- on saveable obstack. */
temp
- = (struct var_refs_queue *) savealloc (sizeof (struct var_refs_queue));
+ = (struct var_refs_queue *) xmalloc (sizeof (struct var_refs_queue));
temp->modified = reg;
temp->promoted_mode = promoted_mode;
temp->unsignedp = TREE_UNSIGNED (type);
temp->next = function->fixup_var_refs_queue;
function->fixup_var_refs_queue = temp;
- pop_obstacks ();
}
else if (used_p)
/* Variable is local; fix it up now. */
#include "system.h"
#include "rtl.h"
#include "insn-config.h" /* For REGISTER_CONSTRAINTS */
+#include "ggc.h"
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
give the same value), optimize it away. */
if (allsame)
{
- obstack_free (rtl_obstack, newexp);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, newexp);
return operate_exp (op, left, XEXP (right, 1));
}
just use that. */
if (rtx_equal_p (newexp, right))
{
- obstack_free (rtl_obstack, newexp);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, newexp);
return right;
}
optimize it away. */
if (allsame)
{
- obstack_free (rtl_obstack, newexp);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, newexp);
return operate_exp (op, XEXP (left, 1), right);
}
just use that. */
if (rtx_equal_p (newexp, left))
{
- obstack_free (rtl_obstack, newexp);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, newexp);
return left;
}
if (len == 0)
{
- obstack_free (rtl_obstack, first_spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, first_spacer);
if (GET_CODE (defval) == COND)
return simplify_cond (defval, insn_code, insn_index);
return defval;
}
else if (allsame)
{
- obstack_free (rtl_obstack, first_spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, first_spacer);
return exp;
}
else
SIMPLIFY_ALTERNATIVE (left);
if (left == false_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return false_rtx;
}
right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
SIMPLIFY_ALTERNATIVE (right);
if (left == false_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return false_rtx;
}
if (left == false_rtx || right == false_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return false_rtx;
}
else if (left == true_rtx)
SIMPLIFY_ALTERNATIVE (left);
if (left == true_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return true_rtx;
}
right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
SIMPLIFY_ALTERNATIVE (right);
if (right == true_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return true_rtx;
}
if (right == true_rtx || left == true_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return true_rtx;
}
else if (left == false_rtx)
if (left == false_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return true_rtx;
}
else if (left == true_rtx)
{
- obstack_free (rtl_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, spacer);
return false_rtx;
}
insert_insn_ent (av, ie);
something_changed = 1;
}
- obstack_free (temp_obstack, spacer);
+ if (!ggc_p)
+ obstack_free (temp_obstack, spacer);
}
}
}
#include "tree.h"
#include "ggc.h"
+int ggc_p = 0;
+
void
lang_mark_tree (t)
union tree_node *t ATTRIBUTE_UNUSED;
#include "rtl.h"
#include "ggc.h"
+/* For now, keep using the old obstack scheme in the gen* programs. */
+int ggc_p = 0;
+
rtx
ggc_alloc_rtx (nslots)
int nslots;
#include "tree.h"
#include "ggc.h"
#include "flags.h"
+#include "varray.h"
/* Debugging flags. */
#undef GGC_DUMP
static void ggc_free_tree PROTO ((struct ggc_tree *t));
static void ggc_mark_rtx_ptr PROTO ((void *elt));
static void ggc_mark_tree_ptr PROTO ((void *elt));
+static void ggc_mark_tree_varray_ptr PROTO ((void *elt));
/* These allocators are dreadfully simple, with no caching whatsoever so
that Purify-like tools that do allocation versioning can catch errors.
}
}
+/* Mark all the elements of the varray V, which contains trees. */
+
+void
+ggc_mark_tree_varray (v)
+ varray_type v;
+{
+ int i;
+
+ for (i = v->num_elements - 1; i >= 0; --i)
+ ggc_mark_tree (VARRAY_TREE (v, i));
+}
+
void
ggc_mark_string (s)
char *s;
ggc_add_root (base, nelt, sizeof(tree), ggc_mark_tree_ptr);
}
+/* Add vV (a varray full of trees) to the list of GC roots. */
+
+void
+ggc_add_tree_varray_root (base, nelt)
+ varray_type *base;
+ int nelt;
+{
+ ggc_add_root (base, nelt, sizeof (varray_type),
+ ggc_mark_tree_varray_ptr);
+}
+
void
ggc_del_root (base)
void *base;
ggc_mark_tree (*(tree *)elt);
}
+/* Type-correct function to pass to ggc_add_root. It just forwards
+ ELT (which is really a varray_type *) to ggc_mark_tree_varray. */
+
+static void
+ggc_mark_tree_varray_ptr (elt)
+ void *elt;
+{
+ ggc_mark_tree_varray (*(varray_type *)elt);
+}
+
#ifdef GGC_DUMP
/* Don't enable this unless you want a really really lot of data. */
static void __attribute__((constructor))
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
+/* Language-specific code defines this variable to be either one (if
+ it wants garbage collection), or zero (if it does not). */
+extern int ggc_p;
+
/* These structures are defined in various headers throughout the
compiler. However, rather than force everyone who includes this
header to include all the headers in which they are declared, we
struct emit_status;
struct stmt_status;
struct varasm_status;
+struct varray_head_tag;
/* Startup */
void (*)(void *)));
void ggc_add_rtx_root PROTO ((struct rtx_def **, int nelt));
void ggc_add_tree_root PROTO ((union tree_node **, int nelt));
+void ggc_add_tree_varray_root PROTO ((struct varray_head_tag **, int nelt));
void ggc_del_root PROTO ((void *base));
/* Mark nodes from the gc_add_root callback. */
#include "config.h"
#include "system.h"
#include "tree.h"
+#include "ggc.h"
void print_node ();
void indent_to ();
}
/* If a permanent object is in the wrong obstack, or the reverse, warn. */
- if (object_permanent_p (node) != TREE_PERMANENT (node))
+ if (!ggc_p && object_permanent_p (node) != TREE_PERMANENT (node))
{
if (TREE_PERMANENT (node))
fputs (" !!permanent object in non-permanent obstack!!", file);
#include "rtl.h"
#include "real.h"
#include "bitmap.h"
-
+#include "ggc.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
int n;
{
rtvec rt;
- int i;
-
- rt = (rtvec) obstack_alloc (rtl_obstack,
- sizeof (struct rtvec_def)
- + (( n - 1) * sizeof (rtx)));
+
+ if (ggc_p)
+ rt = ggc_alloc_rtvec (n);
+ else
+ {
+ int i;
- /* clear out the vector */
- PUT_NUM_ELEM (rt, n);
+ rt = (rtvec) obstack_alloc (rtl_obstack,
+ sizeof (struct rtvec_def)
+ + (( n - 1) * sizeof (rtx)));
- for (i = 0; i < n; i++)
- rt->elem[i] = 0;
+ /* clear out the vector */
+ for (i = 0; i < n; i++)
+ rt->elem[i] = 0;
+ }
+ PUT_NUM_ELEM (rt, n);
return rt;
}
RTX_CODE code;
{
rtx rt;
- register struct obstack *ob = rtl_obstack;
- register int nelts = GET_RTX_LENGTH (code);
- register int length = sizeof (struct rtx_def)
- + (nelts - 1) * sizeof (rtunion);
-
- /* This function is called more than any other in GCC,
- so we manipulate the obstack directly.
- Even though rtx objects are word aligned, we may be sharing an obstack
- with tree nodes, which may have to be double-word aligned. So align
- our length to the alignment mask in the obstack. */
-
- length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
-
- if (ob->chunk_limit - ob->next_free < length)
- _obstack_newchunk (ob, length);
- rt = (rtx)ob->object_base;
- ob->next_free += length;
- ob->object_base = ob->next_free;
-
- /* We want to clear everything up to the FLD array. Normally, this is
- one int, but we don't want to assume that and it isn't very portable
- anyway; this is. */
-
- memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
+ if (ggc_p)
+ rt = ggc_alloc_rtx (GET_RTX_LENGTH (code));
+ else
+ {
+ register struct obstack *ob = rtl_obstack;
+ register int nelts = GET_RTX_LENGTH (code);
+ register int length = sizeof (struct rtx_def)
+ + (nelts - 1) * sizeof (rtunion);
+
+ /* This function is called more than any other in GCC, so we
+ manipulate the obstack directly.
+
+ Even though rtx objects are word aligned, we may be sharing
+ an obstack with tree nodes, which may have to be double-word
+ aligned. So align our length to the alignment mask in the
+ obstack. */
+
+ length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
+
+ if (ob->chunk_limit - ob->next_free < length)
+ _obstack_newchunk (ob, length);
+ rt = (rtx)ob->object_base;
+ ob->next_free += length;
+ ob->object_base = ob->next_free;
+
+ /* We want to clear everything up to the FLD array. Normally,
+ this is one int, but we don't want to assume that and it
+ isn't very portable anyway; this is. */
+
+ memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
+ }
PUT_CODE (rt, code);
-
return rt;
}
rtx_free (x)
rtx x;
{
- obstack_free (rtl_obstack, x);
+ if (!ggc_p)
+ obstack_free (rtl_obstack, x);
}
\f
/* Create a new copy of an rtx.
if (jump_opt_dump)
dump_rtl (".jump", decl, print_rtl, insns);
+ if (ggc_p)
+ ggc_collect ();
+
/* Perform common subexpression elimination.
Nonzero value from `cse_main' means that jumps were simplified
and some code may now be unreachable, so do
print_rtl_graph_with_bb (dump_base_name, ".addressof", insns);
}
+ if (ggc_p)
+ ggc_collect ();
+
/* Perform global cse. */
if (optimize > 0 && flag_gcse)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".gcse", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
/* Move constant computations out of loops. */
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".loop", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
if (optimize > 0)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".cse2", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".bp", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
/* We are no longer anticipating cse in this function, at least. */
print_rtl_graph_with_bb (dump_base_name, ".flow", insns);
}
+ if (ggc_p)
+ ggc_collect ();
+
/* The first life analysis pass has finished. From now on we can not
generate any new pseudos. */
no_new_pseudos = 1;
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".combine", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
/* Register allocation pre-pass, to reduce number of moves
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".regmove", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
/* Print function header into sched dump now
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".sched", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
/* Determine if the current function is a leaf before running reload
print_rtl_graph_with_bb (dump_base_name, ".lreg", insns);
}
+ if (ggc_p)
+ ggc_collect ();
+
if (global_reg_dump)
open_dump_file (".greg", decl_printable_name (decl, 2));
if (failure)
goto exit_rest_of_compilation;
+ if (ggc_p)
+ ggc_collect ();
+
/* Do a very simple CSE pass over just the hard registers. */
if (optimize > 0)
reload_cse_regs (insns);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
});
+
+ if (ggc_p)
+ ggc_collect ();
}
flow2_completed = 1;
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".sched2", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
}
#ifdef LEAF_REGISTERS
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".mach", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
#endif
/* If a scheduling pass for delayed branches is to be done,
print_rtl_graph_with_bb (dump_base_name, ".dbr", insns);
}
}
+
+ if (ggc_p)
+ ggc_collect ();
#endif
/* Shorten branches. */
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".stack", insns);
}
+
+ if (ggc_p)
+ ggc_collect ();
#endif
/* Now turn the rtl into assembler code. */
regset_release_memory ();
});
+ if (ggc_p)
+ ggc_collect ();
+
/* Write DBX symbols if requested */
/* Note that for those inline functions where we don't initially
if (! DECL_DEFER_OUTPUT (decl))
free_after_compilation (current_function);
+ current_function = 0;
+
+ ggc_collect ();
+
/* The parsing time is all the time spent in yyparse
*except* what is spent in this function. */
push_obstacks (current, saveable)
struct obstack *current, *saveable;
{
- struct obstack_stack *p
- = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
+ struct obstack_stack *p;
+
+ if (ggc_p)
+ return;
+
+ p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
(sizeof (struct obstack_stack)));
p->current = current_obstack;
void
push_obstacks_nochange ()
{
- struct obstack_stack *p
- = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
+ struct obstack_stack *p;
+
+ if (ggc_p)
+ return;
+
+ p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
(sizeof (struct obstack_stack)));
p->current = current_obstack;
void
pop_obstacks ()
{
- struct obstack_stack *p = obstack_stack;
+ struct obstack_stack *p;
+
+ if (ggc_p)
+ return;
+
+ p = obstack_stack;
obstack_stack = p->next;
current_obstack = p->current;
abort ();
}
- t = (tree) obstack_alloc (obstack, length);
- bzero ((PTR) t, length);
+ if (ggc_p)
+ t = ggc_alloc_tree (length);
+ else
+ {
+ t = (tree) obstack_alloc (obstack, length);
+ bzero ((PTR) t, length);
+ }
#ifdef GATHER_STATISTICS
tree_node_counts[(int)kind]++;
length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
}
- t = (tree) obstack_alloc (current_obstack, length);
- memcpy (t, node, length);
+ if (ggc_p)
+ t = ggc_alloc_tree (length);
+ else
+ {
+ t = (tree) obstack_alloc (current_obstack, length);
+ memcpy (t, node, length);
+ }
/* EXPR_WITH_FILE_LOCATION must keep filename info stored in TREE_CHAIN */
if (TREE_CODE (node) != EXPR_WITH_FILE_LOCATION)
id_string_size += len;
#endif
- IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);
+ if (ggc_p)
+ IDENTIFIER_POINTER (idp) = ggc_alloc_string (text, len);
+ else
+ IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);
TREE_CHAIN (idp) = hash_table[hi];
hash_table[hi] = idp;
register tree s = make_node (STRING_CST);
TREE_STRING_LENGTH (s) = len;
- TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, len);
+ if (ggc_p)
+ TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
+ else
+ TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, len);
return s;
}
tree_node_sizes[(int)vec_kind] += length;
#endif
- t = (tree) obstack_alloc (obstack, length);
- bzero ((PTR) t, length);
+ if (ggc_p)
+ t = ggc_alloc_tree (length);
+ else
+ {
+ t = (tree) obstack_alloc (obstack, length);
+ bzero ((PTR) t, length);
+ }
TREE_SET_CODE (t, TREE_VEC);
TREE_VEC_LENGTH (t) = len;
#if 0
register tree node = make_node (TREE_LIST);
#else
- register int i;
- register tree node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
+ register tree node;
+
+ if (ggc_p)
+ node = ggc_alloc_tree (sizeof (struct tree_list));
+ else
+ {
+ node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
+ bzero (node, sizeof (struct tree_common));
+ }
+
#ifdef GATHER_STATISTICS
tree_node_counts[(int)x_kind]++;
tree_node_sizes[(int)x_kind] += sizeof (struct tree_list);
#endif
- for (i = (sizeof (struct tree_common) / sizeof (int)) - 1; i >= 0; i--)
- ((int *) node)[i] = 0;
TREE_SET_CODE (node, TREE_LIST);
if (current_obstack == &permanent_obstack)
length = sizeof (struct tree_exp);
- t = (tree) obstack_alloc (obstack, length);
+ if (ggc_p)
+ t = ggc_alloc_tree (length);
+ else
+ t = (tree) obstack_alloc (obstack, length);
bzero ((PTR) t, length);
#ifdef GATHER_STATISTICS
t1 = type_hash_lookup (hashcode, type);
if (t1 != 0)
{
- obstack_free (TYPE_OBSTACK (type), type);
+ if (!ggc_p)
+ obstack_free (TYPE_OBSTACK (type), type);
#ifdef GATHER_STATISTICS
tree_node_counts[(int)t_kind]--;
tree_node_sizes[(int)t_kind] -= sizeof (struct tree_type);