|
|
1.1 root 1: /* Garbage collection primitives for GNU C++.
2: Copyright (C) 1992, 1993 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"
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
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
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
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
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
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: if (flag_vtable_thunks)
388: abort();
389:
390: vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
391: offset = build_component_ref (build_array_ref (vptr, integer_one_node),
392: get_identifier (VTABLE_DELTA_NAME),
393: NULL_TREE, 0);
394: return build (PLUS_EXPR, class_star_type_node, exp,
395: convert (integer_type_node, offset));
396: }
397:
398: /* Given the expression EXP of type `class *', return the
399: type descriptor for the object pointed to by EXP. */
400: tree
401: build_classof (exp)
402: tree exp;
403: {
404: tree type = TREE_TYPE (exp);
405: tree vptr;
406: tree t_desc_entry;
407:
408: if (TREE_CODE (type) != POINTER_TYPE)
409: {
410: error ("`classof' applied to non-pointer type");
411: return error_mark_node;
412: }
413:
414: vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
415: t_desc_entry = build_component_ref (build_array_ref (vptr, integer_one_node),
416: get_identifier (VTABLE_PFN_NAME),
417: NULL_TREE, 0);
418: TREE_TYPE (t_desc_entry) = TYPE_POINTER_TO (__t_desc_type_node);
419: return t_desc_entry;
420: }
421:
422: /* Return the Type_info node associated with the expression EXP. If EXP is
423: a reference to a polymorphic class, return the dynamic type; otherwise
424: return the static type of the expression. */
425: tree
426: build_typeid (exp)
427: tree exp;
428: {
429: tree type;
430:
431: if (exp == error_mark_node)
432: return error_mark_node;
433:
434: type = TREE_TYPE (exp);
435:
436: /* if b is an instance of B, typeid(b) == typeid(B). Do this before
437: reference trickiness. */
438: if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (type) == RECORD_TYPE)
439: return get_typeid (type);
440:
441: /* Apply trivial conversion T -> T& for dereferenced ptrs. */
442: if (TREE_CODE (type) == RECORD_TYPE)
443: type = build_reference_type (type);
444:
445: /* If exp is a reference to polymorphic type, get the real Type_info. */
446: if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type)))
447: {
448: /* build reference to Type_info from vtable. */
449:
450: sorry ("finding Type_info for an object");
451: return error_mark_node;
452: }
453:
454: /* otherwise return the Type_info for the static type of the expr. */
455: return get_typeid (type);
456: }
457:
458: /* Return the Type_info object for TYPE, creating it if necessary. */
459: tree
460: get_typeid (type)
461: tree type;
462: {
463: if (type == error_mark_node)
464: return error_mark_node;
465:
466: /* Is it useful (and/or correct) to have different typeids for `T &'
467: and `T'? */
468: if (TREE_CODE (type) == REFERENCE_TYPE)
469: type = TREE_TYPE (type);
470:
471: /* build reference to static Type_info */
472: #if 1
473: sorry ("finding Type_info for a type");
474: return error_mark_node;
475: #else
476: register tree t = TYPE_TINFO (type);
477:
478: if (t)
479: return t;
480:
481: /* ... */
482:
483: #endif
484: }
485:
486: /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
487: paper. */
488: tree
489: build_dynamic_cast (type, expr)
490: tree type, expr;
491: {
492: enum tree_code tc = TREE_CODE (type);
493: tree exprtype = TREE_TYPE (expr);
494: enum tree_code ec = TREE_CODE (exprtype);
495: tree retval;
496:
497: if (type == error_mark_node || expr == error_mark_node)
498: return error_mark_node;
499:
500: switch (tc)
501: {
502: case POINTER_TYPE:
503: if (TREE_TYPE (type) == void_type_node)
504: break;
505: /* else fall through */
506: case REFERENCE_TYPE:
507: if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
508: && TYPE_SIZE (TREE_TYPE (type)) != NULL_TREE)
509: break;
510: /* else fall through */
511: default:
512: cp_error ("`%#T' is not a valid type argument for dynamic_cast", type);
513: error ("(must be either pointer or reference to defined class or void *)");
514: return error_mark_node;
515: }
516:
517: /* Apply trivial conversion T -> T& for dereferenced ptrs. */
518: if (ec == RECORD_TYPE)
519: {
520: exprtype = build_reference_type (exprtype);
521: ec = REFERENCE_TYPE;
522: }
523:
524: /* the TREE_CODE of exprtype must match that of type. */
525: if (ec != tc)
526: {
527: cp_error ("`%E' (of type `%#T') fails to be of %s type", expr, exprtype,
528: tc == POINTER_TYPE ? "pointer" : "reference");
529: return error_mark_node;
530: }
531:
532: /* If *type is an unambiguous accessible base class of *exprtype,
533: convert statically. */
534: {
535: int distance;
536: tree path;
537:
538: distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
539: &path);
540: if (distance >= 0)
541: return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
542: }
543:
544: /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
545: if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
546: {
547: /* if TYPE is `void *', return pointer to complete object. */
548: if (tc == POINTER_TYPE && TREE_TYPE (type) == void_type_node)
549: {
550: /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
551: if (TREE_CODE (expr) == ADDR_EXPR
552: && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
553: && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
554: return build1 (NOP_EXPR, type, expr);
555:
556: sorry ("finding pointer to complete object");
557: return build1 (NOP_EXPR, type, expr);
558: }
559: else
560: {
561: tree retval;
562:
563: /* If we got here, we can't convert statically. Therefore,
564: dynamic_cast<D&>(b) (b an object) cannot succeed. */
565: if (ec == REFERENCE_TYPE)
566: {
567: if (TREE_CODE (expr) == VAR_DECL
568: && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
569: {
570: cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
571: expr, type);
572: /* cplus_expand_throw (Bad_cast_node); */
573: sorry ("throwing Bad_cast");
574: return error_mark_node;
575: }
576: }
577: /* Ditto for dynamic_cast<D*>(&b). */
578: else if (TREE_CODE (expr) == ADDR_EXPR)
579: {
580: tree op = TREE_OPERAND (expr, 0);
581: if (TREE_CODE (op) == VAR_DECL
582: && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
583: {
584: cp_warning ("dynamic_cast of `%E' to `%#T' can never succeed",
585: expr, type);
586: retval = build_int_2 (0, 0);
587: TREE_TYPE (retval) = type;
588: return retval;
589: }
590: }
591: /* Build run-time conversion. */
592: sorry ("run-time type conversion");
593: retval = build_int_2 (0, 0);
594: TREE_TYPE (retval) = type;
595: return retval;
596: }
597: }
598:
599: cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
600: expr, exprtype, type);
601: return error_mark_node;
602: }
603:
604: /* Build and initialize various sorts of descriptors. Every descriptor
605: node has a name associated with it (the name created by mangling).
606: For this reason, we use the identifier as our access to the __*_desc
607: nodes, instead of sticking them directly in the types. Otherwise we
608: would burden all built-in types (and pointer types) with slots that
609: we don't necessarily want to use.
610:
611: For each descriptor we build, we build a variable that contains
612: the descriptor's information. When we need this info at runtime,
613: all we need is access to these variables.
614:
615: Note: these constructors always return the address of the descriptor
616: info, since that is simplest for their mutual interaction. */
617:
618: static tree
619: build_generic_desc (decl, elems)
620: tree decl;
621: tree elems;
622: {
623: tree init = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, elems);
624: TREE_CONSTANT (init) = 1;
625: TREE_STATIC (init) = 1;
626: TREE_READONLY (init) = 1;
627:
628: DECL_INITIAL (decl) = init;
629: TREE_STATIC (decl) = 1;
630: layout_decl (decl, 0);
631: finish_decl (decl, init, 0, 0);
632:
633: return IDENTIFIER_AS_DESC (DECL_NAME (decl));
634: }
635:
636: /* Build an initializer for a __t_desc node. So that we can take advantage
637: of recursion, we accept NULL for TYPE.
638: DEFINITION is greater than zero iff we must define the type descriptor
639: (as opposed to merely referencing it). 1 means treat according to
640: #pragma interface/#pragma implementation rules. 2 means define as
641: global and public, no matter what. */
642: tree
643: build_t_desc (type, definition)
644: tree type;
645: int definition;
646: {
647: tree tdecl;
648: tree tname, name_string;
649: tree elems, fields;
650: tree parents, vbases, offsets, ivars, methods, target_type;
651: int method_count = 0, field_count = 0;
652:
653: if (type == NULL_TREE)
654: return NULL_TREE;
655:
656: tname = build_t_desc_overload (type);
657: if (IDENTIFIER_AS_DESC (tname)
658: && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
659: return IDENTIFIER_AS_DESC (tname);
660:
661: tdecl = lookup_name (tname, 0);
662: if (tdecl == NULL_TREE)
663: {
664: tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
665: DECL_EXTERNAL (tdecl) = 1;
666: TREE_PUBLIC (tdecl) = 1;
667: tdecl = pushdecl_top_level (tdecl);
668: }
669: /* If we previously defined it, return the defined result. */
670: else if (definition && DECL_INITIAL (tdecl))
671: return IDENTIFIER_AS_DESC (tname);
672:
673: if (definition)
674: {
675: tree taggr = type;
676: /* Let T* and T& be written only when T is written (if T is an aggr).
677: We do this for const, but not for volatile, since volatile
678: is rare and const is not. */
679: if (!TYPE_VOLATILE (taggr)
680: && (TREE_CODE (taggr) == POINTER_TYPE
681: || TREE_CODE (taggr) == REFERENCE_TYPE)
682: && IS_AGGR_TYPE (TREE_TYPE (taggr)))
683: taggr = TREE_TYPE (taggr);
684:
685: /* If we know that we don't need to write out this type's
686: vtable, then don't write out it's dossier. Somebody
687: else will take care of that. */
688: if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
689: {
690: if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
691: {
692: TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
693: && CLASSTYPE_INTERFACE_KNOWN (taggr);
694: TREE_STATIC (tdecl) = 1;
695: DECL_EXTERNAL (tdecl) = 0;
696: }
697: else
698: {
699: if (write_virtuals != 0)
700: TREE_PUBLIC (tdecl) = 1;
701: }
702: }
703: else
704: {
705: DECL_EXTERNAL (tdecl) = 0;
706: TREE_STATIC (tdecl) = 1;
707: TREE_PUBLIC (tdecl) = (definition > 1);
708: }
709: }
710: SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
711: if (!definition || DECL_EXTERNAL (tdecl))
712: {
713: /* That's it! */
714: finish_decl (tdecl, 0, 0, 0);
715: return IDENTIFIER_AS_DESC (tname);
716: }
717:
718: /* Show that we are defining the t_desc for this type. */
719: DECL_INITIAL (tdecl) = error_mark_node;
720:
721: parents = build_tree_list (NULL_TREE, integer_zero_node);
722: vbases = build_tree_list (NULL_TREE, integer_zero_node);
723: offsets = build_tree_list (NULL_TREE, integer_zero_node);
724: methods = NULL_TREE;
725: ivars = NULL_TREE;
726:
727: if (TYPE_LANG_SPECIFIC (type))
728: {
729: int i = CLASSTYPE_N_BASECLASSES (type);
730: tree method_vec = CLASSTYPE_METHOD_VEC (type);
731: tree *meth, *end;
732: tree binfos = TYPE_BINFO_BASETYPES (type);
733: tree vb = CLASSTYPE_VBASECLASSES (type);
734:
735: while (--i >= 0)
736: parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
737:
738: while (vb)
739: {
740: vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
741: offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
742: vb = TREE_CHAIN (vb);
743: }
744:
745: if (method_vec)
746: for (meth = TREE_VEC_END (method_vec),
747: end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
748: if (*meth)
749: {
750: methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
751: method_count++;
752: }
753: }
754:
755: if (IS_AGGR_TYPE (type))
756: {
757: for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
758: if (TREE_CODE (fields) == FIELD_DECL
759: || TREE_CODE (fields) == VAR_DECL)
760: {
761: ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
762: field_count++;
763: }
764: ivars = nreverse (ivars);
765: }
766:
767: parents = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), parents, 0);
768: vbases = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), vbases, 0);
769: offsets = finish_table (0, integer_type_node, offsets, 0);
770: if (methods == NULL_TREE)
771: methods = null_pointer_node;
772: else
773: methods = build_unary_op (ADDR_EXPR,
774: finish_table (0, __m_desc_type_node, methods, 0),
775: 0);
776: if (ivars == NULL_TREE)
777: ivars = null_pointer_node;
778: else
779: ivars = build_unary_op (ADDR_EXPR,
780: finish_table (0, __i_desc_type_node, ivars, 0),
781: 0);
782: if (TREE_TYPE (type))
783: target_type = build_t_desc (TREE_TYPE (type), definition);
784: else
785: target_type = integer_zero_node;
786:
787: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
788:
789: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
790: tree_cons (NULL_TREE,
791: TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
792: /* really should use bitfield initialization here. */
793: tree_cons (NULL_TREE, integer_zero_node,
794: tree_cons (NULL_TREE, target_type,
795: tree_cons (NULL_TREE, build_int_2 (field_count, 2),
796: tree_cons (NULL_TREE, build_int_2 (method_count, 2),
797: tree_cons (NULL_TREE, ivars,
798: tree_cons (NULL_TREE, methods,
799: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
800: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
801: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
802: return build_generic_desc (tdecl, elems);
803: }
804:
805: /* Build an initializer for a __i_desc node. */
806: tree
807: build_i_desc (decl)
808: tree decl;
809: {
810: tree elems, name_string;
811: tree taggr;
812:
813: name_string = DECL_NAME (decl);
814: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
815:
816: /* Now decide whether this ivar should cause it's type to get
817: def'd or ref'd in this file. If the type we are looking at
818: has a proxy definition, we look at the proxy (i.e., a
819: `foo *' is equivalent to a `foo'). */
820: taggr = TREE_TYPE (decl);
821:
822: if ((TREE_CODE (taggr) == POINTER_TYPE
823: || TREE_CODE (taggr) == REFERENCE_TYPE)
824: && TYPE_VOLATILE (taggr) == 0)
825: taggr = TREE_TYPE (taggr);
826:
827: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
828: tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
829: build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
830: ! IS_AGGR_TYPE (taggr)))));
831: taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
832: TREE_CONSTANT (taggr) = 1;
833: TREE_STATIC (taggr) = 1;
834: TREE_READONLY (taggr) = 1;
835: return taggr;
836: }
837:
838: /* Build an initializer for a __m_desc node. */
839: tree
840: build_m_desc (decl)
841: tree decl;
842: {
843: tree taggr, elems, name_string;
844: tree parm_count, req_count, vindex, vcontext;
845: tree parms;
846: int p_count, r_count;
847: tree parm_types = NULL_TREE;
848:
849: for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
850: parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
851: {
852: taggr = TREE_VALUE (parms);
853: if ((TREE_CODE (taggr) == POINTER_TYPE
854: || TREE_CODE (taggr) == REFERENCE_TYPE)
855: && TYPE_VOLATILE (taggr) == 0)
856: taggr = TREE_TYPE (taggr);
857:
858: parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
859: ! IS_AGGR_TYPE (taggr)),
860: parm_types);
861: if (TREE_PURPOSE (parms) == NULL_TREE)
862: r_count++;
863: }
864:
865: parm_types = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node),
866: nreverse (parm_types), 0);
867: parm_count = build_int_2 (p_count, 0);
868: req_count = build_int_2 (r_count, 0);
869:
870: if (DECL_VINDEX (decl))
871: vindex = DECL_VINDEX (decl);
872: else
873: vindex = integer_zero_node;
874: if (DECL_CONTEXT (decl)
875: && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
876: vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
877: else
878: vcontext = integer_zero_node;
879: name_string = DECL_NAME (decl);
880: if (name_string == NULL)
881: name_string = DECL_ASSEMBLER_NAME (decl);
882: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
883:
884: /* Now decide whether the return type of this mvar
885: should cause it's type to get def'd or ref'd in this file.
886: If the type we are looking at has a proxy definition,
887: we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */
888: taggr = TREE_TYPE (TREE_TYPE (decl));
889:
890: if ((TREE_CODE (taggr) == POINTER_TYPE
891: || TREE_CODE (taggr) == REFERENCE_TYPE)
892: && TYPE_VOLATILE (taggr) == 0)
893: taggr = TREE_TYPE (taggr);
894:
895: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
896: tree_cons (NULL_TREE, vindex,
897: tree_cons (NULL_TREE, vcontext,
898: tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
899: ! IS_AGGR_TYPE (taggr)),
900: tree_cons (NULL_TREE, build_c_cast (TYPE_POINTER_TO (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
901: tree_cons (NULL_TREE, parm_count,
902: tree_cons (NULL_TREE, req_count,
903: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
904:
905: taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
906: TREE_CONSTANT (taggr) = 1;
907: TREE_STATIC (taggr) = 1;
908: TREE_READONLY (taggr) = 1;
909: return taggr;
910: }
911:
912: /* Conditionally emit code to set up an unwind-protect for the
913: garbage collector. If this function doesn't do anything that involves
914: the garbage collector, then do nothing. Otherwise, call __gc_push
915: at the beginning and __gc_pop at the end.
916:
917: NOTE! The __gc_pop function must operate transparently, since
918: it comes where the logical return label lies. This means that
919: at runtime *it* must preserve any return value registers. */
920:
921: void
922: expand_gc_prologue_and_epilogue ()
923: {
924: extern tree maybe_gc_cleanup;
925: struct rtx_def *last_parm_insn, *mark;
926: extern struct rtx_def *get_last_insn ();
927: extern struct rtx_def *get_first_nonparm_insn ();
928: extern struct rtx_def *previous_insn ();
929: tree action;
930:
931: /* If we didn't need the obstack, don't cons any space. */
932: if (current_function_obstack_index == 0
933: || current_function_obstack_usage == 0)
934: return;
935:
936: mark = get_last_insn ();
937: last_parm_insn = get_first_nonparm_insn ();
938: if (last_parm_insn == 0) last_parm_insn = mark;
939: else last_parm_insn = previous_insn (last_parm_insn);
940:
941: action = build_function_call (gc_push_fndecl,
942: build_tree_list (NULL_TREE, size_int (++current_function_obstack_index)));
943: expand_expr_stmt (action);
944:
945: reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
946:
947: /* This will be expanded as a cleanup. */
948: TREE_VALUE (maybe_gc_cleanup)
949: = build_function_call (gc_pop_fndecl, NULL_TREE);
950: }
951:
952: /* Some day we'll use this function as a call-back and clean
953: up all the unnecessary gc dribble that we otherwise create. */
954: void
955: lang_expand_end_bindings (first, last)
956: struct rtx_def *first, *last;
957: {
958: }
959:
960: void
961: init_gc_processing ()
962: {
963: tree parmtypes = hash_tree_chain (class_star_type_node,
964: hash_tree_chain (integer_type_node, NULL_TREE));
965: gc_protect_fndecl = define_function ("__gc_protect",
966: build_function_type (class_star_type_node, parmtypes),
967: NOT_BUILT_IN, 0, 0);
968:
969: parmtypes = hash_tree_chain (integer_type_node, NULL_TREE);
970: gc_unprotect_fndecl = define_function ("__gc_unprotect",
971: build_function_type (void_type_node, parmtypes),
972: NOT_BUILT_IN, 0, 0);
973:
974: gc_push_fndecl = define_function ("__gc_push",
975: TREE_TYPE (gc_unprotect_fndecl),
976: NOT_BUILT_IN, 0, 0);
977:
978: gc_pop_fndecl = define_function ("__gc_pop",
979: build_function_type (void_type_node,
980: void_list_node),
981: NOT_BUILT_IN, 0, 0);
982: gc_nonobject = build_int_2 (0x80000000, 0);
983: gc_visible = build_int_2 (0x40000000, 0);
984: gc_white = integer_zero_node;
985: gc_offwhite = build_int_2 (0x10000000, 0);
986: gc_grey = build_int_2 (0x20000000, 0);
987: gc_black = build_int_2 (0x30000000, 0);
988: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.