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