Fixed gcc2 to co-exist with gcc1
[unix-history] / gnu / usr.bin / cc / cc1plus / cp-gc.c
CommitLineData
9bf86ebb
PR
1/* Garbage collection primitives for GNU C++.
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann (tiemann@cygnus.com)
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21
22#include "config.h"
23#include "tree.h"
24#include "cp-tree.h"
25#include "flags.h"
26
27#undef NULL
28#define NULL 0
29
30extern tree define_function ();
31extern tree build_t_desc_overload ();
32
33/* This is the function decl for the (pseudo-builtin) __gc_protect
34 function. Args are (class *value, int index); Returns value. */
35tree gc_protect_fndecl;
36
37/* This is the function decl for the (pseudo-builtin) __gc_unprotect
38 function. Args are (int index); void return. */
39tree gc_unprotect_fndecl;
40
41/* This is the function decl for the (pseudo-builtin) __gc_push
42 function. Args are (int length); void return. */
43tree gc_push_fndecl;
44
45/* This is the function decl for the (pseudo-builtin) __gc_pop
46 function. Args are void; void return. */
47tree gc_pop_fndecl;
48
49/* Special integers that are used to represent bits in gc-safe objects. */
50tree gc_nonobject;
51tree gc_visible;
52tree gc_white;
53tree gc_offwhite;
54tree gc_grey;
55tree gc_black;
56
57/* in c-common.c */
58extern tree combine_strings PROTO((tree));
59\f
60/* Predicate that returns non-zero if TYPE needs some kind of
61 entry for the GC. Returns zero otherwise. */
62int
63type_needs_gc_entry (type)
64 tree type;
65{
66 tree ttype = type;
67
68 if (! flag_gc || type == error_mark_node)
69 return 0;
70
71 /* Aggregate types need gc entries if any of their members
72 need gc entries. */
73 if (IS_AGGR_TYPE (type))
74 {
75 tree binfos;
76 tree fields = TYPE_FIELDS (type);
77 int i;
78
79 /* We don't care about certain pointers. Pointers
80 to virtual baseclasses are always up front. We also
81 cull out virtual function table pointers because it's
82 easy, and it simplifies the logic.*/
83 while (fields
84 && (DECL_NAME (fields) == NULL_TREE
85 || VFIELD_NAME_P (DECL_NAME (fields))
86 || VBASE_NAME_P (DECL_NAME (fields))
87 || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits")))
88 fields = TREE_CHAIN (fields);
89
90 while (fields)
91 {
92 if (type_needs_gc_entry (TREE_TYPE (fields)))
93 return 1;
94 fields = TREE_CHAIN (fields);
95 }
96
97 binfos = TYPE_BINFO_BASETYPES (type);
98 if (binfos)
99 for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
100 if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))
101 return 1;
102
103 return 0;
104 }
105
106 while (TREE_CODE (ttype) == ARRAY_TYPE
107 && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE)
108 ttype = TREE_TYPE (ttype);
109 if ((TREE_CODE (ttype) == POINTER_TYPE
110 || TREE_CODE (ttype) == ARRAY_TYPE
111 || TREE_CODE (ttype) == REFERENCE_TYPE)
112 && IS_AGGR_TYPE (TREE_TYPE (ttype))
113 && CLASSTYPE_DOSSIER (TREE_TYPE (ttype)))
114 return 1;
115
116 return 0;
117}
118
119/* Predicate that returns non-zero iff FROM is safe from the GC.
120
121 If TO is nonzero, it means we know that FROM is being stored
122 in TO, which make make it safe. */
123int
124value_safe_from_gc (to, from)
125 tree to, from;
126{
127 /* First, return non-zero for easy cases: parameters,
128 static variables. */
129 if (TREE_CODE (from) == PARM_DECL
130 || (TREE_CODE (from) == VAR_DECL
131 && TREE_STATIC (from)))
132 return 1;
133
134 /* If something has its address taken, it cannot be
135 in the heap, so it doesn't need to be protected. */
136 if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from))
137 return 1;
138
139 /* If we are storing into a static variable, then what
140 we store will be safe from the gc. */
141 if (to && TREE_CODE (to) == VAR_DECL
142 && TREE_STATIC (to))
143 return 1;
144
145 /* Now recurse on structure of FROM. */
146 switch (TREE_CODE (from))
147 {
148 case COMPONENT_REF:
149 /* These guys are special, and safe. */
150 if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL
151 && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))
152 || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))))
153 return 1;
154 /* fall through... */
155 case NOP_EXPR:
156 case CONVERT_EXPR:
157 case NON_LVALUE_EXPR:
158 case WITH_CLEANUP_EXPR:
159 case SAVE_EXPR:
160 case PREDECREMENT_EXPR:
161 case PREINCREMENT_EXPR:
162 case POSTDECREMENT_EXPR:
163 case POSTINCREMENT_EXPR:
164 if (value_safe_from_gc (to, TREE_OPERAND (from, 0)))
165 return 1;
166 break;
167
168 case VAR_DECL:
169 case PARM_DECL:
170 /* We can safely pass these things as parameters to functions. */
171 if (to == 0)
172 return 1;
173
174 case ARRAY_REF:
175 case INDIRECT_REF:
176 case RESULT_DECL:
177 case OFFSET_REF:
178 case CALL_EXPR:
179 case METHOD_CALL_EXPR:
180 break;
181
182 case COMPOUND_EXPR:
183 case TARGET_EXPR:
184 if (value_safe_from_gc (to, TREE_OPERAND (from, 1)))
185 return 1;
186 break;
187
188 case COND_EXPR:
189 if (value_safe_from_gc (to, TREE_OPERAND (from, 1))
190 && value_safe_from_gc (to, TREE_OPERAND (from, 2)))
191 return 1;
192 break;
193
194 case PLUS_EXPR:
195 case MINUS_EXPR:
196 if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0)))
197 || value_safe_from_gc (to, TREE_OPERAND (from, 0)))
198 && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0
199 || value_safe_from_gc (to, TREE_OPERAND (from, 1))))
200 return 1;
201 break;
202
203 case RTL_EXPR:
204 /* Every time we build an RTL_EXPR in the front-end, we must
205 ensure that everything in it is safe from the garbage collector.
206 ??? This has only been done for `build_new'. */
207 return 1;
208
209 default:
210 my_friendly_abort (41);
211 }
212
213 if (to == 0)
214 return 0;
215
216 /* FROM wasn't safe. But other properties of TO might make it safe. */
217 switch (TREE_CODE (to))
218 {
219 case VAR_DECL:
220 case PARM_DECL:
221 /* We already culled out static VAR_DECLs above. */
222 return 0;
223
224 case COMPONENT_REF:
225 /* These guys are special, and safe. */
226 if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL
227 && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))
228 || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))))
229 return 1;
230 /* fall through... */
231
232 case NOP_EXPR:
233 case NON_LVALUE_EXPR:
234 case WITH_CLEANUP_EXPR:
235 case SAVE_EXPR:
236 case PREDECREMENT_EXPR:
237 case PREINCREMENT_EXPR:
238 case POSTDECREMENT_EXPR:
239 case POSTINCREMENT_EXPR:
240 return value_safe_from_gc (TREE_OPERAND (to, 0), from);
241
242 case COMPOUND_EXPR:
243 case TARGET_EXPR:
244 return value_safe_from_gc (TREE_OPERAND (to, 1), from);
245
246 case COND_EXPR:
247 return (value_safe_from_gc (TREE_OPERAND (to, 1), from)
248 && value_safe_from_gc (TREE_OPERAND (to, 2), from));
249
250 case INDIRECT_REF:
251 case ARRAY_REF:
252 /* This used to be 0, but our current restricted model
253 allows this to be 1. We'll never get arrays this way. */
254 return 1;
255
256 default:
257 my_friendly_abort (42);
258 }
259
260 /* Catch-all case is that TO/FROM is not safe. */
261 return 0;
262}
263\f
264/* Function to build a static GC entry for DECL. TYPE is DECL's type.
265
266 For objects of type `class *', this is just an entry in the
267 static vector __PTR_LIST__.
268
269 For objects of type `class[]', this requires building an entry
270 in the static vector __ARR_LIST__.
271
272 For aggregates, this records all fields of type `class *'
273 and `class[]' in the respective lists above. */
274void
275build_static_gc_entry (decl, type)
276 tree decl;
277 tree type;
278{
279 /* Now, figure out what sort of entry to build. */
280 if (TREE_CODE (type) == POINTER_TYPE
281 || TREE_CODE (type) == REFERENCE_TYPE)
282 assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl)));
283 else if (TREE_CODE (type) == RECORD_TYPE)
284 {
285 tree ref = get_temp_name (build_reference_type (type), 1);
286 DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl);
287 TREE_CONSTANT (DECL_INITIAL (ref)) = 1;
288 finish_decl (ref, DECL_INITIAL (ref), 0, 0);
289 }
290 else
291 {
292 /* Not yet implemented.
293
294 Cons up a static variable that holds address and length info
295 and add that to ___ARR_LIST__. */
296 my_friendly_abort (43);
297 }
298}
299\f
300/* Protect FROM from the GC, assuming FROM is going to be
301 stored into TO. We handle three cases for TO here:
302
303 case 1: TO is a stack variable.
304 case 2: TO is zero (which means it is a parameter).
305 case 3: TO is a return value. */
306
307tree
308protect_value_from_gc (to, from)
309 tree to, from;
310{
311 if (to == 0)
312 {
313 tree cleanup;
314
315 to = get_temp_regvar (TREE_TYPE (from), from);
316
317 /* Convert from integer to list form since we'll use it twice. */
318 DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
319 cleanup = build_function_call (gc_unprotect_fndecl,
320 DECL_GC_OFFSET (to));
321
322 if (! expand_decl_cleanup (to, cleanup))
323 {
324 compiler_error ("cannot unprotect parameter in this scope");
325 return error_mark_node;
326 }
327 }
328
329 /* Should never need to protect a value that's headed for static storage. */
330 if (TREE_STATIC (to))
331 my_friendly_abort (44);
332
333 switch (TREE_CODE (to))
334 {
335 case COMPONENT_REF:
336 case INDIRECT_REF:
337 return protect_value_from_gc (TREE_OPERAND (to, 0), from);
338
339 case VAR_DECL:
340 case PARM_DECL:
341 {
342 tree rval;
343 if (DECL_GC_OFFSET (to) == NULL_TREE)
344 {
345 /* Because of a cast or a conversion, we might stick
346 a value into a variable that would not normally
347 have a GC entry. */
348 DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index);
349 }
350
351 if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST)
352 {
353 DECL_GC_OFFSET (to)
354 = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
355 }
356
357 current_function_obstack_usage = 1;
358 rval = build_function_call (gc_protect_fndecl,
359 tree_cons (NULL_TREE, from,
360 DECL_GC_OFFSET (to)));
361 TREE_TYPE (rval) = TREE_TYPE (from);
362 return rval;
363 }
364 }
365
366 /* If we fall through the switch, assume we lost. */
367 my_friendly_abort (45);
368 /* NOTREACHED */
369 return NULL_TREE;
370}
371\f
372/* Given the expression EXP of type `class *', return the head
373 of the object pointed to by EXP. */
374tree
375build_headof (exp)
376 tree exp;
377{
378 tree type = TREE_TYPE (exp);
379 tree vptr, offset;
380
381 if (TREE_CODE (type) != POINTER_TYPE)
382 {
383 error ("`headof' applied to non-pointer type");
384 return error_mark_node;
385 }
386
387 vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
388 offset = build_component_ref (build_array_ref (vptr, integer_one_node),
389 get_identifier (VTABLE_DELTA_NAME),
390 NULL_TREE, 0);
391 return build (PLUS_EXPR, class_star_type_node, exp,
392 convert (integer_type_node, offset));
393}
394
395/* Given the expression EXP of type `class *', return the
396 type descriptor for the object pointed to by EXP. */
397tree
398build_classof (exp)
399 tree exp;
400{
401 tree type = TREE_TYPE (exp);
402 tree vptr;
403 tree t_desc_entry;
404
405 if (TREE_CODE (type) != POINTER_TYPE)
406 {
407 error ("`classof' applied to non-pointer type");
408 return error_mark_node;
409 }
410
411 vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
412 t_desc_entry = build_component_ref (build_array_ref (vptr, integer_one_node),
413 get_identifier (VTABLE_PFN_NAME),
414 NULL_TREE, 0);
415 TREE_TYPE (t_desc_entry) = TYPE_POINTER_TO (__t_desc_type_node);
416 return t_desc_entry;
417}
418\f
419/* Build and initialize various sorts of descriptors. Every descriptor
420 node has a name associated with it (the name created by mangling).
421 For this reason, we use the identifier as our access to the __*_desc
422 nodes, instead of sticking them directly in the types. Otherwise we
423 would burden all built-in types (and pointer types) with slots that
424 we don't necessarily want to use.
425
426 For each descriptor we build, we build a variable that contains
427 the descriptor's information. When we need this info at runtime,
428 all we need is access to these variables.
429
430 Note: these constructors always return the address of the descriptor
431 info, since that is simplest for their mutual interaction. */
432
433static tree
434build_generic_desc (decl, elems)
435 tree decl;
436 tree elems;
437{
438 tree init = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, elems);
439 TREE_CONSTANT (init) = 1;
440 TREE_STATIC (init) = 1;
441 TREE_READONLY (init) = 1;
442
443 DECL_INITIAL (decl) = init;
444 TREE_STATIC (decl) = 1;
445 layout_decl (decl, 0);
446 finish_decl (decl, init, 0, 0);
447
448 return IDENTIFIER_AS_DESC (DECL_NAME (decl));
449}
450
451/* Build an initializer for a __t_desc node. So that we can take advantage
452 of recursion, we accept NULL for TYPE.
453 DEFINITION is greater than zero iff we must define the type descriptor
454 (as opposed to merely referencing it). 1 means treat according to
455 #pragma interface/#pragma implementation rules. 2 means define as
456 global and public, no matter what. */
457tree
458build_t_desc (type, definition)
459 tree type;
460 int definition;
461{
462 tree tdecl;
463 tree tname, name_string;
464 tree elems, fields;
465 tree parents, vbases, offsets, ivars, methods, target_type;
466 int method_count = 0, field_count = 0;
467
468 if (type == NULL_TREE)
469 return NULL_TREE;
470
471 tname = build_t_desc_overload (type);
472 if (IDENTIFIER_AS_DESC (tname)
473 && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
474 return IDENTIFIER_AS_DESC (tname);
475
476 tdecl = lookup_name (tname, 0);
477 if (tdecl == NULL_TREE)
478 {
479 tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
480 DECL_EXTERNAL (tdecl) = 1;
481 TREE_PUBLIC (tdecl) = 1;
482 tdecl = pushdecl_top_level (tdecl);
483 }
484 /* If we previously defined it, return the defined result. */
485 else if (definition && DECL_INITIAL (tdecl))
486 return IDENTIFIER_AS_DESC (tname);
487
488 if (definition)
489 {
490 tree taggr = type;
491 /* Let T* and T& be written only when T is written (if T is an aggr).
492 We do this for const, but not for volatile, since volatile
493 is rare and const is not. */
494 if (!TYPE_VOLATILE (taggr)
495 && (TREE_CODE (taggr) == POINTER_TYPE
496 || TREE_CODE (taggr) == REFERENCE_TYPE)
497 && IS_AGGR_TYPE (TREE_TYPE (taggr)))
498 taggr = TREE_TYPE (taggr);
499
500 /* If we know that we don't need to write out this type's
501 vtable, then don't write out it's dossier. Somebody
502 else will take care of that. */
503 if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
504 {
505 if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
506 {
507 TREE_PUBLIC (tdecl) = !(CLASSTYPE_INTERFACE_ONLY (taggr)
508 || CLASSTYPE_INTERFACE_UNKNOWN (taggr));
509 TREE_STATIC (tdecl) = 1;
510 DECL_EXTERNAL (tdecl) = 0;
511 }
512 else
513 {
514 if (write_virtuals != 0)
515 TREE_PUBLIC (tdecl) = 1;
516 }
517 }
518 else
519 {
520 DECL_EXTERNAL (tdecl) = 0;
521 TREE_STATIC (tdecl) = 1;
522 TREE_PUBLIC (tdecl) = (definition > 1);
523 }
524 }
525 SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
526 if (!definition || DECL_EXTERNAL (tdecl))
527 {
528 /* That's it! */
529 finish_decl (tdecl, 0, 0, 0);
530 return IDENTIFIER_AS_DESC (tname);
531 }
532
533 /* Show that we are defining the t_desc for this type. */
534 DECL_INITIAL (tdecl) = error_mark_node;
535
536 parents = build_tree_list (NULL_TREE, integer_zero_node);
537 vbases = build_tree_list (NULL_TREE, integer_zero_node);
538 offsets = build_tree_list (NULL_TREE, integer_zero_node);
539 methods = NULL_TREE;
540 ivars = NULL_TREE;
541
542 if (TYPE_LANG_SPECIFIC (type))
543 {
544 int i = CLASSTYPE_N_BASECLASSES (type);
545 tree method_vec = CLASSTYPE_METHOD_VEC (type);
546 tree *meth, *end;
547 tree binfos = TYPE_BINFO_BASETYPES (type);
548 tree vb = CLASSTYPE_VBASECLASSES (type);
549
550 while (--i >= 0)
551 parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
552
553 while (vb)
554 {
555 vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
556 offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
557 vb = TREE_CHAIN (vb);
558 }
559
560 if (method_vec)
561 for (meth = TREE_VEC_END (method_vec),
562 end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
563 if (*meth)
564 {
565 methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
566 method_count++;
567 }
568 }
569
570 if (IS_AGGR_TYPE (type))
571 {
572 for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
573 if (TREE_CODE (fields) == FIELD_DECL
574 || TREE_CODE (fields) == VAR_DECL)
575 {
576 ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
577 field_count++;
578 }
579 ivars = nreverse (ivars);
580 }
581
582 parents = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), parents, 0);
583 vbases = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), vbases, 0);
584 offsets = finish_table (0, integer_type_node, offsets, 0);
585 methods = finish_table (0, __m_desc_type_node, methods, 0);
586 ivars = finish_table (0, __i_desc_type_node, ivars, 0);
587 if (TREE_TYPE (type))
588 target_type = build_t_desc (TREE_TYPE (type), definition);
589 else
590 target_type = integer_zero_node;
591
592 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
593
594 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
595 tree_cons (NULL_TREE,
596 TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
597 /* really should use bitfield initialization here. */
598 tree_cons (NULL_TREE, integer_zero_node,
599 tree_cons (NULL_TREE, target_type,
600 tree_cons (NULL_TREE, build_int_2 (field_count, 2),
601 tree_cons (NULL_TREE, build_int_2 (method_count, 2),
602 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, ivars, 0),
603 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, methods, 0),
604 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
605 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
606 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
607 return build_generic_desc (tdecl, elems);
608}
609
610/* Build an initializer for a __i_desc node. */
611tree
612build_i_desc (decl)
613 tree decl;
614{
615 tree elems, name_string;
616 tree taggr;
617
618 name_string = DECL_NAME (decl);
619 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
620
621 /* Now decide whether this ivar should cause it's type to get
622 def'd or ref'd in this file. If the type we are looking at
623 has a proxy definition, we look at the proxy (i.e., a
624 `foo *' is equivalent to a `foo'). */
625 taggr = TREE_TYPE (decl);
626
627 if ((TREE_CODE (taggr) == POINTER_TYPE
628 || TREE_CODE (taggr) == REFERENCE_TYPE)
629 && TYPE_VOLATILE (taggr) == 0)
630 taggr = TREE_TYPE (taggr);
631
632 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
633 tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
634 build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
635 ! IS_AGGR_TYPE (taggr)))));
636 taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
637 TREE_CONSTANT (taggr) = 1;
638 TREE_STATIC (taggr) = 1;
639 TREE_READONLY (taggr) = 1;
640 return taggr;
641}
642
643/* Build an initializer for a __m_desc node. */
644tree
645build_m_desc (decl)
646 tree decl;
647{
648 tree taggr, elems, name_string;
649 tree parm_count, req_count, vindex, vcontext;
650 tree parms;
651 int p_count, r_count;
652 tree parm_types = NULL_TREE;
653
654 for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
655 parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
656 {
657 taggr = TREE_VALUE (parms);
658 if ((TREE_CODE (taggr) == POINTER_TYPE
659 || TREE_CODE (taggr) == REFERENCE_TYPE)
660 && TYPE_VOLATILE (taggr) == 0)
661 taggr = TREE_TYPE (taggr);
662
663 parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
664 ! IS_AGGR_TYPE (taggr)),
665 parm_types);
666 if (TREE_PURPOSE (parms) == NULL_TREE)
667 r_count++;
668 }
669
670 parm_types = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node),
671 nreverse (parm_types), 0);
672 parm_count = build_int_2 (p_count, 0);
673 req_count = build_int_2 (r_count, 0);
674
675 if (DECL_VINDEX (decl))
676 vindex = DECL_VINDEX (decl);
677 else
678 vindex = integer_zero_node;
679 if (DECL_CONTEXT (decl)
680 && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
681 vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
682 else
683 vcontext = integer_zero_node;
684 name_string = DECL_NAME (decl);
685 if (name_string == NULL)
686 name_string = DECL_ASSEMBLER_NAME (decl);
687 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
688
689 /* Now decide whether the return type of this mvar
690 should cause it's type to get def'd or ref'd in this file.
691 If the type we are looking at has a proxy definition,
692 we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */
693 taggr = TREE_TYPE (TREE_TYPE (decl));
694
695 if ((TREE_CODE (taggr) == POINTER_TYPE
696 || TREE_CODE (taggr) == REFERENCE_TYPE)
697 && TYPE_VOLATILE (taggr) == 0)
698 taggr = TREE_TYPE (taggr);
699
700 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
701 tree_cons (NULL_TREE, vindex,
702 tree_cons (NULL_TREE, vcontext,
703 tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
704 ! IS_AGGR_TYPE (taggr)),
705 tree_cons (NULL_TREE, build_c_cast (TYPE_POINTER_TO (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
706 tree_cons (NULL_TREE, parm_count,
707 tree_cons (NULL_TREE, req_count,
708 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
709
710 taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
711 TREE_CONSTANT (taggr) = 1;
712 TREE_STATIC (taggr) = 1;
713 TREE_READONLY (taggr) = 1;
714 return taggr;
715}
716\f
717/* Conditionally emit code to set up an unwind-protect for the
718 garbage collector. If this function doesn't do anything that involves
719 the garbage collector, then do nothing. Otherwise, call __gc_push
720 at the beginning and __gc_pop at the end.
721
722 NOTE! The __gc_pop function must operate transparently, since
723 it comes where the logical return label lies. This means that
724 at runtime *it* must preserve any return value registers. */
725
726void
727expand_gc_prologue_and_epilogue ()
728{
729 extern tree maybe_gc_cleanup;
730 struct rtx_def *last_parm_insn, *mark;
731 extern struct rtx_def *get_last_insn ();
732 extern struct rtx_def *get_first_nonparm_insn ();
733 extern struct rtx_def *previous_insn ();
734 tree action;
735
736 /* If we didn't need the obstack, don't cons any space. */
737 if (current_function_obstack_index == 0
738 || current_function_obstack_usage == 0)
739 return;
740
741 mark = get_last_insn ();
742 last_parm_insn = get_first_nonparm_insn ();
743 if (last_parm_insn == 0) last_parm_insn = mark;
744 else last_parm_insn = previous_insn (last_parm_insn);
745
746 action = build_function_call (gc_push_fndecl,
747 build_tree_list (NULL_TREE, size_int (++current_function_obstack_index)));
748 expand_expr_stmt (action);
749
750 reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
751
752 /* This will be expanded as a cleanup. */
753 TREE_VALUE (maybe_gc_cleanup)
754 = build_function_call (gc_pop_fndecl, NULL_TREE);
755}
756
757/* Some day we'll use this function as a call-back and clean
758 up all the unnecessary gc dribble that we otherwise create. */
759void
760lang_expand_end_bindings (first, last)
761 struct rtx_def *first, *last;
762{
763}
764\f
765void
766init_gc_processing ()
767{
768 tree parmtypes = hash_tree_chain (class_star_type_node,
769 hash_tree_chain (integer_type_node, NULL_TREE));
770 gc_protect_fndecl = define_function ("__gc_protect",
771 build_function_type (class_star_type_node, parmtypes),
772 NOT_BUILT_IN, 0, 0);
773
774 parmtypes = hash_tree_chain (integer_type_node, NULL_TREE);
775 gc_unprotect_fndecl = define_function ("__gc_unprotect",
776 build_function_type (void_type_node, parmtypes),
777 NOT_BUILT_IN, 0, 0);
778
779 gc_push_fndecl = define_function ("__gc_push",
780 TREE_TYPE (gc_unprotect_fndecl),
781 NOT_BUILT_IN, 0, 0);
782
783 gc_pop_fndecl = define_function ("__gc_pop",
784 build_function_type (void_type_node,
785 void_list_node),
786 NOT_BUILT_IN, 0, 0);
787 gc_nonobject = build_int_2 (0x80000000, 0);
788 gc_visible = build_int_2 (0x40000000, 0);
789 gc_white = integer_zero_node;
790 gc_offwhite = build_int_2 (0x10000000, 0);
791 gc_grey = build_int_2 (0x20000000, 0);
792 gc_black = build_int_2 (0x30000000, 0);
793}