* combine.c (SUBST): Break out to a real function do_SUBST.
[official-gcc.git] / gcc / ggc-simple.c
blobe4064a8140b139c77a13d4cb06d12d46bfac912d
1 /* Simple garbage collection for the GNU compiler.
2 Copyright (C) 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "ggc.h"
26 #include "flags.h"
27 #include "varray.h"
28 #include "hash.h"
30 /* Debugging flags. */
32 /* Zap memory before freeing to catch dangling pointers. */
33 #define GGC_POISON
35 /* Log alloc and release. Don't enable this unless you want a
36 really really lot of data. */
37 #undef GGC_DUMP
39 /* Global lists of roots, rtxs, and trees. */
41 struct ggc_root
43 struct ggc_root *next;
44 void *base;
45 int nelt;
46 int size;
47 void (*cb) PROTO ((void *));
50 static struct ggc_root *roots;
52 struct ggc_rtx
54 struct ggc_rtx *chain;
55 struct rtx_def rtx;
58 struct ggc_rtvec
60 struct ggc_rtvec *chain;
61 struct rtvec_def vec;
64 struct ggc_tree
66 struct ggc_tree *chain;
67 union tree_node tree;
70 struct ggc_string
72 struct ggc_string *chain;
73 int magic_mark;
74 char string[1];
77 /* A generic allocation, with an external mark bit. */
79 struct ggc_any
81 struct ggc_any *chain;
82 char mark;
84 /* Make sure the data is reasonably aligned. */
85 union {
86 char c;
87 HOST_WIDE_INT i;
88 long double d;
89 } u;
92 #define GGC_STRING_MAGIC ((unsigned int)0xa1b2c3d4)
94 struct ggc_status
96 struct ggc_status *next;
97 struct ggc_rtx *rtxs;
98 struct ggc_rtvec *vecs;
99 struct ggc_tree *trees;
100 struct ggc_string *strings;
101 struct ggc_any *anys;
102 size_t bytes_alloced_since_gc;
105 /* A chain of GGC contexts. The currently active context is at the
106 front of the chain. */
107 static struct ggc_status *ggc_chain;
109 /* Some statistics. */
111 static int n_rtxs_collected;
112 static int n_vecs_collected;
113 static int n_trees_collected;
114 static int n_strings_collected;
115 static int n_anys_collected;
116 extern int gc_time;
118 #ifdef GGC_DUMP
119 static FILE *dump;
120 #endif
122 /* Local function prototypes. */
124 static void ggc_free_rtx PROTO ((struct ggc_rtx *r));
125 static void ggc_free_tree PROTO ((struct ggc_tree *t));
126 static void ggc_mark_rtx_ptr PROTO ((void *elt));
127 static void ggc_mark_tree_ptr PROTO ((void *elt));
128 static void ggc_mark_string_ptr PROTO ((void *elt));
129 static void ggc_mark_tree_varray_ptr PROTO ((void *elt));
130 static void ggc_mark_tree_hash_table_ptr PROTO ((void *elt));
131 static boolean ggc_mark_tree_hash_table_entry PROTO ((struct hash_entry *,
132 hash_table_key));
134 /* Called once to initialize the garbage collector. */
136 void
137 init_ggc PROTO ((void))
139 /* Initialize the global context. */
140 ggc_push_context ();
142 #ifdef GGC_DUMP
143 dump = fopen ("zgcdump", "w");
144 setlinebuf (dump);
145 #endif
148 /* Start a new GGC context. Memory allocated in previous contexts
149 will not be collected while the new context is active. */
151 void
152 ggc_push_context PROTO ((void))
154 struct ggc_status *gs = (struct ggc_status *) xcalloc (1, sizeof (*gs));
155 gs->next = ggc_chain;
156 ggc_chain = gs;
159 /* Finish a GC context. Any uncollected memory in the new context
160 will be merged with the old context. */
162 void
163 ggc_pop_context PROTO ((void))
165 struct ggc_rtx *r;
166 struct ggc_rtvec *v;
167 struct ggc_tree *t;
168 struct ggc_string *s;
169 struct ggc_status *gs;
171 gs = ggc_chain;
173 r = gs->rtxs;
174 if (r)
176 while (r->chain)
177 r = r->chain;
178 r->chain = gs->next->rtxs;
179 gs->next->rtxs = gs->rtxs;
182 v = gs->vecs;
183 if (v)
185 while (v->chain)
186 v = v->chain;
187 v->chain = gs->next->vecs;
188 gs->next->vecs = gs->vecs;
191 t = gs->trees;
192 if (t)
194 while (t->chain)
195 t = t->chain;
196 t->chain = gs->next->trees;
197 gs->next->trees = gs->trees;
200 s = gs->strings;
201 if (s)
203 while (s->chain)
204 s = s->chain;
205 s->chain = gs->next->strings;
206 gs->next->strings = gs->strings;
209 ggc_chain = gs->next;
210 free (gs);
213 /* These allocators are dreadfully simple, with no caching whatsoever so
214 that Purify-like tools that do allocation versioning can catch errors.
215 This collector is never going to go fast anyway. */
218 ggc_alloc_rtx (nslots)
219 int nslots;
221 struct ggc_rtx *n;
222 int size = sizeof(*n) + (nslots-1) * sizeof(rtunion);
224 n = (struct ggc_rtx *) xcalloc (1, size);
225 n->chain = ggc_chain->rtxs;
226 ggc_chain->rtxs = n;
228 #ifdef GGC_DUMP
229 fprintf (dump, "alloc rtx %p\n", &n->rtx);
230 #endif
232 ggc_chain->bytes_alloced_since_gc += size;
234 return &n->rtx;
237 rtvec
238 ggc_alloc_rtvec (nelt)
239 int nelt;
241 struct ggc_rtvec *v;
242 int size = sizeof (*v) + (nelt - 1) * sizeof (rtx);
244 v = (struct ggc_rtvec *) xcalloc (1, size);
245 v->chain = ggc_chain->vecs;
246 ggc_chain->vecs = v;
248 #ifdef GGC_DUMP
249 fprintf(dump, "alloc vec %p\n", &v->vec);
250 #endif
252 ggc_chain->bytes_alloced_since_gc += size;
254 return &v->vec;
257 tree
258 ggc_alloc_tree (length)
259 int length;
261 struct ggc_tree *n;
262 int size = sizeof(*n) - sizeof(n->tree) + length;
264 n = (struct ggc_tree *) xcalloc (1, size);
265 n->chain = ggc_chain->trees;
266 ggc_chain->trees = n;
268 #ifdef GGC_DUMP
269 fprintf(dump, "alloc tree %p\n", &n->tree);
270 #endif
272 ggc_chain->bytes_alloced_since_gc += size;
274 return &n->tree;
277 char *
278 ggc_alloc_string (contents, length)
279 const char *contents;
280 int length;
282 struct ggc_string *s;
283 int size;
285 if (length < 0)
287 if (contents == NULL)
288 return NULL;
289 length = strlen (contents);
292 size = (s->string - (char *)s) + length + 1;
293 s = (struct ggc_string *) xmalloc(size);
294 s->chain = ggc_chain->strings;
295 s->magic_mark = GGC_STRING_MAGIC;
296 if (contents)
297 bcopy (contents, s->string, length);
298 s->string[length] = 0;
299 ggc_chain->strings = s;
301 #ifdef GGC_DUMP
302 fprintf(dump, "alloc string %p\n", &s->string);
303 #endif
305 ggc_chain->bytes_alloced_since_gc += size;
307 return s->string;
310 /* Like xmalloc, but allocates GC-able memory. */
312 void *
313 ggc_alloc (bytes)
314 size_t bytes;
316 struct ggc_any *a;
318 if (bytes == 0)
319 bytes = 1;
320 bytes += (&((struct ggc_any *) 0)->u.c - (char *) 0);
322 a = (struct ggc_any *) xmalloc (bytes);
323 a->chain = ggc_chain->anys;
324 ggc_chain->anys = a;
326 return &a->u;
329 /* Freeing a bit of rtl is as simple as calling free. */
331 static void
332 ggc_free_rtx (r)
333 struct ggc_rtx *r;
335 #ifdef GGC_DUMP
336 fprintf (dump, "collect rtx %p\n", &r->rtx);
337 #endif
338 #ifdef GGC_POISON
339 memset (r, 0xAA, sizeof(*r) + ((GET_RTX_LENGTH (r->rtx.code) -1)
340 * sizeof(rtunion)));
341 #endif
343 free (r);
346 /* Freeing an rtvec is as simple as calling free. */
348 static void
349 ggc_free_rtvec (v)
350 struct ggc_rtvec *v;
352 #ifdef GGC_DUMP
353 fprintf(dump, "collect vec %p\n", &v->vec);
354 #endif
355 #ifdef GGC_POISON
356 memset (v, 0xBB, sizeof (*v) + ((GET_NUM_ELEM (&v->vec) - 1)
357 * sizeof (rtunion)));
358 #endif
360 free (v);
363 /* Freeing a tree node is almost, but not quite, as simple as calling free.
364 Mostly we need to let the language clean up its lang_specific bits. */
366 static void
367 ggc_free_tree (t)
368 struct ggc_tree *t;
370 switch (TREE_CODE_CLASS (TREE_CODE (&t->tree)))
372 case 'd': /* A decl node. */
373 case 't': /* A type node. */
374 lang_cleanup_tree (&t->tree);
375 break;
378 #ifdef GGC_DUMP
379 fprintf (dump, "collect tree %p\n", &t->tree);
380 #endif
381 #ifdef GGC_POISON
382 memset(&t->tree.common, 0xCC, sizeof(t->tree.common));
383 #endif
385 free (t);
388 /* Freeing a string is as simple as calling free. */
390 static void
391 ggc_free_string (s)
392 struct ggc_string *s;
394 #ifdef GGC_DUMP
395 fprintf(dump, "collect string %p\n", s->string);
396 #endif
397 #ifdef GGC_POISON
398 s->magic_mark = 0xDDDDDDDD;
399 s->string[0] = 0xDD;
400 #endif
402 free (s);
405 /* Mark a node. */
407 void
408 ggc_mark_rtx (r)
409 rtx r;
411 const char *fmt;
412 int i;
414 if (r == NULL_RTX || r->gc_mark)
415 return;
416 r->gc_mark = 1;
418 /* ??? If (some of) these are really pass-dependant info, do we have
419 any right poking our noses in? */
420 switch (GET_CODE (r))
422 case JUMP_INSN:
423 ggc_mark_rtx (JUMP_LABEL (r));
424 break;
425 case CODE_LABEL:
426 ggc_mark_rtx (LABEL_REFS (r));
427 break;
428 case LABEL_REF:
429 ggc_mark_rtx (LABEL_NEXTREF (r));
430 ggc_mark_rtx (CONTAINING_INSN (r));
431 break;
432 case ADDRESSOF:
433 ggc_mark_tree (ADDRESSOF_DECL (r));
434 break;
435 case CONST_DOUBLE:
436 ggc_mark_rtx (CONST_DOUBLE_CHAIN (r));
437 break;
438 case NOTE:
439 switch (NOTE_LINE_NUMBER (r))
441 case NOTE_INSN_RANGE_START:
442 case NOTE_INSN_RANGE_END:
443 case NOTE_INSN_LIVE:
444 ggc_mark_rtx (NOTE_RANGE_INFO (r));
445 break;
447 default:
448 if (NOTE_LINE_NUMBER (r) >= 0)
449 ggc_mark_string (NOTE_SOURCE_FILE (r));
450 break;
452 break;
454 default:
455 break;
458 for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i)
460 switch (*fmt)
462 case 'e': case 'u':
463 ggc_mark_rtx (XEXP (r, i));
464 break;
465 case 'V': case 'E':
466 ggc_mark_rtvec (XVEC (r, i));
467 break;
468 case 'S': case 's':
469 ggc_mark_string (XSTR (r, i));
470 break;
475 void
476 ggc_mark_rtvec (v)
477 rtvec v;
479 int i;
481 if (v == NULL || v->gc_mark)
482 return;
483 v->gc_mark = 1;
485 i = GET_NUM_ELEM (v);
486 while (--i >= 0)
487 ggc_mark_rtx (RTVEC_ELT (v, i));
490 void
491 ggc_mark_tree (t)
492 tree t;
494 if (t == NULL_TREE || t->common.gc_mark)
495 return;
496 t->common.gc_mark = 1;
498 /* Bits from common. */
499 ggc_mark_tree (TREE_TYPE (t));
500 ggc_mark_tree (TREE_CHAIN (t));
502 /* Some nodes require special handling. */
503 switch (TREE_CODE (t))
505 case TREE_LIST:
506 ggc_mark_tree (TREE_PURPOSE (t));
507 ggc_mark_tree (TREE_VALUE (t));
508 return;
510 case TREE_VEC:
512 int i = TREE_VEC_LENGTH (t);
513 while (--i >= 0)
514 ggc_mark_tree (TREE_VEC_ELT (t, i));
515 return;
518 case SAVE_EXPR:
519 ggc_mark_tree (TREE_OPERAND (t, 0));
520 ggc_mark_tree (SAVE_EXPR_CONTEXT (t));
521 ggc_mark_rtx (SAVE_EXPR_RTL (t));
522 return;
524 case RTL_EXPR:
525 ggc_mark_rtx (RTL_EXPR_SEQUENCE (t));
526 ggc_mark_rtx (RTL_EXPR_RTL (t));
527 return;
529 case CALL_EXPR:
530 ggc_mark_tree (TREE_OPERAND (t, 0));
531 ggc_mark_tree (TREE_OPERAND (t, 1));
532 ggc_mark_rtx (CALL_EXPR_RTL (t));
533 return;
535 case COMPLEX_CST:
536 ggc_mark_tree (TREE_REALPART (t));
537 ggc_mark_tree (TREE_IMAGPART (t));
538 break;
540 case STRING_CST:
541 ggc_mark_string (TREE_STRING_POINTER (t));
542 break;
544 case PARM_DECL:
545 ggc_mark_rtx (DECL_INCOMING_RTL (t));
546 break;
548 case IDENTIFIER_NODE:
549 ggc_mark_string (IDENTIFIER_POINTER (t));
550 lang_mark_tree (t);
551 return;
553 default:
554 break;
557 /* But in general we can handle them by class. */
558 switch (TREE_CODE_CLASS (TREE_CODE (t)))
560 case 'd': /* A decl node. */
561 ggc_mark_tree (DECL_SIZE (t));
562 ggc_mark_tree (DECL_NAME (t));
563 ggc_mark_tree (DECL_CONTEXT (t));
564 ggc_mark_tree (DECL_ARGUMENTS (t));
565 ggc_mark_tree (DECL_RESULT (t));
566 ggc_mark_tree (DECL_INITIAL (t));
567 ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
568 ggc_mark_tree (DECL_ASSEMBLER_NAME (t));
569 ggc_mark_tree (DECL_SECTION_NAME (t));
570 ggc_mark_tree (DECL_MACHINE_ATTRIBUTES (t));
571 ggc_mark_rtx (DECL_RTL (t));
572 ggc_mark_tree (DECL_VINDEX (t));
573 lang_mark_tree (t);
574 break;
576 case 't': /* A type node. */
577 ggc_mark_tree (TYPE_SIZE (t));
578 ggc_mark_tree (TYPE_SIZE_UNIT (t));
579 ggc_mark_tree (TYPE_ATTRIBUTES (t));
580 ggc_mark_tree (TYPE_VALUES (t));
581 ggc_mark_tree (TYPE_POINTER_TO (t));
582 ggc_mark_tree (TYPE_REFERENCE_TO (t));
583 ggc_mark_tree (TYPE_NAME (t));
584 ggc_mark_tree (TYPE_MIN_VALUE (t));
585 ggc_mark_tree (TYPE_MAX_VALUE (t));
586 ggc_mark_tree (TYPE_NEXT_VARIANT (t));
587 ggc_mark_tree (TYPE_MAIN_VARIANT (t));
588 ggc_mark_tree (TYPE_BINFO (t));
589 ggc_mark_tree (TYPE_NONCOPIED_PARTS (t));
590 ggc_mark_tree (TYPE_CONTEXT (t));
591 lang_mark_tree (t);
592 break;
594 case 'b': /* A lexical block. */
595 ggc_mark_tree (BLOCK_VARS (t));
596 ggc_mark_tree (BLOCK_TYPE_TAGS (t));
597 ggc_mark_tree (BLOCK_SUBBLOCKS (t));
598 ggc_mark_tree (BLOCK_SUPERCONTEXT (t));
599 ggc_mark_tree (BLOCK_ABSTRACT_ORIGIN (t));
600 ggc_mark_rtx (BLOCK_END_NOTE (t));
601 break;
603 case 'c': /* A constant. */
604 ggc_mark_rtx (TREE_CST_RTL (t));
605 break;
607 case 'r': case '<': case '1':
608 case '2': case 'e': case 's': /* Expressions. */
610 int i = tree_code_length[TREE_CODE (t)];
611 while (--i >= 0)
612 ggc_mark_tree (TREE_OPERAND (t, i));
613 break;
616 case 'x':
617 lang_mark_tree (t);
618 break;
622 /* Mark all the elements of the varray V, which contains trees. */
624 void
625 ggc_mark_tree_varray (v)
626 varray_type v;
628 int i;
630 if (v)
631 for (i = v->num_elements - 1; i >= 0; --i)
632 ggc_mark_tree (VARRAY_TREE (v, i));
635 /* Mark the hash table-entry HE. It's key field is really a tree. */
637 static boolean
638 ggc_mark_tree_hash_table_entry (he, k)
639 struct hash_entry *he;
640 hash_table_key k ATTRIBUTE_UNUSED;
642 ggc_mark_tree ((tree) he->key);
643 return true;
646 /* Mark all the elements of the hash-table H, which contains trees. */
648 void
649 ggc_mark_tree_hash_table (ht)
650 struct hash_table *ht;
652 hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0);
655 void
656 ggc_mark_string (s)
657 char *s;
659 unsigned int *magic = (unsigned int *)s - 1;
661 if (s == NULL)
662 return;
664 if ((*magic & ~(unsigned)1) != GGC_STRING_MAGIC)
665 return; /* abort? */
666 *magic = GGC_STRING_MAGIC | 1;
669 /* Mark P, allocated with ggc_alloc. */
671 void
672 ggc_mark (p)
673 void *p;
675 struct ggc_any *a;
676 ptrdiff_t d = (&((struct ggc_any *) 0)->u.c - (char *) 0);
677 a = (struct ggc_any *) (((char*) p) - d);
678 a->mark = 1;
681 /* The top level mark-and-sweep routine. */
683 void
684 ggc_collect ()
686 struct ggc_rtx *r, **rp;
687 struct ggc_rtvec *v, **vp;
688 struct ggc_tree *t, **tp;
689 struct ggc_string *s, **sp;
690 struct ggc_root *x;
691 struct ggc_status *gs;
692 struct ggc_any *a, **ap;
693 int time, n_rtxs, n_trees, n_vecs, n_strings, n_anys;
695 #if 0
696 /* See if it's even worth our while. */
697 if (ggc_chain->bytes_alloced_since_gc < 64*1024)
698 return;
699 #endif
701 if (!quiet_flag)
702 fputs (" {GC ", stderr);
704 time = get_run_time ();
706 /* Clean out all of the GC marks. */
707 for (gs = ggc_chain; gs; gs = gs->next)
709 for (r = gs->rtxs; r != NULL; r = r->chain)
710 r->rtx.gc_mark = 0;
711 for (v = gs->vecs; v != NULL; v = v->chain)
712 v->vec.gc_mark = 0;
713 for (t = gs->trees; t != NULL; t = t->chain)
714 t->tree.common.gc_mark = 0;
715 for (s = gs->strings; s != NULL; s = s->chain)
716 s->magic_mark = GGC_STRING_MAGIC;
717 for (a = gs->anys; a != NULL; a = a->chain)
718 a->mark = 0;
721 /* Mark through all the roots. */
722 for (x = roots; x != NULL; x = x->next)
724 char *elt = x->base;
725 int s = x->size, n = x->nelt;
726 void (*cb) PROTO ((void *)) = x->cb;
727 int i;
729 for (i = 0; i < n; ++i, elt += s)
730 (*cb)(elt);
733 /* Sweep the resulting dead nodes. */
735 /* The RTXs. */
737 rp = &ggc_chain->rtxs;
738 r = ggc_chain->rtxs;
739 n_rtxs = 0;
740 while (r != NULL)
742 struct ggc_rtx *chain = r->chain;
743 if (!r->rtx.gc_mark)
745 ggc_free_rtx (r);
746 *rp = chain;
747 n_rtxs++;
749 else
750 rp = &r->chain;
751 r = chain;
753 *rp = NULL;
754 n_rtxs_collected += n_rtxs;
756 /* The vectors. */
758 vp = &ggc_chain->vecs;
759 v = ggc_chain->vecs;
760 n_vecs = 0;
761 while (v != NULL)
763 struct ggc_rtvec *chain = v->chain;
764 if (!v->vec.gc_mark)
766 ggc_free_rtvec (v);
767 *vp = chain;
768 n_vecs++;
770 else
771 vp = &v->chain;
772 v = chain;
774 *vp = NULL;
775 n_vecs_collected += n_vecs;
777 /* The trees. */
779 tp = &ggc_chain->trees;
780 t = ggc_chain->trees;
781 n_trees = 0;
782 while (t != NULL)
784 struct ggc_tree *chain = t->chain;
785 if (!t->tree.common.gc_mark)
787 ggc_free_tree (t);
788 *tp = chain;
789 n_trees++;
791 else
792 tp = &t->chain;
793 t = chain;
795 *tp = NULL;
796 n_trees_collected += n_trees;
798 /* The strings. */
800 sp = &ggc_chain->strings;
801 s = ggc_chain->strings;
802 n_strings = 0;
803 while (s != NULL)
805 struct ggc_string *chain = s->chain;
806 if (!(s->magic_mark & 1))
808 ggc_free_string (s);
809 *sp = chain;
810 n_strings++;
812 else
813 sp = &s->chain;
814 s = chain;
816 *sp = NULL;
817 n_strings_collected += n_strings;
819 /* The generic data. */
821 ap = &ggc_chain->anys;
822 a = ggc_chain->anys;
823 n_anys = 0;
824 while (a != NULL)
826 struct ggc_any *chain = a->chain;
827 if (!a->mark)
829 free (a);
830 *ap = chain;
831 n_anys++;
833 else
834 ap = &a->chain;
835 a = chain;
837 n_anys_collected += n_anys;
839 ggc_chain->bytes_alloced_since_gc = 0;
841 time = get_run_time () - time;
842 gc_time += time;
844 if (!quiet_flag)
846 time = (time + 500) / 1000;
847 fprintf (stderr, "%dr,%dv,%dt,%ds,%da %d.%03d}", n_rtxs, n_vecs,
848 n_trees, n_strings, n_anys, time / 1000, time % 1000);
852 /* Manipulate global roots that are needed between calls to gc. */
854 void
855 ggc_add_root (base, nelt, size, cb)
856 void *base;
857 int nelt, size;
858 void (*cb) PROTO ((void *));
860 struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof(*x));
862 x->next = roots;
863 x->base = base;
864 x->nelt = nelt;
865 x->size = size;
866 x->cb = cb;
868 roots = x;
871 void
872 ggc_add_rtx_root (base, nelt)
873 rtx *base;
874 int nelt;
876 ggc_add_root (base, nelt, sizeof(rtx), ggc_mark_rtx_ptr);
879 void
880 ggc_add_tree_root (base, nelt)
881 tree *base;
882 int nelt;
884 ggc_add_root (base, nelt, sizeof(tree), ggc_mark_tree_ptr);
887 void
888 ggc_add_string_root (base, nelt)
889 char **base;
890 int nelt;
892 ggc_add_root (base, nelt, sizeof(char *), ggc_mark_string_ptr);
895 /* Add V (a varray full of trees) to the list of GC roots. */
897 void
898 ggc_add_tree_varray_root (base, nelt)
899 varray_type *base;
900 int nelt;
902 ggc_add_root (base, nelt, sizeof (varray_type),
903 ggc_mark_tree_varray_ptr);
906 /* Add HT (a hash-table where ever key is a tree) to the list of GC
907 roots. */
909 void
910 ggc_add_tree_hash_table_root (base, nelt)
911 struct hash_table **base;
912 int nelt;
914 ggc_add_root (base, nelt, sizeof (struct hash_table *),
915 ggc_mark_tree_hash_table_ptr);
918 void
919 ggc_del_root (base)
920 void *base;
922 struct ggc_root *x, **p;
924 p = &roots, x = roots;
925 while (x)
927 if (x->base == base)
929 *p = x->next;
930 free (x);
931 return;
933 p = &x->next;
934 x = x->next;
937 abort();
940 static void
941 ggc_mark_rtx_ptr (elt)
942 void *elt;
944 ggc_mark_rtx (*(rtx *)elt);
947 static void
948 ggc_mark_tree_ptr (elt)
949 void *elt;
951 ggc_mark_tree (*(tree *)elt);
954 /* Type-correct function to pass to ggc_add_root. It just forwards
955 ELT (which is really a char **) to ggc_mark_string. */
957 static void
958 ggc_mark_string_ptr (elt)
959 void *elt;
961 ggc_mark_string (*(char **)elt);
964 /* Type-correct function to pass to ggc_add_root. It just forwards
965 ELT (which is really a varray_type *) to ggc_mark_tree_varray. */
967 static void
968 ggc_mark_tree_varray_ptr (elt)
969 void *elt;
971 ggc_mark_tree_varray (*(varray_type *)elt);
974 /* Type-correct function to pass to ggc_add_root. It just forwards
975 ELT (which is really a struct hash_table **) to
976 ggc_mark_tree_hash_table. */
978 static void
979 ggc_mark_tree_hash_table_ptr (elt)
980 void *elt;
982 ggc_mark_tree_hash_table (*(struct hash_table **) elt);
985 #if 0
986 /* GDB really should have a memory search function. Since this is just
987 for initial debugging, I won't even pretend to get the __data_start
988 to work on any but alpha-dec-linux-gnu. */
989 static void **
990 search_data(void **start, void *target)
992 extern void *__data_start[];
993 void **_end = (void **)sbrk(0);
995 if (start == NULL)
996 start = __data_start;
997 while (start < _end)
999 if (*start == target)
1000 return start;
1001 start++;
1003 return NULL;
1005 #endif