summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog50
-rw-r--r--gcc/Makefile.in15
-rw-r--r--gcc/emit-rtl.c37
-rw-r--r--gcc/except.c76
-rw-r--r--gcc/function.c119
-rw-r--r--gcc/function.h3
-rw-r--r--gcc/ggc-callbacks.c9
-rw-r--r--gcc/ggc.h25
-rw-r--r--gcc/optabs.c17
-rw-r--r--gcc/stmt.c140
-rw-r--r--gcc/toplev.c1
-rw-r--r--gcc/tree.c62
-rw-r--r--gcc/varasm.c25
13 files changed, 544 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a80c0e8d0ba..f9b2e2579fc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,53 @@
+Sat Sep 4 19:26:25 1999 Richard Henderson <rth@cygnus.com>
+ Bernd Schmidt <bernds@cygnus.co.uk>
+ Mark Mitchell <mark@codesourcery.com>
+
+ * Makefile.in (tree.o): Depend on ggc.h.
+ (varasm.o): Likewise.
+ (function.o): Likewise.
+ (stmt.o): Likewise.
+ (except.o): Likewise.
+ (optabs.o): Likewise.
+ (emit-rtl.o): Likewise.
+ * emit-rtl.c: Include ggc.h.
+ (sequence_element_free_list): Remove, and all references.
+ (mark_sequence): New functions.
+ (mark_emit_state): New function.
+ * except.c: Include ggc.h.
+ (mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
+ (mark_tree_label_node): New functions.
+ (mark_eh_state): New function.
+ * function.c: Include ggc.h.
+ (mark_temp_slot, mark_function_chain): New functions.
+ (mark_function_state): New function.
+ (init_function_once): New function.
+ * function.h (init_function_once): New function.
+ * ggc-callbacks.c (lang_mark_false_label_stack): New function.
+ * ggc.h (label_node): Declare.
+ (eh_status, emit_status, stmt_status, varasm_status): Likewise.
+ (lang_mark_false_label_stack): New function.
+ (mark_temp_slot): Remove declaration.
+ (mark_function_chain): Likewise.
+ (mark_eh_state): Adjust prototype.
+ (mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
+ Likewise.
+ * optabs.c: Include ggc.h.
+ (mark_optab): New function.
+ (init_optabs): Add gc roots.
+ * stmt.c: Include ggc.h.
+ (mark_cond_nesting, mark_loop_nesting): New functions.
+ (mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
+ (mark_stmt_state): New function.
+ * toplev.c (compile_file): Call init_function_once.
+ * tree.c: Include ggc.h.
+ (type_hash): Move declaration earlier in file.
+ (TYPE_HASH_SIZE, type_hash_table): Likewise.
+ (init_obstacks): Add gc roots.
+ (mark_type_hash): New function.
+ * varasm.c: Include ggc.h.
+ (mark_pool_constant): New function.
+ (mark_varasm_state): New function.
+
Sat Sep 4 22:28:56 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* ggc-simple.c (ggc_root, ggc_collect): Wrap prototype with PROTO.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a358df2cd4a..77f2b02462b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1450,7 +1450,8 @@ prefix.o: prefix.c $(CONFIG_H) system.h Makefile prefix.h
convert.o: convert.c $(CONFIG_H) $(TREE_H) flags.h convert.h toplev.h
-tree.o : tree.c $(CONFIG_H) system.h $(TREE_H) flags.h function.h toplev.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)
stor-layout.o : stor-layout.c $(CONFIG_H) system.h $(TREE_H) flags.h \
function.h $(EXPR_H) $(RTL_H) toplev.h
@@ -1473,16 +1474,16 @@ errors.o : errors.c $(CONFIG_H) system.h errors.h
varasm.o : varasm.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h \
function.h defaults.h $(EXPR_H) hard-reg-set.h $(REGS_H) \
- xcoffout.h output.h c-pragma.h toplev.h dbxout.h sdbout.h
+ xcoffout.h output.h c-pragma.h toplev.h dbxout.h sdbout.h ggc.h
function.o : function.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
function.h insn-flags.h insn-codes.h $(EXPR_H) $(REGS_H) hard-reg-set.h \
- insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h
+ insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h ggc.h
stmt.o : stmt.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h function.h \
insn-flags.h insn-config.h insn-codes.h hard-reg-set.h $(EXPR_H) except.h \
- loop.h $(RECOG_H) toplev.h output.h varray.h
+ loop.h $(RECOG_H) toplev.h output.h varray.h ggc.h
except.o : except.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
function.h insn-flags.h $(EXPR_H) $(REGS_H) hard-reg-set.h \
- insn-config.h $(RECOG_H) output.h except.h toplev.h intl.h
+ insn-config.h $(RECOG_H) output.h except.h toplev.h intl.h ggc.h
expr.o : expr.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h function.h \
$(REGS_H) insn-flags.h insn-codes.h $(EXPR_H) insn-config.h $(RECOG_H) \
output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h except.h
@@ -1499,7 +1500,7 @@ explow.o : explow.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
insn-codes.h toplev.h
optabs.o : optabs.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) reload.h \
- toplev.h
+ toplev.h ggc.h
dbxout.o : dbxout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h $(REGS_H) \
insn-config.h reload.h gstab.h xcoffout.h defaults.h output.h dbxout.h \
toplev.h
@@ -1515,7 +1516,7 @@ dwarf2out.o : dwarf2out.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) dwarf2.h \
xcoffout.o : xcoffout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) xcoffout.h \
flags.h toplev.h output.h dbxout.h
emit-rtl.o : emit-rtl.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
- function.h $(REGS_H) insn-config.h $(RECOG_H) real.h \
+ function.h $(REGS_H) insn-config.h $(RECOG_H) real.h ggc.h \
$(EXPR_H) $(srcdir)/../include/obstack.h hard-reg-set.h bitmap.h toplev.h
real.o : real.c $(CONFIG_H) system.h $(TREE_H) toplev.h
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index fd04427edbb..a781e2da79d 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -49,6 +49,7 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "obstack.h"
#include "bitmap.h"
+#include "ggc.h"
/* Commonly used modes. */
@@ -187,6 +188,7 @@ static rtx free_insn;
static rtx make_jump_insn_raw PROTO((rtx));
static rtx make_call_insn_raw PROTO((rtx));
static rtx find_line_note PROTO((rtx));
+static void mark_sequence_stack PROTO((struct sequence_stack *));
rtx
gen_rtx_CONST_INT (mode, arg)
@@ -3467,6 +3469,41 @@ init_emit ()
#endif
}
+/* Mark SS for GC. */
+
+static void
+mark_sequence_stack (ss)
+ struct sequence_stack *ss;
+{
+ while (ss)
+ {
+ ggc_mark_rtx (ss->first);
+ ggc_mark_tree (ss->sequence_rtl_expr);
+ ss = ss->next;
+ }
+}
+
+/* Mark ES for GC. */
+
+void
+mark_emit_state (es)
+ struct emit_status *es;
+{
+ rtx *r;
+ int i;
+
+ if (es == 0)
+ return;
+
+ for (i = es->regno_pointer_flag_length, r = es->x_regno_reg_rtx;
+ i > 0; --i, ++r)
+ ggc_mark_rtx (*r);
+
+ mark_sequence_stack (es->sequence_stack);
+ ggc_mark_tree (es->sequence_rtl_expr);
+ ggc_mark_rtx (es->x_first_insn);
+}
+
/* Create some permanent unique rtl objects shared between all functions.
LINE_NUMBERS is nonzero if line numbers are to be generated. */
diff --git a/gcc/except.c b/gcc/except.c
index 6cc84659032..0a7b9a944df 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -408,6 +408,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "intl.h"
#include "obstack.h"
+#include "ggc.h"
/* One to use setjmp/longjmp method of generating code for exception
handling. */
@@ -467,6 +468,10 @@ static void set_insn_eh_region PROTO((rtx *, int));
#ifdef DONT_USE_BUILTIN_SETJMP
static void jumpif_rtx PROTO((rtx, rtx));
#endif
+static void mark_eh_node PROTO((struct eh_node *));
+static void mark_eh_stack PROTO((struct eh_stack *));
+static void mark_eh_queue PROTO((struct eh_queue *));
+static void mark_tree_label_node PROTO ((struct label_node *));
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
@@ -2333,7 +2338,76 @@ check_exception_handler_labels ()
}
}
-
+
+/* Mark the children of NODE for GC. */
+
+static void
+mark_eh_node (node)
+ struct eh_node *node;
+{
+ while (node)
+ {
+ if (node->entry)
+ {
+ ggc_mark_rtx (node->entry->outer_context);
+ ggc_mark_rtx (node->entry->exception_handler_label);
+ ggc_mark_tree (node->entry->finalization);
+ }
+ node = node ->chain;
+ }
+}
+
+/* Mark S for GC. */
+
+static void
+mark_eh_stack (s)
+ struct eh_stack *s;
+{
+ if (s)
+ mark_eh_node (s->top);
+}
+
+/* Mark Q for GC. */
+
+static void
+mark_eh_queue (q)
+ struct eh_queue *q;
+{
+ if (q)
+ mark_eh_node (q->head);
+}
+
+/* Mark NODE for GC. A label_node contains a union containing either
+ a tree or an rtx. This label_node will contain a tree. */
+
+static void
+mark_tree_label_node (node)
+ struct label_node *node;
+{
+ while (node)
+ {
+ ggc_mark_tree (node->u.tlabel);
+ node = node->chain;
+ }
+}
+
+/* Mark EH for GC. */
+
+void
+mark_eh_state (eh)
+ struct eh_status *eh;
+{
+ mark_eh_stack (&eh->x_ehstack);
+ mark_eh_queue (&eh->x_ehqueue);
+ ggc_mark_rtx (eh->x_catch_clauses);
+
+ lang_mark_false_label_stack (eh->x_false_label_stack);
+ mark_tree_label_node (eh->x_caught_return_label_stack);
+
+ ggc_mark_tree (eh->x_protect_list);
+ ggc_mark_rtx (eh->ehc);
+}
+
/* This group of functions initializes the exception handling data
structures at the start of the compilation, initializes the data
structures at the start of a function, and saves and restores the
diff --git a/gcc/function.c b/gcc/function.c
index cb474b2308a..b0c27256dab 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -57,6 +57,7 @@ Boston, MA 02111-1307, USA. */
#include "obstack.h"
#include "toplev.h"
#include "hash.h"
+#include "ggc.h"
#ifndef TRAMPOLINE_ALIGNMENT
#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
@@ -272,6 +273,9 @@ static unsigned long insns_for_mem_hash PROTO ((hash_table_key));
static boolean insns_for_mem_comp PROTO ((hash_table_key, hash_table_key));
static int insns_for_mem_walk PROTO ((rtx *, void *));
static void compute_insns_for_mem PROTO ((rtx, rtx, struct hash_table *));
+static void mark_temp_slot PROTO ((struct temp_slot *));
+static void mark_function_state PROTO ((struct function *));
+static void mark_function_chain PROTO ((void *));
/* Pointer to chain of `struct function' for containing functions. */
@@ -5630,7 +5634,7 @@ init_function_start (subr, filename, line)
/* Remember this function for later. */
current_function->next_global = all_functions;
all_functions = current_function;
-
+
current_function_name = (*decl_printable_name) (subr, 2);
/* Nonzero if this is a nested function that uses a static chain. */
@@ -6637,3 +6641,116 @@ reposition_prologue_and_epilogue_notes (f)
}
#endif /* HAVE_prologue or HAVE_epilogue */
}
+
+/* Mark T for GC. */
+
+static void
+mark_temp_slot (t)
+ struct temp_slot *t;
+{
+ while (t)
+ {
+ ggc_mark_rtx (t->slot);
+ ggc_mark_rtx (t->address);
+ ggc_mark_tree (t->rtl_expr);
+
+ t = t->next;
+ }
+}
+
+/* Mark P for GC. */
+
+static void
+mark_function_state (p)
+ struct function *p;
+{
+ int i;
+ rtx *r;
+
+ if (p == 0)
+ return;
+
+ ggc_mark_rtx (p->arg_offset_rtx);
+
+ for (i = p->x_max_parm_reg, r = p->x_parm_reg_stack_loc;
+ i > 0; --i, ++r)
+ ggc_mark_rtx (*r);
+
+ ggc_mark_rtx (p->return_rtx);
+ ggc_mark_rtx (p->x_cleanup_label);
+ ggc_mark_rtx (p->x_return_label);
+ ggc_mark_rtx (p->x_save_expr_regs);
+ ggc_mark_rtx (p->x_stack_slot_list);
+ ggc_mark_rtx (p->x_parm_birth_insn);
+ ggc_mark_rtx (p->x_tail_recursion_label);
+ ggc_mark_rtx (p->x_tail_recursion_reentry);
+ ggc_mark_rtx (p->internal_arg_pointer);
+ ggc_mark_rtx (p->x_arg_pointer_save_area);
+ ggc_mark_tree (p->x_rtl_expr_chain);
+ ggc_mark_rtx (p->x_last_parm_insn);
+ ggc_mark_tree (p->x_context_display);
+ ggc_mark_tree (p->x_trampoline_list);
+ ggc_mark_rtx (p->epilogue_delay_list);
+
+ mark_temp_slot (p->x_temp_slots);
+
+ {
+ struct var_refs_queue *q = p->fixup_var_refs_queue;
+ while (q)
+ {
+ ggc_mark_rtx (q->modified);
+ q = q->next;
+ }
+ }
+
+ ggc_mark_rtx (p->x_nonlocal_goto_handler_slots);
+ ggc_mark_rtx (p->x_nonlocal_goto_stack_level);
+ ggc_mark_tree (p->x_nonlocal_labels);
+}
+
+/* Mark the function chain ARG (which is really a struct function **)
+ for GC. */
+
+static void
+mark_function_chain (arg)
+ void *arg;
+{
+ struct function *f = *(struct function **) arg;
+
+ for (; f; f = f->next_global)
+ {
+ if (f->can_garbage_collect)
+ continue;
+
+ ggc_mark_tree (f->decl);
+
+ mark_function_state (f);
+ mark_stmt_state (f->stmt);
+ mark_eh_state (f->eh);
+ mark_emit_state (f->emit);
+ mark_varasm_state (f->varasm);
+
+ ggc_mark_rtx (f->expr->x_saveregs_value);
+ ggc_mark_rtx (f->expr->x_apply_args_value);
+ ggc_mark_rtx (f->expr->x_forced_labels);
+
+ if (mark_machine_status)
+ (*mark_machine_status) (f);
+ if (mark_lang_status)
+ (*mark_lang_status) (f);
+
+ if (f->original_arg_vector)
+ ggc_mark_rtvec ((rtvec) f->original_arg_vector);
+ if (f->original_decl_initial)
+ ggc_mark_tree (f->original_decl_initial);
+ }
+}
+
+/* Called once, at initialization, to initialize function.c. */
+
+void
+init_function_once ()
+{
+ ggc_add_root (&all_functions, 1, sizeof all_functions,
+ mark_function_chain);
+}
diff --git a/gcc/function.h b/gcc/function.h
index 0b6eb66b68d..966b3f74e47 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -558,6 +558,9 @@ extern rtx get_first_block_beg PROTO((void));
extern void init_virtual_regs PROTO((struct emit_status *));
+/* Called once, at initialization, to initialize function.c. */
+extern void init_function_once PROTO((void));
+
#ifdef rtx
#undef rtx
#endif
diff --git a/gcc/ggc-callbacks.c b/gcc/ggc-callbacks.c
index 851f8dd0a26..1b19579e914 100644
--- a/gcc/ggc-callbacks.c
+++ b/gcc/ggc-callbacks.c
@@ -41,3 +41,12 @@ lang_cleanup_tree (t)
only included in compilers for languages that don't support GC. */
abort ();
}
+
+void
+lang_mark_false_label_stack (l)
+ struct label_node *l ATTRIBUTE_UNUSED;
+{
+ /* If this function is called, we are doing GC. But, this file is
+ only included in compilers for languages that don't support GC. */
+ abort ();
+}
diff --git a/gcc/ggc.h b/gcc/ggc.h
index bb0be13623e..6967900cb8a 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -23,6 +23,16 @@
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
+/* 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
+ just forward-declare them here. */
+struct label_node;
+struct eh_status;
+struct emit_status;
+struct stmt_status;
+struct varasm_status;
+
/* Startup */
extern void init_ggc PROTO ((void));
@@ -61,12 +71,15 @@ void lang_mark_tree PROTO ((union tree_node *));
/* And similarly to free that data when the tree node is released. */
void lang_cleanup_tree PROTO ((union tree_node *));
+/* The FALSE_LABEL_STACK, declared in except.h, has
+ language-dependent semantics. Each front-end should define this
+ function appropriately. */
+void lang_mark_false_label_stack PROTO ((struct label_node *));
+
/* Mark functions for various structs scattered about. */
-void mark_temp_slot PROTO ((void *));
-void mark_function_chain PROTO ((void *));
-void mark_eh_state PROTO ((void *));
-void mark_stmt_state PROTO ((void *));
-void mark_emit_state PROTO ((void *));
-void mark_varasm_state PROTO ((void *));
+void mark_eh_state PROTO ((struct eh_status *));
+void mark_stmt_state PROTO ((struct stmt_status *));
+void mark_emit_state PROTO ((struct emit_status *));
+void mark_varasm_state PROTO ((struct varasm_status *));
void mark_optab PROTO ((void *));
diff --git a/gcc/optabs.c b/gcc/optabs.c
index ae6a6ff999b..d82eb2ee6fa 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "recog.h"
#include "reload.h"
+#include "ggc.h"
/* Each optab contains info on how this target machine
can perform a particular operation
@@ -4342,6 +4343,18 @@ init_floating_libfuncs (optable, opname, suffix)
init_libfuncs (optable, SFmode, TFmode, opname, suffix);
}
+/* Mark ARG (which is really an OPTAB *) for GC. */
+
+void
+mark_optab (arg)
+ void *arg;
+{
+ optab o = *(optab *) arg;
+ int i;
+
+ for (i = 0; i < NUM_MACHINE_MODES; ++i)
+ ggc_mark_rtx (o->handlers[i].libfunc);
+}
/* Call this once to initialize the contents of the optabs
appropriately for the current target machine. */
@@ -4679,6 +4692,10 @@ init_optabs ()
/* Allow the target to add more libcalls or rename some, etc. */
INIT_TARGET_OPTABS;
#endif
+
+ /* Add these GC roots. */
+ ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab);
+ ggc_add_rtx_root (libfunc_table, LTI_MAX);
}
#ifdef BROKEN_LDEXP
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 255d635fbbb..a9f859237c2 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -52,6 +52,7 @@ Boston, MA 02111-1307, USA. */
#include "machmode.h"
#include "toplev.h"
#include "output.h"
+#include "ggc.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -425,6 +426,12 @@ static void emit_jump_if_reachable PROTO((rtx));
static void emit_case_nodes PROTO((rtx, case_node_ptr, rtx, tree));
static int add_case_node PROTO((tree, tree, tree, tree *));
static struct case_node *case_tree2list PROTO((case_node *, case_node *));
+static void mark_cond_nesting PROTO((struct nesting *));
+static void mark_loop_nesting PROTO((struct nesting *));
+static void mark_block_nesting PROTO((struct nesting *));
+static void mark_case_nesting PROTO((struct nesting *));
+static void mark_goto_fixup PROTO((struct goto_fixup *));
+
void
using_eh_for_cleanups ()
@@ -432,6 +439,139 @@ using_eh_for_cleanups ()
using_eh_for_cleanups_p = 1;
}
+/* Mark N (known to be a cond-nesting) for GC. */
+
+static void
+mark_cond_nesting (n)
+ struct nesting *n;
+{
+ while (n)
+ {
+ ggc_mark_rtx (n->exit_label);
+ ggc_mark_rtx (n->data.cond.endif_label);
+ ggc_mark_rtx (n->data.cond.next_label);
+
+ n = n->next;
+ }
+}
+
+/* Mark N (known to be a loop-nesting) for GC. */
+
+static void
+mark_loop_nesting (n)
+ struct nesting *n;
+{
+
+ while (n)
+ {
+ ggc_mark_rtx (n->exit_label);
+ ggc_mark_rtx (n->data.loop.start_label);
+ ggc_mark_rtx (n->data.loop.end_label);
+ ggc_mark_rtx (n->data.loop.alt_end_label);
+ ggc_mark_rtx (n->data.loop.continue_label);
+
+ n = n->next;
+ }
+}
+
+/* Mark N (known to be a block-nesting) for GC. */
+
+static void
+mark_block_nesting (n)
+ struct nesting *n;
+{
+ while (n)
+ {
+ struct label_chain *l;
+
+ ggc_mark_rtx (n->exit_label);
+ ggc_mark_rtx (n->data.block.stack_level);
+ ggc_mark_rtx (n->data.block.first_insn);
+ ggc_mark_tree (n->data.block.cleanups);
+ ggc_mark_tree (n->data.block.outer_cleanups);
+
+ for (l = n->data.block.label_chain; l != NULL; l = l->next)
+ ggc_mark_tree (l->label);
+
+ ggc_mark_rtx (n->data.block.last_unconditional_cleanup);
+
+ /* ??? cleanup_ptr never points outside the stack, does it? */
+
+ n = n->next;
+ }
+}
+
+/* Mark N (known to be a case-nesting) for GC. */
+
+static void
+mark_case_nesting (n)
+ struct nesting *n;
+{
+ while (n)
+ {
+ struct case_node *node;
+
+ ggc_mark_rtx (n->exit_label);
+ ggc_mark_rtx (n->data.case_stmt.start);
+
+ node = n->data.case_stmt.case_list;
+ while (node)
+ {
+ ggc_mark_tree (node->low);
+ ggc_mark_tree (node->high);
+ ggc_mark_tree (node->code_label);
+ node = node->right;
+ }
+
+ ggc_mark_tree (n->data.case_stmt.default_label);
+ ggc_mark_tree (n->data.case_stmt.index_expr);
+ ggc_mark_tree (n->data.case_stmt.nominal_type);
+
+ n = n->next;
+ }
+}
+
+/* Mark G for GC. */
+
+static void
+mark_goto_fixup (g)
+ struct goto_fixup *g;
+{
+ while (g)
+ {
+ ggc_mark_rtx (g->before_jump);
+ ggc_mark_tree (g->target);
+ ggc_mark_tree (g->context);
+ ggc_mark_rtx (g->target_rtl);
+ ggc_mark_rtx (g->stack_level);
+ ggc_mark_tree (g->cleanup_list_list);
+
+ g = g->next;
+ }
+}
+
+/* Mark P for GC. */
+
+void
+mark_stmt_state (p)
+ struct stmt_status *p;
+{
+ if (p == 0)
+ return;
+
+ mark_block_nesting (p->x_block_stack);
+ mark_cond_nesting (p->x_cond_stack);
+ mark_loop_nesting (p->x_loop_stack);
+ mark_case_nesting (p->x_case_stack);
+
+ ggc_mark_tree (p->x_last_expr_type);
+ /* last_epxr_value is only valid if last_expr_type is nonzero. */
+ if (p->x_last_expr_type)
+ ggc_mark_rtx (p->x_last_expr_value);
+
+ mark_goto_fixup (p->x_goto_fixup_chain);
+}
+
void
init_stmt ()
{
diff --git a/gcc/toplev.c b/gcc/toplev.c
index e654146e2c4..eaa013eda78 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2935,6 +2935,7 @@ compile_file (name)
init_loop ();
init_reload ();
init_alias_once ();
+ init_function_once ();
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them. */
diff --git a/gcc/tree.c b/gcc/tree.c
index e280190fcd5..1d0f27377da 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
#include "obstack.h"
#include "toplev.h"
+#include "ggc.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -247,9 +248,30 @@ int (*lang_get_alias_set) PROTO((tree));
codes are made. */
#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
+/* Each hash table slot is a bucket containing a chain
+ of these structures. */
+
+struct type_hash
+{
+ struct type_hash *next; /* Next structure in the bucket. */
+ int hashcode; /* Hash code of this type. */
+ tree type; /* The type recorded here. */
+};
+
+/* Now here is the hash table. When recording a type, it is added
+ to the slot whose index is the hash code mod the table size.
+ Note that the hash table is used for several kinds of types
+ (function types, array types and array index range types, for now).
+ While all these live in the same table, they are completely independent,
+ and the hash code is computed differently for each of these. */
+
+#define TYPE_HASH_SIZE 59
+struct type_hash *type_hash_table[TYPE_HASH_SIZE];
+
static void set_type_quals PROTO((tree, int));
static void append_random_chars PROTO((char *));
static void build_real_from_int_cst_1 PROTO((PTR));
+static void mark_type_hash PROTO ((void *));
void gcc_obstack_init ();
@@ -284,6 +306,11 @@ init_obstacks ()
/* Init the hash table of identifiers. */
bzero ((char *) hash_table, sizeof hash_table);
+
+ ggc_add_tree_root (hash_table, MAX_HASH_TABLE);
+ ggc_add_root (type_hash_table, TYPE_HASH_SIZE,
+ sizeof(struct type_hash *),
+ mark_type_hash);
}
void
@@ -3587,26 +3614,6 @@ build_type_copy (type)
/* Hashing of types so that we don't make duplicates.
The entry point is `type_hash_canon'. */
-/* Each hash table slot is a bucket containing a chain
- of these structures. */
-
-struct type_hash
-{
- struct type_hash *next; /* Next structure in the bucket. */
- int hashcode; /* Hash code of this type. */
- tree type; /* The type recorded here. */
-};
-
-/* Now here is the hash table. When recording a type, it is added
- to the slot whose index is the hash code mod the table size.
- Note that the hash table is used for several kinds of types
- (function types, array types and array index range types, for now).
- While all these live in the same table, they are completely independent,
- and the hash code is computed differently for each of these. */
-
-#define TYPE_HASH_SIZE 59
-struct type_hash *type_hash_table[TYPE_HASH_SIZE];
-
/* Compute a hash code for a list of types (chain of TREE_LIST nodes
with types in the TREE_VALUE slots), by adding the hash codes
of the individual types. */
@@ -3714,6 +3721,21 @@ type_hash_canon (hashcode, type)
return type;
}
+/* Mark ARG (which is really a struct type_hash **) for GC. */
+
+static void
+mark_type_hash (arg)
+ void *arg;
+{
+ struct type_hash *t = *(struct type_hash **) arg;
+
+ while (t)
+ {
+ ggc_mark_tree (t->type);
+ t = t->next;
+ }
+}
+
/* Compute a hash code for a list of attributes (chain of TREE_LIST nodes
with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots),
by adding the hash codes of the individual attributes. */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 3f25a982929..33b16fe87bd 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA. */
#include "obstack.h"
#include "c-pragma.h"
+#include "ggc.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h"
@@ -186,6 +187,7 @@ static void asm_output_bss PROTO((FILE *, tree, char *, int, int));
static void asm_output_aligned_bss PROTO((FILE *, tree, char *, int, int));
#endif
#endif /* BSS_SECTION_ASM_OP */
+static void mark_pool_constant PROTO((struct pool_constant *));
static enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
@@ -3186,6 +3188,29 @@ init_varasm_status (f)
p->x_const_double_chain = 0;
}
+/* Mark PC for GC. */
+
+static void
+mark_pool_constant (pc)
+ struct pool_constant *pc;
+{
+ while (pc)
+ {
+ ggc_mark_rtx (pc->constant);
+ pc = pc->next;
+ }
+}
+
+/* Mark P for GC. */
+
+void
+mark_varasm_state (p)
+ struct varasm_status *p;
+{
+ mark_pool_constant (p->x_first_pool);
+ ggc_mark_rtx (p->x_const_double_chain);
+}
+
/* Clear out all parts of our state in F that can safely be discarded
after the function has been compiled. */
void