]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gcc/ggc-common.c
Merge FreeBSD modifications into gcc 3.2.1-prerelease:
[FreeBSD/FreeBSD.git] / contrib / gcc / ggc-common.c
1 /* Simple garbage collection for the GNU compiler.
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20
21 /* Generic garbage collection (GC) functions and data, not specific to
22    any particular GC implementation.  */
23
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "tm_p.h"
29 #include "hash.h"
30 #include "hashtab.h"
31 #include "varray.h"
32 #include "ggc.h"
33
34 /* Statistics about the allocation.  */
35 static ggc_statistics *ggc_stats;
36
37 /* The FALSE_LABEL_STACK, declared in except.h, has language-dependent
38    semantics.  If a front-end needs to mark the false label stack, it
39    should set this pointer to a non-NULL value.  Otherwise, no marking
40    will be done.  */
41 void (*lang_mark_false_label_stack) PARAMS ((struct label_node *));
42
43 /* Trees that have been marked, but whose children still need marking.  */
44 varray_type ggc_pending_trees;
45
46 static void ggc_mark_rtx_children_1 PARAMS ((rtx));
47 static void ggc_mark_rtx_ptr PARAMS ((void *));
48 static void ggc_mark_tree_ptr PARAMS ((void *));
49 static void ggc_mark_rtx_varray_ptr PARAMS ((void *));
50 static void ggc_mark_tree_varray_ptr PARAMS ((void *));
51 static void ggc_mark_tree_hash_table_ptr PARAMS ((void *));
52 static int ggc_htab_delete PARAMS ((void **, void *));
53 static void ggc_mark_trees PARAMS ((void));
54 static bool ggc_mark_tree_hash_table_entry PARAMS ((struct hash_entry *,
55                                                     hash_table_key));
56
57 /* Maintain global roots that are preserved during GC.  */
58
59 /* Global roots that are preserved during calls to gc.  */
60
61 struct ggc_root
62 {
63   struct ggc_root *next;
64   void *base;
65   int nelt;
66   int size;
67   void (*cb) PARAMS ((void *));
68 };
69
70 static struct ggc_root *roots;
71
72 /* Add BASE as a new garbage collection root.  It is an array of
73    length NELT with each element SIZE bytes long.  CB is a 
74    function that will be called with a pointer to each element
75    of the array; it is the intention that CB call the appropriate
76    routine to mark gc-able memory for that element.  */
77
78 void
79 ggc_add_root (base, nelt, size, cb)
80      void *base;
81      int nelt, size;
82      void (*cb) PARAMS ((void *));
83 {
84   struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x));
85
86   x->next = roots;
87   x->base = base;
88   x->nelt = nelt;
89   x->size = size;
90   x->cb = cb;
91
92   roots = x;
93 }
94
95 /* Register an array of rtx as a GC root.  */
96
97 void
98 ggc_add_rtx_root (base, nelt)
99      rtx *base;
100      int nelt;
101 {
102   ggc_add_root (base, nelt, sizeof (rtx), ggc_mark_rtx_ptr);
103 }
104
105 /* Register an array of trees as a GC root.  */
106
107 void
108 ggc_add_tree_root (base, nelt)
109      tree *base;
110      int nelt;
111 {
112   ggc_add_root (base, nelt, sizeof (tree), ggc_mark_tree_ptr);
113 }
114
115 /* Register a varray of rtxs as a GC root.  */
116
117 void
118 ggc_add_rtx_varray_root (base, nelt)
119      varray_type *base;
120      int nelt;
121 {
122   ggc_add_root (base, nelt, sizeof (varray_type), 
123                 ggc_mark_rtx_varray_ptr);
124 }
125
126 /* Register a varray of trees as a GC root.  */
127
128 void
129 ggc_add_tree_varray_root (base, nelt)
130      varray_type *base;
131      int nelt;
132 {
133   ggc_add_root (base, nelt, sizeof (varray_type), 
134                 ggc_mark_tree_varray_ptr);
135 }
136
137 /* Register a hash table of trees as a GC root.  */
138
139 void
140 ggc_add_tree_hash_table_root (base, nelt)
141      struct hash_table **base;
142      int nelt;
143 {
144   ggc_add_root (base, nelt, sizeof (struct hash_table *), 
145                 ggc_mark_tree_hash_table_ptr);
146 }
147
148 /* Remove the previously registered GC root at BASE.  */
149
150 void
151 ggc_del_root (base)
152      void *base;
153 {
154   struct ggc_root *x, **p;
155
156   p = &roots, x = roots;
157   while (x)
158     {
159       if (x->base == base)
160         {
161           *p = x->next;
162           free (x);
163           return;
164         }
165       p = &x->next;
166       x = x->next;
167     }
168
169   abort ();
170 }
171
172 /* Add a hash table to be scanned when all roots have been processed.  We
173    delete any entry in the table that has not been marked.  */
174
175 struct d_htab_root
176 {
177   struct d_htab_root *next;
178   htab_t htab;
179   ggc_htab_marked_p marked_p;
180   ggc_htab_mark mark;
181 };
182
183 static struct d_htab_root *d_htab_roots;
184
185 /* Add X, an htab, to a list of htabs that contain objects which are allocated
186    from GC memory.  Once all other roots are marked, we check each object in
187    the htab to see if it has already been marked.  If not, it is deleted.
188
189    MARKED_P, if specified, is a function that returns 1 if the entry is to
190    be considered as "marked".  If not present, the data structure pointed to
191    by the htab slot is tested.  This function should be supplied if some
192    other object (such as something pointed to by that object) should be tested
193    in which case the function tests whether that object (or objects) are
194    marked (using ggc_marked_p) and returns nonzero if it is.
195
196    MARK, if specified, is a function that is passed the contents of a slot
197    that has been determined to have been "marked" (via the above function)
198    and marks any other objects pointed to by that object.  For example,
199    we might have a hash table of memory attribute blocks, which are pointed
200    to by a MEM RTL but have a pointer to a DECL.  MARKED_P in that case will
201    not be specified because we want to know if the attribute block is pointed
202    to by the MEM, but MARK must be specified because if the block has been
203    marked, we need to mark the DECL.  */
204
205 void
206 ggc_add_deletable_htab (x, marked_p, mark)
207      PTR x;
208      ggc_htab_marked_p marked_p;
209      ggc_htab_mark mark;
210 {
211   struct d_htab_root *r
212     = (struct d_htab_root *) xmalloc (sizeof (struct d_htab_root));
213
214   r->next = d_htab_roots;
215   r->htab = (htab_t) x;
216   r->marked_p = marked_p ? marked_p : ggc_marked_p;
217   r->mark = mark;
218   d_htab_roots = r;
219 }
220
221 /* Process a slot of an htab by deleting it if it has not been marked.  */
222
223 static int
224 ggc_htab_delete (slot, info)
225      void **slot;
226      void *info;
227 {
228   struct d_htab_root *r = (struct d_htab_root *) info;
229
230   if (! (*r->marked_p) (*slot))
231     htab_clear_slot (r->htab, slot);
232   else if (r->mark)
233     (*r->mark) (*slot);
234
235   return 1;
236 }
237
238 /* Iterate through all registered roots and mark each element.  */
239
240 void
241 ggc_mark_roots ()
242 {
243   struct ggc_root *x;
244   struct d_htab_root *y;
245   
246   VARRAY_TREE_INIT (ggc_pending_trees, 4096, "ggc_pending_trees");
247
248   for (x = roots; x != NULL; x = x->next)
249     {
250       char *elt = x->base;
251       int s = x->size, n = x->nelt;
252       void (*cb) PARAMS ((void *)) = x->cb;
253       int i;
254
255       for (i = 0; i < n; ++i, elt += s)
256         (*cb)(elt);
257     }
258
259   /* Mark all the queued up trees, and their children.  */
260   ggc_mark_trees ();
261   VARRAY_FREE (ggc_pending_trees);
262
263   /* Now scan all hash tables that have objects which are to be deleted if
264      they are not already marked.  Since these may mark more trees, we need
265      to reinitialize that varray.  */
266   VARRAY_TREE_INIT (ggc_pending_trees, 1024, "ggc_pending_trees");
267
268   for (y = d_htab_roots; y != NULL; y = y->next)
269     htab_traverse (y->htab, ggc_htab_delete, (PTR) y);
270   ggc_mark_trees ();
271   VARRAY_FREE (ggc_pending_trees);
272 }
273
274 /* R had not been previously marked, but has now been marked via
275    ggc_set_mark.  Now recurse and process the children.  */
276
277 void
278 ggc_mark_rtx_children (r)
279      rtx r;
280 {
281   rtx i, last;
282
283   /* Special case the instruction chain.  This is a data structure whose
284      chain length is potentially unbounded, and which contain references
285      within the chain (e.g. label_ref and insn_list).  If do nothing here,
286      we risk blowing the stack recursing through a long chain of insns.
287
288      Combat this by marking all of the instructions in the chain before
289      marking the contents of those instructions.  */
290
291   switch (GET_CODE (r))
292     {
293     case INSN:
294     case JUMP_INSN:
295     case CALL_INSN:
296     case NOTE:
297     case CODE_LABEL:
298     case BARRIER:
299       for (i = NEXT_INSN (r); ; i = NEXT_INSN (i))
300         if (! ggc_test_and_set_mark (i))
301           break;
302       last = i;
303
304       for (i = NEXT_INSN (r); i != last; i = NEXT_INSN (i))
305         ggc_mark_rtx_children_1 (i);
306
307     default:
308       break;
309     }
310
311   ggc_mark_rtx_children_1 (r);
312 }
313
314 static void
315 ggc_mark_rtx_children_1 (r)
316      rtx r;
317 {
318   const char *fmt;
319   int i;
320   rtx next_rtx;
321
322   do 
323     {
324       enum rtx_code code = GET_CODE (r);
325       /* This gets set to a child rtx to eliminate tail recursion.  */
326       next_rtx = NULL;
327
328       /* Collect statistics, if appropriate.  */
329       if (ggc_stats)
330         {
331           ++ggc_stats->num_rtxs[(int) code];
332           ggc_stats->size_rtxs[(int) code] += ggc_get_size (r);
333         }
334
335       /* ??? If (some of) these are really pass-dependent info, do we
336          have any right poking our noses in?  */
337       switch (code)
338         {
339         case MEM:
340           ggc_mark (MEM_ATTRS (r));
341           break;
342         case JUMP_INSN:
343           ggc_mark_rtx (JUMP_LABEL (r));
344           break;
345         case CODE_LABEL:
346           ggc_mark_rtx (LABEL_REFS (r));
347           break;
348         case LABEL_REF:
349           ggc_mark_rtx (LABEL_NEXTREF (r));
350           ggc_mark_rtx (CONTAINING_INSN (r));
351           break;
352         case ADDRESSOF:
353           ggc_mark_tree (ADDRESSOF_DECL (r));
354           break;
355         case CONST_DOUBLE:
356           ggc_mark_rtx (CONST_DOUBLE_CHAIN (r));
357           break;
358         case NOTE:
359           switch (NOTE_LINE_NUMBER (r))
360             {
361             case NOTE_INSN_RANGE_BEG:
362             case NOTE_INSN_RANGE_END:
363             case NOTE_INSN_LIVE:
364             case NOTE_INSN_EXPECTED_VALUE:
365               ggc_mark_rtx (NOTE_RANGE_INFO (r));
366               break;
367
368             case NOTE_INSN_BLOCK_BEG:
369             case NOTE_INSN_BLOCK_END:
370               ggc_mark_tree (NOTE_BLOCK (r));
371               break;
372
373             default:
374               break;
375             }
376           break;
377
378         default:
379           break;
380         }
381
382       for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i)
383         {
384           rtx exp;
385           switch (*fmt)
386             {
387             case 'e': case 'u':
388               exp = XEXP (r, i);
389               if (ggc_test_and_set_mark (exp))
390                 { 
391                   if (next_rtx == NULL) 
392                     next_rtx = exp; 
393                   else 
394                     ggc_mark_rtx_children (exp);
395                 } 
396               break;
397             case 'V': case 'E':
398               ggc_mark_rtvec (XVEC (r, i));
399               break;
400             }
401         }
402     }
403   while ((r = next_rtx) != NULL);
404 }
405
406 /* V had not been previously marked, but has now been marked via
407    ggc_set_mark.  Now recurse and process the children.  */
408
409 void
410 ggc_mark_rtvec_children (v)
411      rtvec v;
412 {
413   int i;
414
415   i = GET_NUM_ELEM (v);
416   while (--i >= 0)
417     ggc_mark_rtx (RTVEC_ELT (v, i));
418 }
419
420 /* Recursively set marks on all of the children of the
421    GCC_PENDING_TREES.  */
422
423 static void
424 ggc_mark_trees ()
425 {
426   while (ggc_pending_trees->elements_used)
427     {
428       tree t;
429       enum tree_code code;
430
431       t = VARRAY_TOP_TREE (ggc_pending_trees);
432       VARRAY_POP (ggc_pending_trees);
433       code = TREE_CODE (t);
434
435       /* Collect statistics, if appropriate.  */
436       if (ggc_stats)
437         {
438           ++ggc_stats->num_trees[(int) code];
439           ggc_stats->size_trees[(int) code] += ggc_get_size (t);
440         }
441
442       /* Bits from common.  */
443       ggc_mark_tree (TREE_TYPE (t));
444       ggc_mark_tree (TREE_CHAIN (t));
445
446       /* Some nodes require special handling.  */
447       switch (code)
448         {
449         case TREE_LIST:
450           ggc_mark_tree (TREE_PURPOSE (t));
451           ggc_mark_tree (TREE_VALUE (t));
452           continue;
453
454         case TREE_VEC:
455           {
456             int i = TREE_VEC_LENGTH (t);
457
458             while (--i >= 0)
459               ggc_mark_tree (TREE_VEC_ELT (t, i));
460             continue;
461           }
462
463         case COMPLEX_CST:
464           ggc_mark_tree (TREE_REALPART (t));
465           ggc_mark_tree (TREE_IMAGPART (t));
466           break;
467
468         case PARM_DECL:
469           ggc_mark_rtx (DECL_INCOMING_RTL (t));
470           break;
471
472         case FIELD_DECL:
473           ggc_mark_tree (DECL_FIELD_BIT_OFFSET (t));
474           break;
475
476         case IDENTIFIER_NODE:
477           lang_mark_tree (t);
478           continue;
479
480         default:
481           break;
482         }
483   
484       /* But in general we can handle them by class.  */
485       switch (TREE_CODE_CLASS (code))
486         {
487         case 'd': /* A decl node.  */
488           ggc_mark_tree (DECL_SIZE (t));
489           ggc_mark_tree (DECL_SIZE_UNIT (t));
490           ggc_mark_tree (DECL_NAME (t));
491           ggc_mark_tree (DECL_CONTEXT (t));
492           ggc_mark_tree (DECL_ARGUMENTS (t));
493           ggc_mark_tree (DECL_RESULT_FLD (t));
494           ggc_mark_tree (DECL_INITIAL (t));
495           ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
496           ggc_mark_tree (DECL_SECTION_NAME (t));
497           ggc_mark_tree (DECL_ATTRIBUTES (t));
498           if (DECL_RTL_SET_P (t))
499             ggc_mark_rtx (DECL_RTL (t));
500           ggc_mark_rtx (DECL_LIVE_RANGE_RTL (t));
501           ggc_mark_tree (DECL_VINDEX (t));
502           if (DECL_ASSEMBLER_NAME_SET_P (t))
503             ggc_mark_tree (DECL_ASSEMBLER_NAME (t));
504           if (TREE_CODE (t) == FUNCTION_DECL)
505             {
506               ggc_mark_tree (DECL_SAVED_TREE (t));
507               ggc_mark_tree (DECL_INLINED_FNS (t));
508               if (DECL_SAVED_INSNS (t))
509                 ggc_mark_struct_function (DECL_SAVED_INSNS (t));
510             }
511           lang_mark_tree (t);
512           break;
513
514         case 't': /* A type node.  */
515           ggc_mark_tree (TYPE_SIZE (t));
516           ggc_mark_tree (TYPE_SIZE_UNIT (t));
517           ggc_mark_tree (TYPE_ATTRIBUTES (t));
518           ggc_mark_tree (TYPE_VALUES (t));
519           ggc_mark_tree (TYPE_POINTER_TO (t));
520           ggc_mark_tree (TYPE_REFERENCE_TO (t));
521           ggc_mark_tree (TYPE_NAME (t));
522           ggc_mark_tree (TYPE_MIN_VALUE (t));
523           ggc_mark_tree (TYPE_MAX_VALUE (t));
524           ggc_mark_tree (TYPE_NEXT_VARIANT (t));
525           ggc_mark_tree (TYPE_MAIN_VARIANT (t));
526           ggc_mark_tree (TYPE_BINFO (t));
527           ggc_mark_tree (TYPE_CONTEXT (t));
528           lang_mark_tree (t);
529           break;
530
531         case 'b': /* A lexical block.  */
532           ggc_mark_tree (BLOCK_VARS (t));
533           ggc_mark_tree (BLOCK_SUBBLOCKS (t));
534           ggc_mark_tree (BLOCK_SUPERCONTEXT (t));
535           ggc_mark_tree (BLOCK_ABSTRACT_ORIGIN (t));
536           break;
537
538         case 'c': /* A constant.  */
539           ggc_mark_rtx (TREE_CST_RTL (t));
540           break;
541
542         case 'r': case '<': case '1':
543         case '2': case 'e': case 's': /* Expressions.  */
544           {
545             int i = TREE_CODE_LENGTH (TREE_CODE (t));
546             int first_rtl = first_rtl_op (TREE_CODE (t));
547
548             while (--i >= 0)
549               {
550                 if (i >= first_rtl)
551                   ggc_mark_rtx ((rtx) TREE_OPERAND (t, i));
552                 else
553                   ggc_mark_tree (TREE_OPERAND (t, i));
554               }
555             break;      
556           }
557
558         case 'x':
559           lang_mark_tree (t);
560           break;
561         }
562     }
563 }
564
565 /* Mark all the elements of the varray V, which contains rtxs.  */
566
567 void
568 ggc_mark_rtx_varray (v)
569      varray_type v;
570 {
571   int i;
572
573   if (v)
574     for (i = v->num_elements - 1; i >= 0; --i) 
575       ggc_mark_rtx (VARRAY_RTX (v, i));
576 }
577
578 /* Mark all the elements of the varray V, which contains trees.  */
579
580 void
581 ggc_mark_tree_varray (v)
582      varray_type v;
583 {
584   int i;
585
586   if (v)
587     for (i = v->num_elements - 1; i >= 0; --i) 
588       ggc_mark_tree (VARRAY_TREE (v, i));
589 }
590
591 /* Mark the hash table-entry HE.  Its key field is really a tree.  */
592
593 static bool
594 ggc_mark_tree_hash_table_entry (he, k)
595      struct hash_entry *he;
596      hash_table_key k ATTRIBUTE_UNUSED;
597 {
598   ggc_mark_tree ((tree) he->key);
599   return true;
600 }
601
602 /* Mark all the elements of the hash-table H, which contains trees.  */
603
604 void
605 ggc_mark_tree_hash_table (ht)
606      struct hash_table *ht;
607 {
608   hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0);
609 }
610
611 /* Type-correct function to pass to ggc_add_root.  It just forwards
612    *ELT (which is an rtx) to ggc_mark_rtx.  */
613
614 static void
615 ggc_mark_rtx_ptr (elt)
616      void *elt;
617 {
618   ggc_mark_rtx (*(rtx *) elt);
619 }
620
621 /* Type-correct function to pass to ggc_add_root.  It just forwards
622    *ELT (which is a tree) to ggc_mark_tree.  */
623
624 static void
625 ggc_mark_tree_ptr (elt)
626      void *elt;
627 {
628   ggc_mark_tree (*(tree *) elt);
629 }
630
631 /* Type-correct function to pass to ggc_add_root.  It just forwards
632    ELT (which is really a varray_type *) to ggc_mark_rtx_varray.  */
633
634 static void
635 ggc_mark_rtx_varray_ptr (elt)
636      void *elt;
637 {
638   ggc_mark_rtx_varray (*(varray_type *) elt);
639 }
640
641 /* Type-correct function to pass to ggc_add_root.  It just forwards
642    ELT (which is really a varray_type *) to ggc_mark_tree_varray.  */
643
644 static void
645 ggc_mark_tree_varray_ptr (elt)
646      void *elt;
647 {
648   ggc_mark_tree_varray (*(varray_type *) elt);
649 }
650
651 /* Type-correct function to pass to ggc_add_root.  It just forwards
652    ELT (which is really a struct hash_table **) to
653    ggc_mark_tree_hash_table.  */
654
655 static void
656 ggc_mark_tree_hash_table_ptr (elt)
657      void *elt;
658 {
659   ggc_mark_tree_hash_table (*(struct hash_table **) elt);
660 }
661
662 /* Allocate a block of memory, then clear it.  */
663 void *
664 ggc_alloc_cleared (size)
665      size_t size;
666 {
667   void *buf = ggc_alloc (size);
668   memset (buf, 0, size);
669   return buf;
670 }
671
672 /* Print statistics that are independent of the collector in use.  */
673 #define SCALE(x) ((unsigned long) ((x) < 1024*10 \
674                   ? (x) \
675                   : ((x) < 1024*1024*10 \
676                      ? (x) / 1024 \
677                      : (x) / (1024*1024))))
678 #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
679
680 void
681 ggc_print_common_statistics (stream, stats)
682      FILE *stream;
683      ggc_statistics *stats;
684 {
685   int code;
686
687   /* Set the pointer so that during collection we will actually gather
688      the statistics.  */
689   ggc_stats = stats;
690
691   /* Then do one collection to fill in the statistics.  */
692   ggc_collect ();
693
694   /* Total the statistics.  */
695   for (code = 0; code < MAX_TREE_CODES; ++code)
696     {
697       stats->total_num_trees += stats->num_trees[code];
698       stats->total_size_trees += stats->size_trees[code];
699     }
700   for (code = 0; code < NUM_RTX_CODE; ++code)
701     {
702       stats->total_num_rtxs += stats->num_rtxs[code];
703       stats->total_size_rtxs += stats->size_rtxs[code];
704     }
705
706   /* Print the statistics for trees.  */
707   fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree", 
708            "Number", "Bytes", "% Total");
709   for (code = 0; code < MAX_TREE_CODES; ++code)
710     if (ggc_stats->num_trees[code]) 
711       {
712         fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
713                  tree_code_name[code],
714                  ggc_stats->num_trees[code],
715                  SCALE (ggc_stats->size_trees[code]),
716                  LABEL (ggc_stats->size_trees[code]),
717                  (100 * ((double) ggc_stats->size_trees[code]) 
718                   / ggc_stats->total_size_trees));
719       }
720   fprintf (stream,
721            "%-17s%10u%16ld%c\n", "Total",
722            ggc_stats->total_num_trees,
723            SCALE (ggc_stats->total_size_trees),
724            LABEL (ggc_stats->total_size_trees));
725
726   /* Print the statistics for RTL.  */
727   fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX", 
728            "Number", "Bytes", "% Total");
729   for (code = 0; code < NUM_RTX_CODE; ++code)
730     if (ggc_stats->num_rtxs[code]) 
731       {
732         fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
733                  rtx_name[code],
734                  ggc_stats->num_rtxs[code],
735                  SCALE (ggc_stats->size_rtxs[code]),
736                  LABEL (ggc_stats->size_rtxs[code]),
737                  (100 * ((double) ggc_stats->size_rtxs[code]) 
738                   / ggc_stats->total_size_rtxs));
739       }
740   fprintf (stream,
741            "%-17s%10u%16ld%c\n", "Total",
742            ggc_stats->total_num_rtxs,
743            SCALE (ggc_stats->total_size_rtxs),
744            LABEL (ggc_stats->total_size_rtxs));
745
746   /* Don't gather statistics any more.  */
747   ggc_stats = NULL;
748 }