xref: /386bsd/usr/src/usr.bin/g++/cc1plus/cp-gc.c (revision a2142627)
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 
5 This file is part of GNU CC.
6 
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the 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 
30 extern tree define_function ();
31 extern 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.  */
35 tree gc_protect_fndecl;
36 
37 /* This is the function decl for the (pseudo-builtin) __gc_unprotect
38    function.  Args are (int index); void return.  */
39 tree gc_unprotect_fndecl;
40 
41 /* This is the function decl for the (pseudo-builtin) __gc_push
42    function.  Args are (int length); void return.  */
43 tree gc_push_fndecl;
44 
45 /* This is the function decl for the (pseudo-builtin) __gc_pop
46    function.  Args are void; void return.  */
47 tree gc_pop_fndecl;
48 
49 /* Special integers that are used to represent bits in gc-safe objects.  */
50 tree gc_nonobject;
51 tree gc_visible;
52 tree gc_white;
53 tree gc_offwhite;
54 tree gc_grey;
55 tree gc_black;
56 
57 /* in c-common.c */
58 extern tree combine_strings PROTO((tree));
59 
60 /* Predicate that returns non-zero if TYPE needs some kind of
61    entry for the GC.  Returns zero otherwise.  */
62 int
type_needs_gc_entry(type)63 type_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.  */
123 int
value_safe_from_gc(to,from)124 value_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 
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.  */
274 void
build_static_gc_entry(decl,type)275 build_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 
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 
307 tree
protect_value_from_gc(to,from)308 protect_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 
372 /* Given the expression EXP of type `class *', return the head
373    of the object pointed to by EXP.  */
374 tree
build_headof(exp)375 build_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.  */
397 tree
build_classof(exp)398 build_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 
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 
433 static tree
build_generic_desc(decl,elems)434 build_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.  */
457 tree
build_t_desc(type,definition)458 build_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.  */
611 tree
build_i_desc(decl)612 build_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.  */
644 tree
build_m_desc(decl)645 build_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 
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 
726 void
expand_gc_prologue_and_epilogue()727 expand_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.  */
759 void
lang_expand_end_bindings(first,last)760 lang_expand_end_bindings (first, last)
761      struct rtx_def *first, *last;
762 {
763 }
764 
765 void
init_gc_processing()766 init_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 }
794