ggc-common.c revision 96489
12089Ssos/* Simple garbage collection for the GNU compiler.
216565Ssos   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
32089Ssos
42089SsosThis file is part of GCC.
52089Ssos
62089SsosGCC is free software; you can redistribute it and/or modify it under
72089Ssosthe terms of the GNU General Public License as published by the Free
82089SsosSoftware Foundation; either version 2, or (at your option) any later
95994Ssosversion.
105994Ssos
112089SsosGCC is distributed in the hope that it will be useful, but WITHOUT ANY
122089SsosWARRANTY; without even the implied warranty of MERCHANTABILITY or
132089SsosFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
142089Ssosfor more details.
1597748Sschweikh
162089SsosYou should have received a copy of the GNU General Public License
172089Ssosalong with GCC; see the file COPYING.  If not, write to the Free
182089SsosSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
192089Ssos02111-1307, USA.  */
202089Ssos
212089Ssos/* Generic garbage collection (GC) functions and data, not specific to
222089Ssos   any particular GC implementation.  */
232089Ssos
242089Ssos#include "config.h"
252089Ssos#include "system.h"
262089Ssos#include "rtl.h"
272089Ssos#include "tree.h"
282089Ssos#include "tm_p.h"
2930764Scharnier#include "hash.h"
3030764Scharnier#include "hashtab.h"
3150479Speter#include "varray.h"
3230764Scharnier#include "ggc.h"
3330764Scharnier
342089Ssos/* Statistics about the allocation.  */
3530764Scharnierstatic ggc_statistics *ggc_stats;
3655849Syokota
372089Ssos/* The FALSE_LABEL_STACK, declared in except.h, has language-dependent
3823457Sbrian   semantics.  If a front-end needs to mark the false label stack, it
3930764Scharnier   should set this pointer to a non-NULL value.  Otherwise, no marking
4023702Speter   will be done.  */
4166834Sphkvoid (*lang_mark_false_label_stack) PARAMS ((struct label_node *));
4266834Sphk
432089Ssos/* Trees that have been marked, but whose children still need marking.  */
4475344Ssobomaxvarray_type ggc_pending_trees;
4575344Ssobomax
462089Ssosstatic void ggc_mark_rtx_children_1 PARAMS ((rtx));
4723457Sbrianstatic void ggc_mark_rtx_ptr PARAMS ((void *));
482089Ssosstatic void ggc_mark_tree_ptr PARAMS ((void *));
4971642Ssobomaxstatic void ggc_mark_rtx_varray_ptr PARAMS ((void *));
5071642Ssobomaxstatic void ggc_mark_tree_varray_ptr PARAMS ((void *));
5171642Ssobomaxstatic void ggc_mark_tree_hash_table_ptr PARAMS ((void *));
5271642Ssobomaxstatic int ggc_htab_delete PARAMS ((void **, void *));
5376845Ssobomaxstatic void ggc_mark_trees PARAMS ((void));
5476845Ssobomaxstatic bool ggc_mark_tree_hash_table_entry PARAMS ((struct hash_entry *,
5576845Ssobomax						    hash_table_key));
5676845Ssobomax
5776845Ssobomax/* Maintain global roots that are preserved during GC.  */
582089Ssos
592089Ssos/* Global roots that are preserved during calls to gc.  */
602089Ssos
612089Ssosstruct ggc_root
622089Ssos{
636628Ssos  struct ggc_root *next;
642089Ssos  void *base;
656047Ssos  int nelt;
6671642Ssobomax  int size;
6771642Ssobomax  void (*cb) PARAMS ((void *));
682089Ssos};
692089Ssos
702089Ssosstatic struct ggc_root *roots;
712089Ssos
7230764Scharnier/* Add BASE as a new garbage collection root.  It is an array of
736628Ssos   length NELT with each element SIZE bytes long.  CB is a
746628Ssos   function that will be called with a pointer to each element
7555849Syokota   of the array; it is the intention that CB call the appropriate
7677329Sdes   routine to mark gc-able memory for that element.  */
7777329Sdes
7877329Sdesvoid
7977329Sdesggc_add_root (base, nelt, size, cb)
8030764Scharnier     void *base;
816628Ssos     int nelt, size;
826628Ssos     void (*cb) PARAMS ((void *));
832089Ssos{
8475344Ssobomax  struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x));
852089Ssos
862089Ssos  x->next = roots;
872089Ssos  x->base = base;
8875344Ssobomax  x->nelt = nelt;
8975344Ssobomax  x->size = size;
9075344Ssobomax  x->cb = cb;
912089Ssos
922089Ssos  roots = x;
9392460Ssobomax}
9492460Ssobomax
952089Ssos/* Register an array of rtx as a GC root.  */
9692460Ssobomax
9792460Ssobomaxvoid
982089Ssosggc_add_rtx_root (base, nelt)
9992460Ssobomax     rtx *base;
10092460Ssobomax     int nelt;
10192460Ssobomax{
10292460Ssobomax  ggc_add_root (base, nelt, sizeof (rtx), ggc_mark_rtx_ptr);
10392460Ssobomax}
10492460Ssobomax
10592460Ssobomax/* Register an array of trees as a GC root.  */
10692460Ssobomax
10792460Ssobomaxvoid
10892460Ssobomaxggc_add_tree_root (base, nelt)
10992460Ssobomax     tree *base;
11092460Ssobomax     int nelt;
11192460Ssobomax{
11252262Sbillf  ggc_add_root (base, nelt, sizeof (tree), ggc_mark_tree_ptr);
11392460Ssobomax}
1142089Ssos
1152089Ssos/* Register a varray of rtxs as a GC root.  */
1162089Ssos
1172089Ssosvoid
1182089Ssosggc_add_rtx_varray_root (base, nelt)
11992460Ssobomax     varray_type *base;
12092460Ssobomax     int nelt;
1212089Ssos{
1222089Ssos  ggc_add_root (base, nelt, sizeof (varray_type),
12392460Ssobomax		ggc_mark_rtx_varray_ptr);
12492460Ssobomax}
12592460Ssobomax
12692460Ssobomax/* Register a varray of trees as a GC root.  */
1272089Ssos
12892460Ssobomaxvoid
1292089Ssosggc_add_tree_varray_root (base, nelt)
13030764Scharnier     varray_type *base;
1312089Ssos     int nelt;
1322089Ssos{
1332089Ssos  ggc_add_root (base, nelt, sizeof (varray_type),
13475344Ssobomax		ggc_mark_tree_varray_ptr);
1352089Ssos}
1362089Ssos
13730764Scharnier/* Register a hash table of trees as a GC root.  */
13823457Sbrian
1392089Ssosvoid
1402089Ssosggc_add_tree_hash_table_root (base, nelt)
1412089Ssos     struct hash_table **base;
1422089Ssos     int nelt;
14330764Scharnier{
14423457Sbrian  ggc_add_root (base, nelt, sizeof (struct hash_table *),
1452089Ssos		ggc_mark_tree_hash_table_ptr);
1462089Ssos}
1472089Ssos
1482089Ssos/* Remove the previously registered GC root at BASE.  */
1492089Ssos
1506628Ssosvoid
1512089Ssosggc_del_root (base)
1522089Ssos     void *base;
1532089Ssos{
1542089Ssos  struct ggc_root *x, **p;
1552089Ssos
15630764Scharnier  p = &roots, x = roots;
1572089Ssos  while (x)
1582089Ssos    {
1592089Ssos      if (x->base == base)
1602089Ssos	{
1612089Ssos	  *p = x->next;
1622089Ssos	  free (x);
1632089Ssos	  return;
1642089Ssos	}
1652089Ssos      p = &x->next;
16630764Scharnier      x = x->next;
1672089Ssos    }
1682089Ssos
1692089Ssos  abort ();
1702089Ssos}
1712089Ssos
1722089Ssos/* Add a hash table to be scanned when all roots have been processed.  We
1738857Srgrimes   delete any entry in the table that has not been marked.  */
1742089Ssos
1752089Ssosstruct d_htab_root
1762089Ssos{
1772089Ssos  struct d_htab_root *next;
1782089Ssos  htab_t htab;
1792089Ssos  ggc_htab_marked_p marked_p;
1802089Ssos  ggc_htab_mark mark;
18175344Ssobomax};
18275344Ssobomax
18375344Ssobomaxstatic struct d_htab_root *d_htab_roots;
18475344Ssobomax
18575344Ssobomax/* Add X, an htab, to a list of htabs that contain objects which are allocated
18675344Ssobomax   from GC memory.  Once all other roots are marked, we check each object in
18775344Ssobomax   the htab to see if it has already been marked.  If not, it is deleted.
18875344Ssobomax
18975344Ssobomax   MARKED_P, if specified, is a function that returns 1 if the entry is to
19075344Ssobomax   be considered as "marked".  If not present, the data structure pointed to
19175344Ssobomax   by the htab slot is tested.  This function should be supplied if some
19275344Ssobomax   other object (such as something pointed to by that object) should be tested
19375344Ssobomax   in which case the function tests whether that object (or objects) are
1948857Srgrimes   marked (using ggc_marked_p) and returns nonzero if it is.
1952089Ssos
1962089Ssos   MARK, if specified, is a function that is passed the contents of a slot
19792460Ssobomax   that has been determined to have been "marked" (via the above function)
19875344Ssobomax   and marks any other objects pointed to by that object.  For example,
19975344Ssobomax   we might have a hash table of memory attribute blocks, which are pointed
20092460Ssobomax   to by a MEM RTL but have a pointer to a DECL.  MARKED_P in that case will
20192460Ssobomax   not be specified because we want to know if the attribute block is pointed
20292460Ssobomax   to by the MEM, but MARK must be specified because if the block has been
20392460Ssobomax   marked, we need to mark the DECL.  */
20492460Ssobomax
20592460Ssobomaxvoid
2062089Ssosggc_add_deletable_htab (x, marked_p, mark)
20775344Ssobomax     PTR x;
20875344Ssobomax     ggc_htab_marked_p marked_p;
20975344Ssobomax     ggc_htab_mark mark;
21075344Ssobomax{
21175344Ssobomax  struct d_htab_root *r
21275344Ssobomax    = (struct d_htab_root *) xmalloc (sizeof (struct d_htab_root));
21375344Ssobomax
21475344Ssobomax  r->next = d_htab_roots;
21575344Ssobomax  r->htab = (htab_t) x;
21692460Ssobomax  r->marked_p = marked_p ? marked_p : ggc_marked_p;
21792460Ssobomax  r->mark = mark;
21892460Ssobomax  d_htab_roots = r;
21992460Ssobomax}
2202089Ssos
22192460Ssobomax/* Process a slot of an htab by deleting it if it has not been marked.  */
22292460Ssobomax
2232089Ssosstatic int
22475344Ssobomaxggc_htab_delete (slot, info)
2252089Ssos     void **slot;
2262089Ssos     void *info;
22775344Ssobomax{
22875344Ssobomax  struct d_htab_root *r = (struct d_htab_root *) info;
22975344Ssobomax
23075344Ssobomax  if (! (*r->marked_p) (*slot))
23175344Ssobomax    htab_clear_slot (r->htab, slot);
23275344Ssobomax  else if (r->mark)
23375344Ssobomax    (*r->mark) (*slot);
23475344Ssobomax
23575344Ssobomax  return 1;
23675344Ssobomax}
23775344Ssobomax
23875344Ssobomax/* Iterate through all registered roots and mark each element.  */
23975344Ssobomax
24075344Ssobomaxvoid
24175344Ssobomaxggc_mark_roots ()
24275344Ssobomax{
24375344Ssobomax  struct ggc_root *x;
24475344Ssobomax  struct d_htab_root *y;
24575344Ssobomax
24675344Ssobomax  VARRAY_TREE_INIT (ggc_pending_trees, 4096, "ggc_pending_trees");
24775344Ssobomax
24875344Ssobomax  for (x = roots; x != NULL; x = x->next)
24975344Ssobomax    {
25075344Ssobomax      char *elt = x->base;
25175344Ssobomax      int s = x->size, n = x->nelt;
25275344Ssobomax      void (*cb) PARAMS ((void *)) = x->cb;
25375344Ssobomax      int i;
25475344Ssobomax
25575344Ssobomax      for (i = 0; i < n; ++i, elt += s)
25675344Ssobomax	(*cb)(elt);
25775344Ssobomax    }
25875344Ssobomax
25975344Ssobomax  /* Mark all the queued up trees, and their children.  */
26075344Ssobomax  ggc_mark_trees ();
26175344Ssobomax  VARRAY_FREE (ggc_pending_trees);
26275344Ssobomax
26375344Ssobomax  /* Now scan all hash tables that have objects which are to be deleted if
26475344Ssobomax     they are not already marked.  Since these may mark more trees, we need
26575344Ssobomax     to reinitialize that varray.  */
26675344Ssobomax  VARRAY_TREE_INIT (ggc_pending_trees, 1024, "ggc_pending_trees");
26775344Ssobomax
2682089Ssos  for (y = d_htab_roots; y != NULL; y = y->next)
26975344Ssobomax    htab_traverse (y->htab, ggc_htab_delete, (PTR) y);
2702089Ssos  ggc_mark_trees ();
27175344Ssobomax  VARRAY_FREE (ggc_pending_trees);
2722089Ssos}
27375344Ssobomax
27475344Ssobomax/* R had not been previously marked, but has now been marked via
27523457Sbrian   ggc_set_mark.  Now recurse and process the children.  */
2762089Ssos
2772089Ssosvoid
2782089Ssosggc_mark_rtx_children (r)
2792089Ssos     rtx r;
2802089Ssos{
28130764Scharnier  rtx i, last;
28223457Sbrian
2832089Ssos  /* Special case the instruction chain.  This is a data structure whose
2842089Ssos     chain length is potentially unbounded, and which contain references
2852089Ssos     within the chain (e.g. label_ref and insn_list).  If do nothing here,
2862089Ssos     we risk blowing the stack recursing through a long chain of insns.
2872089Ssos
2882089Ssos     Combat this by marking all of the instructions in the chain before
2892089Ssos     marking the contents of those instructions.  */
2902089Ssos
2912089Ssos  switch (GET_CODE (r))
2922089Ssos    {
2932089Ssos    case INSN:
2942089Ssos    case JUMP_INSN:
2952089Ssos    case CALL_INSN:
29630764Scharnier    case NOTE:
2972089Ssos    case CODE_LABEL:
2982089Ssos    case BARRIER:
2992089Ssos      for (i = NEXT_INSN (r); ; i = NEXT_INSN (i))
3002089Ssos	if (! ggc_test_and_set_mark (i))
30130764Scharnier	  break;
3022089Ssos      last = i;
3032089Ssos
3042089Ssos      for (i = NEXT_INSN (r); i != last; i = NEXT_INSN (i))
3055536Ssos	ggc_mark_rtx_children_1 (i);
3062089Ssos
3075536Ssos    default:
3082089Ssos      break;
3096230Ssos    }
3106230Ssos
3116230Ssos  ggc_mark_rtx_children_1 (r);
3125536Ssos}
3136230Ssos
3146230Ssosstatic void
3155536Ssosggc_mark_rtx_children_1 (r)
31630764Scharnier     rtx r;
3172089Ssos{
3182089Ssos  const char *fmt;
3195536Ssos  int i;
3202089Ssos  rtx next_rtx;
3212089Ssos
32223457Sbrian  do
3232089Ssos    {
3242089Ssos      enum rtx_code code = GET_CODE (r);
32539592Syokota      /* This gets set to a child rtx to eliminate tail recursion.  */
32639592Syokota      next_rtx = NULL;
32739592Syokota
32839592Syokota      /* Collect statistics, if appropriate.  */
32939592Syokota      if (ggc_stats)
33039592Syokota	{
33139592Syokota	  ++ggc_stats->num_rtxs[(int) code];
33239592Syokota	  ggc_stats->size_rtxs[(int) code] += ggc_get_size (r);
33339592Syokota	}
33439592Syokota
33539592Syokota      /* ??? If (some of) these are really pass-dependent info, do we
33639592Syokota	 have any right poking our noses in?  */
33739592Syokota      switch (code)
33839592Syokota	{
33939592Syokota	case MEM:
34039592Syokota	  ggc_mark (MEM_ATTRS (r));
34139592Syokota	  break;
34239592Syokota	case JUMP_INSN:
34339592Syokota	  ggc_mark_rtx (JUMP_LABEL (r));
34448105Syokota	  break;
34548105Syokota	case CODE_LABEL:
34648105Syokota	  ggc_mark_rtx (LABEL_REFS (r));
34748105Syokota	  break;
34848105Syokota	case LABEL_REF:
34948105Syokota	  ggc_mark_rtx (LABEL_NEXTREF (r));
35048105Syokota	  ggc_mark_rtx (CONTAINING_INSN (r));
35139592Syokota	  break;
35239592Syokota	case ADDRESSOF:
35339592Syokota	  ggc_mark_tree (ADDRESSOF_DECL (r));
35439592Syokota	  break;
35539592Syokota	case CONST_DOUBLE:
35639592Syokota	  ggc_mark_rtx (CONST_DOUBLE_CHAIN (r));
35739592Syokota	  break;
35839592Syokota	case NOTE:
35939592Syokota	  switch (NOTE_LINE_NUMBER (r))
36039592Syokota	    {
36142605Smjacob	    case NOTE_INSN_RANGE_BEG:
36248105Syokota	    case NOTE_INSN_RANGE_END:
36348105Syokota	    case NOTE_INSN_LIVE:
36439287Ssos	    case NOTE_INSN_EXPECTED_VALUE:
36539592Syokota	      ggc_mark_rtx (NOTE_RANGE_INFO (r));
3662089Ssos	      break;
36748105Syokota
36848105Syokota	    case NOTE_INSN_BLOCK_BEG:
3692089Ssos	    case NOTE_INSN_BLOCK_END:
37039592Syokota	      ggc_mark_tree (NOTE_BLOCK (r));
37139592Syokota	      break;
37239592Syokota
37339592Syokota	    default:
37439592Syokota	      break;
37539592Syokota	    }
37639592Syokota	  break;
3772089Ssos
3782089Ssos	default:
37930764Scharnier	  break;
38039287Ssos	}
38171642Ssobomax
38271642Ssobomax      for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i)
38371642Ssobomax	{
38471642Ssobomax	  rtx exp;
38571642Ssobomax	  switch (*fmt)
38671642Ssobomax	    {
38771642Ssobomax	    case 'e': case 'u':
38871642Ssobomax	      exp = XEXP (r, i);
38971642Ssobomax	      if (ggc_test_and_set_mark (exp))
39071642Ssobomax		{
39171642Ssobomax		  if (next_rtx == NULL)
39271642Ssobomax		    next_rtx = exp;
39371642Ssobomax		  else
39471642Ssobomax		    ggc_mark_rtx_children (exp);
39571642Ssobomax		}
39671642Ssobomax	      break;
39771642Ssobomax	    case 'V': case 'E':
39871642Ssobomax	      ggc_mark_rtvec (XVEC (r, i));
39971642Ssobomax	      break;
40048105Syokota	    }
40148105Syokota	}
40248105Syokota    }
40380148Syokota  while ((r = next_rtx) != NULL);
40480148Syokota}
40580148Syokota
40648105Syokota/* V had not been previously marked, but has now been marked via
40748105Syokota   ggc_set_mark.  Now recurse and process the children.  */
40848105Syokota
40948105Syokotavoid
41039287Ssosggc_mark_rtvec_children (v)
4112089Ssos     rtvec v;
4122089Ssos{
4132089Ssos  int i;
4142089Ssos
4158857Srgrimes  i = GET_NUM_ELEM (v);
4162089Ssos  while (--i >= 0)
4172089Ssos    ggc_mark_rtx (RTVEC_ELT (v, i));
4182089Ssos}
4192089Ssos
4202089Ssos/* Recursively set marks on all of the children of the
4212089Ssos   GCC_PENDING_TREES.  */
4222089Ssos
4232089Ssosstatic void
4242089Ssosggc_mark_trees ()
4252089Ssos{
4262089Ssos  while (ggc_pending_trees->elements_used)
42723457Sbrian    {
4282089Ssos      tree t;
4292089Ssos      enum tree_code code;
4302089Ssos
4312089Ssos      t = VARRAY_TOP_TREE (ggc_pending_trees);
4322089Ssos      VARRAY_POP (ggc_pending_trees);
4332089Ssos      code = TREE_CODE (t);
4342089Ssos
4358857Srgrimes      /* Collect statistics, if appropriate.  */
4368857Srgrimes      if (ggc_stats)
4372089Ssos	{
4382089Ssos	  ++ggc_stats->num_trees[(int) code];
4392089Ssos	  ggc_stats->size_trees[(int) code] += ggc_get_size (t);
4402089Ssos	}
4412089Ssos
4422089Ssos      /* Bits from common.  */
4432089Ssos      ggc_mark_tree (TREE_TYPE (t));
44423457Sbrian      ggc_mark_tree (TREE_CHAIN (t));
4452089Ssos
4462089Ssos      /* Some nodes require special handling.  */
4472089Ssos      switch (code)
4482089Ssos	{
4492089Ssos	case TREE_LIST:
4502089Ssos	  ggc_mark_tree (TREE_PURPOSE (t));
4518857Srgrimes	  ggc_mark_tree (TREE_VALUE (t));
4528857Srgrimes	  continue;
4532089Ssos
4542089Ssos	case TREE_VEC:
4552089Ssos	  {
4562089Ssos	    int i = TREE_VEC_LENGTH (t);
4572089Ssos
4582089Ssos	    while (--i >= 0)
4592089Ssos	      ggc_mark_tree (TREE_VEC_ELT (t, i));
46023457Sbrian	    continue;
46123457Sbrian	  }
46223457Sbrian
46323457Sbrian	case COMPLEX_CST:
46423457Sbrian	  ggc_mark_tree (TREE_REALPART (t));
46523457Sbrian	  ggc_mark_tree (TREE_IMAGPART (t));
46630764Scharnier	  break;
46723457Sbrian
46823457Sbrian	case PARM_DECL:
46923457Sbrian	  ggc_mark_rtx (DECL_INCOMING_RTL (t));
47023457Sbrian	  break;
47151393Syokota
47230764Scharnier	case FIELD_DECL:
47342605Smjacob	  ggc_mark_tree (DECL_FIELD_BIT_OFFSET (t));
47430764Scharnier	  break;
47523457Sbrian
47623457Sbrian	case IDENTIFIER_NODE:
47723457Sbrian	  lang_mark_tree (t);
4782089Ssos	  continue;
4792089Ssos
4802089Ssos	default:
4812089Ssos	  break;
4822089Ssos	}
4832089Ssos
4842089Ssos      /* But in general we can handle them by class.  */
4852089Ssos      switch (TREE_CODE_CLASS (code))
4868857Srgrimes	{
4872089Ssos	case 'd': /* A decl node.  */
4882089Ssos	  ggc_mark_tree (DECL_SIZE (t));
48916565Ssos	  ggc_mark_tree (DECL_SIZE_UNIT (t));
49055849Syokota	  ggc_mark_tree (DECL_NAME (t));
49155849Syokota	  ggc_mark_tree (DECL_CONTEXT (t));
49255849Syokota	  ggc_mark_tree (DECL_ARGUMENTS (t));
49355849Syokota	  ggc_mark_tree (DECL_RESULT_FLD (t));
49455849Syokota	  ggc_mark_tree (DECL_INITIAL (t));
49555849Syokota	  ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
49675788Sache	  ggc_mark_tree (DECL_SECTION_NAME (t));
49775788Sache	  ggc_mark_tree (DECL_ATTRIBUTES (t));
49855849Syokota	  if (DECL_RTL_SET_P (t))
49955849Syokota	    ggc_mark_rtx (DECL_RTL (t));
50055849Syokota	  ggc_mark_rtx (DECL_LIVE_RANGE_RTL (t));
50155849Syokota	  ggc_mark_tree (DECL_VINDEX (t));
50255849Syokota	  if (DECL_ASSEMBLER_NAME_SET_P (t))
50355849Syokota	    ggc_mark_tree (DECL_ASSEMBLER_NAME (t));
50455849Syokota	  if (TREE_CODE (t) == FUNCTION_DECL)
50555849Syokota	    {
50616565Ssos	      ggc_mark_tree (DECL_SAVED_TREE (t));
50716565Ssos	      ggc_mark_tree (DECL_INLINED_FNS (t));
50816565Ssos	      if (DECL_SAVED_INSNS (t))
50916565Ssos		ggc_mark_struct_function (DECL_SAVED_INSNS (t));
51016565Ssos	    }
51116565Ssos	  lang_mark_tree (t);
51216565Ssos	  break;
51316565Ssos
51416565Ssos	case 't': /* A type node.  */
51530764Scharnier	  ggc_mark_tree (TYPE_SIZE (t));
51616565Ssos	  ggc_mark_tree (TYPE_SIZE_UNIT (t));
51716565Ssos	  ggc_mark_tree (TYPE_ATTRIBUTES (t));
51816565Ssos	  ggc_mark_tree (TYPE_VALUES (t));
51916565Ssos	  ggc_mark_tree (TYPE_POINTER_TO (t));
52016565Ssos	  ggc_mark_tree (TYPE_REFERENCE_TO (t));
52139287Ssos	  ggc_mark_tree (TYPE_NAME (t));
52239287Ssos	  ggc_mark_tree (TYPE_MIN_VALUE (t));
52339287Ssos	  ggc_mark_tree (TYPE_MAX_VALUE (t));
52439287Ssos	  ggc_mark_tree (TYPE_NEXT_VARIANT (t));
52539287Ssos	  ggc_mark_tree (TYPE_MAIN_VARIANT (t));
52639287Ssos	  ggc_mark_tree (TYPE_BINFO (t));
52739287Ssos	  ggc_mark_tree (TYPE_CONTEXT (t));
52839287Ssos	  lang_mark_tree (t);
52939287Ssos	  break;
53039287Ssos
53139287Ssos	case 'b': /* A lexical block.  */
53239287Ssos	  ggc_mark_tree (BLOCK_VARS (t));
53339287Ssos	  ggc_mark_tree (BLOCK_SUBBLOCKS (t));
53448105Syokota	  ggc_mark_tree (BLOCK_SUPERCONTEXT (t));
53539287Ssos	  ggc_mark_tree (BLOCK_ABSTRACT_ORIGIN (t));
53639287Ssos	  break;
53739287Ssos
53839287Ssos	case 'c': /* A constant.  */
53939287Ssos	  ggc_mark_rtx (TREE_CST_RTL (t));
54039287Ssos	  break;
54139287Ssos
54239287Ssos	case 'r': case '<': case '1':
54339287Ssos	case '2': case 'e': case 's': /* Expressions.  */
54439287Ssos	  {
54523457Sbrian	    int i = TREE_CODE_LENGTH (TREE_CODE (t));
54639287Ssos	    int first_rtl = first_rtl_op (TREE_CODE (t));
54739287Ssos
54842505Syokota	    while (--i >= 0)
54939287Ssos	      {
55039287Ssos		if (i >= first_rtl)
55139287Ssos		  ggc_mark_rtx ((rtx) TREE_OPERAND (t, i));
55239287Ssos		else
55339287Ssos		  ggc_mark_tree (TREE_OPERAND (t, i));
55439287Ssos	      }
55539287Ssos	    break;
55642505Syokota	  }
55742505Syokota
55842505Syokota	case 'x':
55939287Ssos	  lang_mark_tree (t);
56042505Syokota	  break;
56139287Ssos	}
56239287Ssos    }
56348105Syokota}
56448105Syokota
56548105Syokota/* Mark all the elements of the varray V, which contains rtxs.  */
56648105Syokota
56748105Syokotavoid
56848105Syokotaggc_mark_rtx_varray (v)
56948105Syokota     varray_type v;
57039287Ssos{
57139287Ssos  int i;
57239287Ssos
57339287Ssos  if (v)
57439287Ssos    for (i = v->num_elements - 1; i >= 0; --i)
57539287Ssos      ggc_mark_rtx (VARRAY_RTX (v, i));
57639287Ssos}
57739287Ssos
57839287Ssos/* Mark all the elements of the varray V, which contains trees.  */
57939287Ssos
58039287Ssosvoid
58139287Ssosggc_mark_tree_varray (v)
58239287Ssos     varray_type v;
58339287Ssos{
58439287Ssos  int i;
58539287Ssos
58639287Ssos  if (v)
58739287Ssos    for (i = v->num_elements - 1; i >= 0; --i)
58848105Syokota      ggc_mark_tree (VARRAY_TREE (v, i));
58948105Syokota}
59039287Ssos
59139287Ssos/* Mark the hash table-entry HE.  Its key field is really a tree.  */
59239287Ssos
59339287Ssosstatic bool
59439287Ssosggc_mark_tree_hash_table_entry (he, k)
59539287Ssos     struct hash_entry *he;
59639287Ssos     hash_table_key k ATTRIBUTE_UNUSED;
59739287Ssos{
59839287Ssos  ggc_mark_tree ((tree) he->key);
59939287Ssos  return true;
60039287Ssos}
60139287Ssos
60239287Ssos/* Mark all the elements of the hash-table H, which contains trees.  */
60339287Ssos
60439287Ssosvoid
60539287Ssosggc_mark_tree_hash_table (ht)
60639287Ssos     struct hash_table *ht;
60739287Ssos{
60843186Sdfr  hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0);
60943186Sdfr}
61048105Syokota
61143186Sdfr/* Type-correct function to pass to ggc_add_root.  It just forwards
61239287Ssos   *ELT (which is an rtx) to ggc_mark_rtx.  */
61339287Ssos
61439287Ssosstatic void
61539287Ssosggc_mark_rtx_ptr (elt)
61639287Ssos     void *elt;
61739287Ssos{
61839287Ssos  ggc_mark_rtx (*(rtx *) elt);
61939287Ssos}
62039287Ssos
62139287Ssos/* Type-correct function to pass to ggc_add_root.  It just forwards
62239287Ssos   *ELT (which is a tree) to ggc_mark_tree.  */
62339287Ssos
62439287Ssosstatic void
62539287Ssosggc_mark_tree_ptr (elt)
62639287Ssos     void *elt;
62739287Ssos{
62839287Ssos  ggc_mark_tree (*(tree *) elt);
6292089Ssos}
6302089Ssos
6312089Ssos/* Type-correct function to pass to ggc_add_root.  It just forwards
6322089Ssos   ELT (which is really a varray_type *) to ggc_mark_rtx_varray.  */
6332089Ssos
6342089Ssosstatic void
6352089Ssosggc_mark_rtx_varray_ptr (elt)
6362089Ssos     void *elt;
6372089Ssos{
6388857Srgrimes  ggc_mark_rtx_varray (*(varray_type *) elt);
6398857Srgrimes}
6402089Ssos
6412089Ssos/* Type-correct function to pass to ggc_add_root.  It just forwards
6428857Srgrimes   ELT (which is really a varray_type *) to ggc_mark_tree_varray.  */
6432089Ssos
6442089Ssosstatic void
6452089Ssosggc_mark_tree_varray_ptr (elt)
64676845Ssobomax     void *elt;
64776845Ssobomax{
64876845Ssobomax  ggc_mark_tree_varray (*(varray_type *) elt);
64976845Ssobomax}
65076845Ssobomax
65176845Ssobomax/* Type-correct function to pass to ggc_add_root.  It just forwards
65276845Ssobomax   ELT (which is really a struct hash_table **) to
65376845Ssobomax   ggc_mark_tree_hash_table.  */
65476845Ssobomax
65576845Ssobomaxstatic void
65676845Ssobomaxggc_mark_tree_hash_table_ptr (elt)
65776845Ssobomax     void *elt;
65876845Ssobomax{
65976845Ssobomax  ggc_mark_tree_hash_table (*(struct hash_table **) elt);
66076845Ssobomax}
66176845Ssobomax
66276845Ssobomax/* Allocate a block of memory, then clear it.  */
66376845Ssobomaxvoid *
66476845Ssobomaxggc_alloc_cleared (size)
66576845Ssobomax     size_t size;
66676845Ssobomax{
66776845Ssobomax  void *buf = ggc_alloc (size);
66876845Ssobomax  memset (buf, 0, size);
66976845Ssobomax  return buf;
67076845Ssobomax}
67176845Ssobomax
67276845Ssobomax/* Print statistics that are independent of the collector in use.  */
67376845Ssobomax#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
67476845Ssobomax		  ? (x) \
67576845Ssobomax		  : ((x) < 1024*1024*10 \
67676845Ssobomax		     ? (x) / 1024 \
67776845Ssobomax		     : (x) / (1024*1024))))
67876845Ssobomax#define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
67976845Ssobomax
68076845Ssobomaxvoid
68176845Ssobomaxggc_print_common_statistics (stream, stats)
68276845Ssobomax     FILE *stream;
68376845Ssobomax     ggc_statistics *stats;
68476845Ssobomax{
68576845Ssobomax  int code;
68676845Ssobomax
68776845Ssobomax  /* Set the pointer so that during collection we will actually gather
68876845Ssobomax     the statistics.  */
68976845Ssobomax  ggc_stats = stats;
69076845Ssobomax
69176845Ssobomax  /* Then do one collection to fill in the statistics.  */
69276845Ssobomax  ggc_collect ();
69376845Ssobomax
69476845Ssobomax  /* Total the statistics.  */
69576845Ssobomax  for (code = 0; code < MAX_TREE_CODES; ++code)
69676845Ssobomax    {
69776845Ssobomax      stats->total_num_trees += stats->num_trees[code];
69876845Ssobomax      stats->total_size_trees += stats->size_trees[code];
69976845Ssobomax    }
70076845Ssobomax  for (code = 0; code < NUM_RTX_CODE; ++code)
70176845Ssobomax    {
70276845Ssobomax      stats->total_num_rtxs += stats->num_rtxs[code];
70376845Ssobomax      stats->total_size_rtxs += stats->size_rtxs[code];
70476845Ssobomax    }
70576845Ssobomax
70676845Ssobomax  /* Print the statistics for trees.  */
70776845Ssobomax  fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree",
70876845Ssobomax	   "Number", "Bytes", "% Total");
70976845Ssobomax  for (code = 0; code < MAX_TREE_CODES; ++code)
71076845Ssobomax    if (ggc_stats->num_trees[code])
71176845Ssobomax      {
71276845Ssobomax	fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
71376845Ssobomax		 tree_code_name[code],
71476845Ssobomax		 ggc_stats->num_trees[code],
71576845Ssobomax		 SCALE (ggc_stats->size_trees[code]),
71676845Ssobomax		 LABEL (ggc_stats->size_trees[code]),
71777329Sdes		 (100 * ((double) ggc_stats->size_trees[code])
71877329Sdes		  / ggc_stats->total_size_trees));
71977329Sdes      }
72077329Sdes  fprintf (stream,
72177329Sdes	   "%-17s%10u%16ld%c\n", "Total",
72277329Sdes	   ggc_stats->total_num_trees,
72377329Sdes	   SCALE (ggc_stats->total_size_trees),
72477329Sdes	   LABEL (ggc_stats->total_size_trees));
72577329Sdes
72677329Sdes  /* Print the statistics for RTL.  */
72777329Sdes  fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX",
72877329Sdes	   "Number", "Bytes", "% Total");
72977329Sdes  for (code = 0; code < NUM_RTX_CODE; ++code)
73077329Sdes    if (ggc_stats->num_rtxs[code])
73177329Sdes      {
73277329Sdes	fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
73377329Sdes		 rtx_name[code],
73477329Sdes		 ggc_stats->num_rtxs[code],
73577329Sdes		 SCALE (ggc_stats->size_rtxs[code]),
73677329Sdes		 LABEL (ggc_stats->size_rtxs[code]),
73777329Sdes		 (100 * ((double) ggc_stats->size_rtxs[code])
73877329Sdes		  / ggc_stats->total_size_rtxs));
73923457Sbrian      }
7402089Ssos  fprintf (stream,
7412089Ssos	   "%-17s%10u%16ld%c\n", "Total",
74275344Ssobomax	   ggc_stats->total_num_rtxs,
74375344Ssobomax	   SCALE (ggc_stats->total_size_rtxs),
7442089Ssos	   LABEL (ggc_stats->total_size_rtxs));
7458857Srgrimes
7462089Ssos  /* Don't gather statistics any more.  */
74776897Ssobomax  ggc_stats = NULL;
74876897Ssobomax}
74976897Ssobomax