source: trunk/third/gcc/cp/gc.c @ 8834

Revision 8834, 45.5 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, which included commits to RCS files with non-trunk default branches.
Line 
1/* Garbage collection primitives for GNU C++.
2   Copyright (C) 1992, 1993, 1994, 1995 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, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA.  */
21
22
23#include "config.h"
24#include "tree.h"
25#include "cp-tree.h"
26#include "flags.h"
27#include "output.h"
28
29#undef NULL
30#define NULL 0
31
32extern tree define_function ();
33extern tree build_t_desc_overload ();
34extern struct obstack *permanent_obstack;
35
36/* This is the function decl for the (pseudo-builtin) __gc_protect
37   function.  Args are (class *value, int index); Returns value.  */
38tree gc_protect_fndecl;
39
40/* This is the function decl for the (pseudo-builtin) __gc_unprotect
41   function.  Args are (int index); void return.  */
42tree gc_unprotect_fndecl;
43
44/* This is the function decl for the (pseudo-builtin) __gc_push
45   function.  Args are (int length); void return.  */
46tree gc_push_fndecl;
47
48/* This is the function decl for the (pseudo-builtin) __gc_pop
49   function.  Args are void; void return.  */
50tree gc_pop_fndecl;
51
52/* Special integers that are used to represent bits in gc-safe objects.  */
53tree gc_nonobject;
54tree gc_visible;
55tree gc_white;
56tree gc_offwhite;
57tree gc_grey;
58tree gc_black;
59
60/* in c-common.c */
61extern tree combine_strings PROTO((tree));
62
63/* Predicate that returns non-zero if TYPE needs some kind of
64   entry for the GC.  Returns zero otherwise.  */
65int
66type_needs_gc_entry (type)
67     tree type;
68{
69  tree ttype = type;
70
71  if (! flag_gc || type == error_mark_node)
72    return 0;
73
74  /* Aggregate types need gc entries if any of their members
75     need gc entries.  */
76  if (IS_AGGR_TYPE (type))
77    {
78      tree binfos;
79      tree fields = TYPE_FIELDS (type);
80      int i;
81
82      /* We don't care about certain pointers.  Pointers
83         to virtual baseclasses are always up front.  We also
84         cull out virtual function table pointers because it's
85         easy, and it simplifies the logic.*/
86      while (fields
87             && (DECL_NAME (fields) == NULL_TREE
88                 || VFIELD_NAME_P (DECL_NAME (fields))
89                 || VBASE_NAME_P (DECL_NAME (fields))
90                 || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits")))
91        fields = TREE_CHAIN (fields);
92
93      while (fields)
94        {
95          if (type_needs_gc_entry (TREE_TYPE (fields)))
96            return 1;
97          fields = TREE_CHAIN (fields);
98        }
99
100      binfos = TYPE_BINFO_BASETYPES (type);
101      if (binfos)
102        for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
103          if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))
104            return 1;
105
106      return 0;
107    }
108
109  while (TREE_CODE (ttype) == ARRAY_TYPE
110         && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE)
111    ttype = TREE_TYPE (ttype);
112  if ((TREE_CODE (ttype) == POINTER_TYPE
113       || TREE_CODE (ttype) == ARRAY_TYPE
114       || TREE_CODE (ttype) == REFERENCE_TYPE)
115      && IS_AGGR_TYPE (TREE_TYPE (ttype))
116      && CLASSTYPE_RTTI (TREE_TYPE (ttype)))
117    return 1;
118
119  return 0;
120}
121
122/* Predicate that returns non-zero iff FROM is safe from the GC.
123   
124   If TO is nonzero, it means we know that FROM is being stored
125   in TO, which make make it safe.  */
126int
127value_safe_from_gc (to, from)
128     tree to, from;
129{
130  /* First, return non-zero for easy cases: parameters,
131     static variables.  */
132  if (TREE_CODE (from) == PARM_DECL
133      || (TREE_CODE (from) == VAR_DECL
134          && TREE_STATIC (from)))
135    return 1;
136
137  /* If something has its address taken, it cannot be
138     in the heap, so it doesn't need to be protected.  */
139  if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from))
140    return 1;
141
142  /* If we are storing into a static variable, then what
143     we store will be safe from the gc.  */
144  if (to && TREE_CODE (to) == VAR_DECL
145      && TREE_STATIC (to))
146    return 1;
147
148  /* Now recurse on structure of FROM.  */
149  switch (TREE_CODE (from))
150    {
151    case COMPONENT_REF:
152      /* These guys are special, and safe.  */
153      if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL
154          && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))
155              || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))))
156        return 1;
157      /* fall through...  */
158    case NOP_EXPR:
159    case CONVERT_EXPR:
160    case NON_LVALUE_EXPR:
161    case WITH_CLEANUP_EXPR:
162    case SAVE_EXPR:
163    case PREDECREMENT_EXPR:
164    case PREINCREMENT_EXPR:
165    case POSTDECREMENT_EXPR:
166    case POSTINCREMENT_EXPR:
167      if (value_safe_from_gc (to, TREE_OPERAND (from, 0)))
168        return 1;
169      break;
170
171    case VAR_DECL:
172    case PARM_DECL:
173      /* We can safely pass these things as parameters to functions.  */
174      if (to == 0)
175        return 1;
176
177    case ARRAY_REF:
178    case INDIRECT_REF:
179    case RESULT_DECL:
180    case OFFSET_REF:
181    case CALL_EXPR:
182    case METHOD_CALL_EXPR:
183      break;
184
185    case COMPOUND_EXPR:
186    case TARGET_EXPR:
187      if (value_safe_from_gc (to, TREE_OPERAND (from, 1)))
188        return 1;
189      break;
190
191    case COND_EXPR:
192      if (value_safe_from_gc (to, TREE_OPERAND (from, 1))
193          && value_safe_from_gc (to, TREE_OPERAND (from, 2)))
194        return 1;
195      break;
196
197    case PLUS_EXPR:
198    case MINUS_EXPR:
199      if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0)))
200           || value_safe_from_gc (to, TREE_OPERAND (from, 0)))
201          && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0
202              || value_safe_from_gc (to, TREE_OPERAND (from, 1))))
203        return 1;
204      break;
205
206    case RTL_EXPR:
207      /* Every time we build an RTL_EXPR in the front-end, we must
208         ensure that everything in it is safe from the garbage collector.
209         ??? This has only been done for `build_new'.  */
210      return 1;
211
212    default:
213      my_friendly_abort (41);
214    }
215
216  if (to == 0)
217    return 0;
218
219  /* FROM wasn't safe.  But other properties of TO might make it safe.  */
220  switch (TREE_CODE (to))
221    {
222    case VAR_DECL:
223    case PARM_DECL:
224      /* We already culled out static VAR_DECLs above.  */
225      return 0;
226
227    case COMPONENT_REF:
228      /* These guys are special, and safe.  */
229      if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL
230          && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))
231              || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))))
232        return 1;
233      /* fall through...  */
234
235    case NOP_EXPR:
236    case NON_LVALUE_EXPR:
237    case WITH_CLEANUP_EXPR:
238    case SAVE_EXPR:
239    case PREDECREMENT_EXPR:
240    case PREINCREMENT_EXPR:
241    case POSTDECREMENT_EXPR:
242    case POSTINCREMENT_EXPR:
243      return value_safe_from_gc (TREE_OPERAND (to, 0), from);
244
245    case COMPOUND_EXPR:
246    case TARGET_EXPR:
247      return value_safe_from_gc (TREE_OPERAND (to, 1), from);
248
249    case COND_EXPR:
250      return (value_safe_from_gc (TREE_OPERAND (to, 1), from)
251              && value_safe_from_gc (TREE_OPERAND (to, 2), from));
252
253    case INDIRECT_REF:
254    case ARRAY_REF:
255      /* This used to be 0, but our current restricted model
256         allows this to be 1.  We'll never get arrays this way.  */
257      return 1;
258
259    default:
260      my_friendly_abort (42);
261    }
262
263  /* Catch-all case is that TO/FROM is not safe.  */
264  return 0;
265}
266
267/* Function to build a static GC entry for DECL.  TYPE is DECL's type.
268
269   For objects of type `class *', this is just an entry in the
270   static vector __PTR_LIST__.
271
272   For objects of type `class[]', this requires building an entry
273   in the static vector __ARR_LIST__.
274
275   For aggregates, this records all fields of type `class *'
276   and `class[]' in the respective lists above.  */
277void
278build_static_gc_entry (decl, type)
279     tree decl;
280     tree type;
281{
282  /* Now, figure out what sort of entry to build.  */
283  if (TREE_CODE (type) == POINTER_TYPE
284      || TREE_CODE (type) == REFERENCE_TYPE)
285    assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl)));
286  else if (TREE_CODE (type) == RECORD_TYPE)
287    {
288      tree ref = get_temp_name (build_reference_type (type), 1);
289      DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl);
290      TREE_CONSTANT (DECL_INITIAL (ref)) = 1;
291      cp_finish_decl (ref, DECL_INITIAL (ref), NULL_TREE, 0, 0);
292    }
293  else
294    {
295      /* Not yet implemented.
296         
297         Cons up a static variable that holds address and length info
298         and add that to ___ARR_LIST__.  */
299      my_friendly_abort (43);
300    }
301}
302
303/* Protect FROM from the GC, assuming FROM is going to be
304   stored into TO.  We handle three cases for TO here:
305
306   case 1: TO is a stack variable.
307   case 2: TO is zero (which means it is a parameter).
308   case 3: TO is a return value.  */
309
310tree
311protect_value_from_gc (to, from)
312     tree to, from;
313{
314  if (to == 0)
315    {
316      tree cleanup;
317
318      to = get_temp_regvar (TREE_TYPE (from), from);
319
320      /* Convert from integer to list form since we'll use it twice.  */
321      DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
322      cleanup = build_function_call (gc_unprotect_fndecl,
323                                     DECL_GC_OFFSET (to));
324
325      if (! cp_expand_decl_cleanup (to, cleanup))
326        {
327          compiler_error ("cannot unprotect parameter in this scope");
328          return error_mark_node;
329        }
330    }
331
332  /* Should never need to protect a value that's headed for static storage.  */
333  if (TREE_STATIC (to))
334    my_friendly_abort (44);
335
336  switch (TREE_CODE (to))
337    {
338    case COMPONENT_REF:
339    case INDIRECT_REF:
340      return protect_value_from_gc (TREE_OPERAND (to, 0), from);
341
342    case VAR_DECL:
343    case PARM_DECL:
344      {
345        tree rval;
346        if (DECL_GC_OFFSET (to) == NULL_TREE)
347          {
348            /* Because of a cast or a conversion, we might stick
349               a value into a variable that would not normally
350               have a GC entry.  */
351            DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index);
352          }
353
354        if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST)
355          {
356            DECL_GC_OFFSET (to)
357              = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
358          }
359
360        current_function_obstack_usage = 1;
361        rval = build_function_call (gc_protect_fndecl,
362                                    tree_cons (NULL_TREE, from,
363                                               DECL_GC_OFFSET (to)));
364        TREE_TYPE (rval) = TREE_TYPE (from);
365        return rval;
366      }
367    }
368
369  /* If we fall through the switch, assume we lost.  */
370  my_friendly_abort (45);
371  /* NOTREACHED */
372  return NULL_TREE;
373}
374
375/* Given the expression EXP of type `class *', return the head
376   of the object pointed to by EXP.  */
377tree
378build_headof (exp)
379     tree exp;
380{
381  tree type = TREE_TYPE (exp);
382  tree vptr, offset;
383
384  if (TREE_CODE (type) != POINTER_TYPE)
385    {
386      error ("`headof' applied to non-pointer type");
387      return error_mark_node;
388    }
389  type = TREE_TYPE (type);
390
391  if (!TYPE_VIRTUAL_P (type) || CLASSTYPE_VFIELD (type) == NULL_TREE)
392    return exp;
393
394  vptr = fold (size_binop (PLUS_EXPR,
395           size_binop (FLOOR_DIV_EXPR,
396             DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (type)),
397             size_int (BITS_PER_UNIT)),
398           exp));
399  vptr = build1 (INDIRECT_REF, build_pointer_type (vtable_entry_type), vptr);
400
401  if (flag_vtable_thunks)
402    offset = build_array_ref (vptr, integer_zero_node);
403  else
404    offset = build_component_ref (build_array_ref (vptr, integer_zero_node),
405                                  delta_identifier,
406                                  NULL_TREE, 0);
407
408  type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
409                             TREE_THIS_VOLATILE (exp));
410  return build (PLUS_EXPR, type, exp,
411                convert (ptrdiff_type_node, offset));
412}
413
414/* Return the type_info node associated with the expression EXP.  If EXP is
415   a reference to a polymorphic class, return the dynamic type; otherwise
416   return the static type of the expression.  */
417tree
418build_typeid (exp)
419     tree exp;
420{
421  tree type;
422
423  if (!flag_rtti)
424    cp_error ("cannot take typeid of object when -frtti is not specified");
425
426  if (exp == error_mark_node)
427    return error_mark_node;
428
429  type = TREE_TYPE (exp);
430
431  /* Strip top-level cv-qualifiers.  */
432  type = TYPE_MAIN_VARIANT (type);
433
434  /* if b is an instance of B, typeid(b) == typeid(B).  Do this before
435     reference trickiness.  */
436  if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (type) == RECORD_TYPE)
437    return get_typeid (type);
438
439  /* peel back references, so they match. */
440  if (TREE_CODE (type) == REFERENCE_TYPE)
441    type = TREE_TYPE (type);
442
443  /* Peel off cv qualifiers. */
444  type = TYPE_MAIN_VARIANT (type);
445
446  /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
447  if (TREE_CODE (type) == RECORD_TYPE)
448    type = build_reference_type (type);
449
450  /* If exp is a reference to polymorphic type, get the real type_info.  */
451  if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type)))
452    {
453      /* build reference to type_info from vtable.  */
454      tree t;
455
456      if (flag_vtable_thunks)
457        t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_one_node);
458      else
459        t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_zero_node);
460
461      TREE_TYPE (t) = build_pointer_type (__class_desc_type_node);
462      t = build_indirect_ref (t, NULL);
463      return t;
464    }
465
466  /* otherwise return the type_info for the static type of the expr.  */
467  return get_typeid (type);
468}
469
470/* Return the type_info object for TYPE, creating it if necessary.  */
471tree
472get_typeid (type)
473     tree type;
474{
475  tree t, td;
476
477  if (type == error_mark_node)
478    return error_mark_node;
479 
480  /* Is it useful (and/or correct) to have different typeids for `T &'
481     and `T'?  */
482  if (TREE_CODE (type) == REFERENCE_TYPE)
483    type = TREE_TYPE (type);
484
485  td = build_t_desc (type, 1);
486  if (td == error_mark_node)
487    return error_mark_node;
488
489  t = TREE_OPERAND (td, 0);
490  return t;
491}
492
493/* Get a bad_cast node for the program to throw...
494
495   See libstdc++::exception{,.cc} for __bad_cast_object */
496tree
497get_bad_cast_node ()
498{
499  static tree t;
500  if (t == NULL_TREE
501      && (t = lookup_name (get_identifier ("__bad_cast_object"), 0))
502         == NULL_TREE)
503    {
504      error ("you must #include <typeinfo>");
505      return error_mark_node;
506    }
507  return t;
508}
509
510/* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
511   paper.  */
512tree
513build_dynamic_cast (type, expr)
514     tree type, expr;
515{
516  enum tree_code tc = TREE_CODE (type);
517  tree exprtype = TREE_TYPE (expr);
518  enum tree_code ec = TREE_CODE (exprtype);
519  tree retval;
520
521  if (type == error_mark_node || expr == error_mark_node)
522    return error_mark_node;
523 
524  switch (tc)
525    {
526    case POINTER_TYPE:
527      if (ec == REFERENCE_TYPE)
528        {
529          expr = convert_from_reference (expr);
530          exprtype = TREE_TYPE (expr);
531          ec = TREE_CODE (exprtype);
532        }
533      if (ec != POINTER_TYPE)
534        goto fail;
535      if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
536        goto fail;
537      if (TYPE_SIZE (TREE_TYPE (exprtype)) == 0)
538        goto fail;
539      if (TREE_READONLY (TREE_TYPE (exprtype)) &&
540          ! TYPE_READONLY (TREE_TYPE (type)))
541        goto fail;
542      if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
543        break;
544      /* else fall through */
545    case REFERENCE_TYPE:
546      if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
547          && TYPE_SIZE (TREE_TYPE (type)) != NULL_TREE)
548        break;
549      /* else fall through */
550    default:
551      goto fail;
552    }
553
554  /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
555  if (ec == RECORD_TYPE)
556    {
557      exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
558                                     TREE_THIS_VOLATILE (expr));
559      exprtype = build_reference_type (exprtype);
560      expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
561                                   LOOKUP_NORMAL, NULL_TREE);
562      ec = REFERENCE_TYPE;
563    }
564
565  if (tc == REFERENCE_TYPE)
566    {
567      if (ec != REFERENCE_TYPE)
568        goto fail;
569      if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
570        goto fail;
571      if (TYPE_SIZE (TREE_TYPE (exprtype)) == 0)
572        goto fail;
573    }
574
575  /* If *type is an unambiguous accessible base class of *exprtype,
576     convert statically.  */
577  {
578    int distance;
579    tree path;
580
581    distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
582                                  &path);
583    if (distance >= 0)
584      return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
585  }
586
587  /* Otherwise *exprtype must be a polymorphic class (have a vtbl).  */
588  if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
589    {
590      /* if TYPE is `void *', return pointer to complete object.  */
591      if (tc == POINTER_TYPE
592          && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
593        {
594          /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b.  */
595          if (TREE_CODE (expr) == ADDR_EXPR
596              && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
597              && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
598            return build1 (NOP_EXPR, type, expr);
599
600          return build_headof (expr);
601        }
602      else
603        {
604          tree retval;
605          tree result, td1, td2, elems, tmp1, expr1;
606
607          /* If we got here, we can't convert statically.  Therefore,
608             dynamic_cast<D&>(b) (b an object) cannot succeed.  */
609          if (ec == REFERENCE_TYPE)
610            {
611              if (TREE_CODE (expr) == VAR_DECL
612                  && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
613                {
614                  cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
615                              expr, type);
616                  return build_throw (get_bad_cast_node ());
617                }
618            }
619          /* Ditto for dynamic_cast<D*>(&b).  */
620          else if (TREE_CODE (expr) == ADDR_EXPR)
621            {
622              tree op = TREE_OPERAND (expr, 0);
623              if (TREE_CODE (op) == VAR_DECL
624                  && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
625                {
626                  cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
627                              expr, type);
628                  retval = build_int_2 (0, 0);
629                  TREE_TYPE (retval) = type;
630                  return retval;
631                }
632            }
633
634          expr1 = expr;
635          if (tc == REFERENCE_TYPE)
636            expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
637
638          /* Build run-time conversion.  */
639          expr1 = build_headof (expr1);
640
641          if (ec == POINTER_TYPE)
642            td1 = build_typeid (build_indirect_ref (expr, NULL_PTR));
643          else
644            td1 = build_typeid (expr);
645         
646          if (tc == POINTER_TYPE)
647            td2 = get_typeid (TREE_TYPE (type));
648          else
649            td2 = get_typeid (type);
650
651          elems = tree_cons (NULL_TREE, td2,
652            tree_cons (NULL_TREE, build_int_2 (1, 0),
653              tree_cons (NULL_TREE, expr1, NULL_TREE)));
654          result = build_method_call (td1,
655            get_identifier ("__rtti_match"), elems, NULL_TREE, LOOKUP_NORMAL);
656
657          if (tc == REFERENCE_TYPE)
658            {
659              expr1 = build_throw (get_bad_cast_node ());
660              expr1 = build_compound_expr (tree_cons (NULL_TREE, expr1,
661                                                      build_tree_list (NULL_TREE, convert (type, integer_zero_node))));
662              TREE_TYPE (expr1) = type;
663              return build (COND_EXPR, type, result, result, expr1);
664            }
665
666          /* Now back to the type we want from a void*. */
667          result = convert (type, result);
668          return result;
669        }
670    }
671
672 fail:
673  cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
674            expr, exprtype, type);
675  return error_mark_node;
676}
677
678/* Build and initialize various sorts of descriptors.  Every descriptor
679   node has a name associated with it (the name created by mangling).
680   For this reason, we use the identifier as our access to the __*_desc
681   nodes, instead of sticking them directly in the types.  Otherwise we
682   would burden all built-in types (and pointer types) with slots that
683   we don't necessarily want to use.
684
685   For each descriptor we build, we build a variable that contains
686   the descriptor's information.  When we need this info at runtime,
687   all we need is access to these variables.
688
689   Note: these constructors always return the address of the descriptor
690   info, since that is simplest for their mutual interaction.  */
691
692static tree
693build_generic_desc (tdecl, type, elems)
694     tree tdecl;
695     tree type;
696     tree elems;
697{
698  tree init = elems;
699  int toplev = global_bindings_p ();
700
701  TREE_CONSTANT (init) = 1;
702  TREE_STATIC (init) = 1;
703  TREE_READONLY (init) = 1;
704
705  TREE_TYPE (tdecl) = type;
706  DECL_INITIAL (tdecl) = init;
707  TREE_STATIC (tdecl) = 1;
708  DECL_SIZE (tdecl) = NULL_TREE;
709  layout_decl (tdecl, 0);
710  if (! toplev)
711    push_to_top_level ();
712  cp_finish_decl (tdecl, init, NULL_TREE, 0, 0);
713  if (! toplev)
714    pop_from_top_level ();
715
716  if (! TREE_USED (tdecl))
717    {
718      assemble_external (tdecl);
719      TREE_USED (tdecl) = 1;
720    }
721
722  return IDENTIFIER_AS_DESC (DECL_NAME (tdecl));
723}
724
725/* Build an initializer for a __bltn_desc node.  */
726static tree
727build_bltn_desc (tdecl, type)
728     tree tdecl;
729     tree type;
730{
731  tree elems, t;
732
733  if (type == boolean_type_node)
734    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_BOOL"),
735                      0, 0);
736  else if (type == char_type_node)
737    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_CHAR"),
738                      0, 0);
739  else if (type == short_integer_type_node)
740    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SHORT"),
741                      0, 0);
742  else if (type == integer_type_node)
743    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_INT"),
744                      0, 0);
745  else if (type == long_integer_type_node)
746    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_LONG"),
747                      0, 0);
748  else if (type == long_long_integer_type_node)
749    t = lookup_field (__bltn_desc_type_node,
750                      get_identifier("_RTTI_BI_LONGLONG"), 0, 0);
751  else if (type == float_type_node)
752    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_FLOAT"),
753                      0, 0);
754  else if (type == double_type_node)
755    t = lookup_field (__bltn_desc_type_node,
756                      get_identifier("_RTTI_BI_DOUBLE"), 0, 0);
757  else if (type == long_double_type_node)
758    t = lookup_field (__bltn_desc_type_node,
759                      get_identifier("_RTTI_BI_LDOUBLE"), 0, 0);
760  else if (type == unsigned_char_type_node)
761    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UCHAR"),
762                      0, 0);
763  else if (type == short_unsigned_type_node)
764    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_USHORT"),
765                      0, 0);
766  else if (type == unsigned_type_node)
767    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UINT"),
768                      0, 0);
769  else if (type == long_unsigned_type_node)
770    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_ULONG"),
771                      0, 0);
772  else if (type == long_long_unsigned_type_node)
773    t = lookup_field (__bltn_desc_type_node,
774                      get_identifier("_RTTI_BI_ULONGLONG"), 0, 0);
775  else if (type == signed_char_type_node)
776    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SCHAR"),
777                      0, 0);
778  else if (type == wchar_type_node)
779    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_WCHAR"),
780                      0, 0);
781  else if (type == void_type_node)
782    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_VOID"),
783                      0, 0);
784  else
785    {
786      cp_compiler_error ("type `%T' not handled as a built-in type");
787    }
788
789  elems = tree_cons (NULL_TREE, t, NULL_TREE);
790  return build_generic_desc (tdecl, __bltn_desc_type_node, elems);
791}
792
793/* Build an initializer for a __user_desc node.  */
794static tree
795build_user_desc (tdecl)
796     tree tdecl;
797{
798  tree elems, name_string, t;
799  tree tname = DECL_NAME (tdecl);
800
801  name_string = combine_strings (build_string
802    (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
803  elems = name_string;
804  return build_generic_desc (tdecl, __user_desc_type_node, elems);
805}
806
807/* Build an initializer for a __class_type_info node. */
808static tree
809build_class_desc (tdecl, type)
810     tree tdecl;
811     tree type;
812{
813  tree tname = DECL_NAME (tdecl);
814  tree name_string;
815
816  int i = CLASSTYPE_N_BASECLASSES (type);
817  int n_base = i;
818  int base_cnt = 0;
819  tree binfos = TYPE_BINFO_BASETYPES (type);
820  tree vb = CLASSTYPE_VBASECLASSES (type);
821  tree base, elems, access, offset, isvir;
822  tree base_list, off_list, acc_list, isvir_list;
823  tree t;
824  static tree acc_pub = NULL_TREE;
825  static tree acc_pro = NULL_TREE;
826  static tree acc_pri = NULL_TREE;
827
828  if (acc_pub == NULL_TREE)
829    {
830      acc_pub = lookup_field (__class_desc_type_node,
831                                get_identifier("_RTTI_ACCESS_PUBLIC"), 0, 0);
832      acc_pro = lookup_field (__class_desc_type_node,
833                                get_identifier("_RTTI_ACCESS_PROTECTED"), 0, 0);
834      acc_pri = lookup_field (__class_desc_type_node,
835                                get_identifier("_RTTI_ACCESS_PRIVATE"), 0, 0);
836    }
837
838  base_list = build_tree_list (NULL_TREE, integer_zero_node);
839  off_list = build_tree_list (NULL_TREE, integer_zero_node);
840  acc_list = build_tree_list (NULL_TREE, integer_zero_node);
841  isvir_list = build_tree_list (NULL_TREE, integer_zero_node);
842  while (--i >= 0)
843    {
844      tree binfo = TREE_VEC_ELT (binfos, i);
845
846      base = build_t_desc (BINFO_TYPE (binfo), 1);
847      if (TREE_VIA_VIRTUAL (binfo))
848        {
849          tree t = BINFO_TYPE (binfo);
850          char *name;
851          tree field;
852          int off;
853
854          name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
855          sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
856          field = lookup_field (type, get_identifier (name), 0, 0);
857          offset = size_binop (FLOOR_DIV_EXPR,
858                DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
859        }
860      else
861        offset = BINFO_OFFSET (binfo);
862
863      if (TREE_VIA_PUBLIC (binfo))
864        access = acc_pub;
865      else if (TREE_VIA_PROTECTED (binfo))
866        access = acc_pro;
867      else
868        access = acc_pri;
869      if (TREE_VIA_VIRTUAL (binfo))
870        isvir = build_int_2 (1, 0);
871      else
872        isvir = build_int_2 (0, 0);
873
874      base_list = tree_cons (NULL_TREE, base, base_list);
875      isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
876      acc_list = tree_cons (NULL_TREE, access, acc_list);
877      off_list = tree_cons (NULL_TREE, offset, off_list);
878      base_cnt++;
879    }
880#if 0
881  i = n_base;
882  while (vb)
883    {
884      tree b;
885      access = acc_pub;
886      while (--i >= 0)
887        {
888          b = TREE_VEC_ELT (binfos, i);
889          if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
890            {
891              if (TREE_VIA_PUBLIC (b))
892                access = acc_pub;
893              else if (TREE_VIA_PROTECTED (b))
894                access = acc_pro;
895              else
896                access = acc_pri;
897              break;
898            }
899        }
900      base = build_t_desc (BINFO_TYPE (vb), 1);
901      offset = BINFO_OFFSET (vb);
902      isvir = build_int_2 (1, 0);
903
904      base_list = tree_cons (NULL_TREE, base, base_list);
905      isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
906      acc_list = tree_cons (NULL_TREE, access, acc_list);
907      off_list = tree_cons (NULL_TREE, offset, off_list);
908
909      base_cnt++;
910      vb = TREE_CHAIN (vb);
911    }
912#endif
913  base_list = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
914                            base_list, 0);
915  off_list = finish_table (NULL_TREE, integer_type_node,
916                            off_list, 0);
917  isvir_list = finish_table (NULL_TREE, integer_type_node,
918                            isvir_list, 0);
919  acc_list = finish_table (NULL_TREE, __access_mode_type_node,
920                            acc_list, 0);
921
922
923  name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
924
925  elems = tree_cons (NULL_TREE, name_string,
926            tree_cons (NULL_TREE, default_conversion (base_list),
927              tree_cons (NULL_TREE, default_conversion (off_list),
928                tree_cons (NULL_TREE, default_conversion (isvir_list),
929                  tree_cons (NULL_TREE, default_conversion (acc_list),
930                    tree_cons (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE))))));
931
932  return build_generic_desc (tdecl, __class_desc_type_node, elems);
933}
934
935/* Build an initializer for a __pointer_type_info node.  */
936static tree
937build_ptr_desc (tdecl, type)
938     tree tdecl;
939     tree type;
940{
941  tree t, elems;
942
943  t = TREE_TYPE (type);
944  t = build_t_desc (t, 1);
945  t = build_indirect_ref (t, NULL);
946  elems = tree_cons (NULL_TREE, t, NULL_TREE);
947  return build_generic_desc (tdecl, __ptr_desc_type_node,  elems);
948}
949
950/* Build an initializer for a __attr_type_info node.  */
951static tree
952build_attr_desc (tdecl, type)
953     tree tdecl;
954     tree type;
955{
956  tree elems, t, attrval;
957
958  if (TYPE_READONLY (type))
959    {
960      if (TYPE_VOLATILE (type))
961        attrval = lookup_field (__attr_desc_type_node,
962                                get_identifier("_RTTI_ATTR_CONSTVOL"), 0, 0);
963      else
964        attrval = lookup_field (__attr_desc_type_node,
965                                get_identifier("_RTTI_ATTR_CONST"), 0, 0);
966    }
967  else
968    {
969      if (TYPE_VOLATILE (type))
970        attrval = lookup_field (__attr_desc_type_node,
971                                get_identifier("_RTTI_ATTR_VOLATILE"), 0, 0);
972    }
973  t = build_t_desc (TYPE_MAIN_VARIANT (type), 1);
974  t = build_indirect_ref (t , NULL);
975  elems = tree_cons (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE));
976  return build_generic_desc (tdecl, __attr_desc_type_node,  elems);
977}
978
979/* Build an initializer for a __func_type_info node.  */
980static tree
981build_func_desc (tdecl)
982     tree tdecl;
983{
984  tree elems, name_string;
985  tree tname = DECL_NAME (tdecl);
986
987  name_string = combine_strings (build_string
988    (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
989  elems = name_string;
990  return build_generic_desc (tdecl, __func_desc_type_node,  elems);
991}
992
993/* Build an initializer for a __ptmf_type_info node.  */
994static tree
995build_ptmf_desc (tdecl, type)
996     tree tdecl;
997     tree type;
998{
999  tree elems, name_string;
1000  tree tname = DECL_NAME (tdecl);
1001
1002  name_string = combine_strings (build_string
1003    (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
1004  elems = name_string;
1005  return build_generic_desc (tdecl, __ptmf_desc_type_node,  elems);
1006}
1007
1008/* Build an initializer for a __ptmd_type_info node.  */
1009static tree
1010build_ptmd_desc (tdecl, type)
1011     tree tdecl;
1012     tree type;
1013{
1014  tree tc, t, elems;
1015  tc = build_t_desc (TYPE_OFFSET_BASETYPE (type), 1);
1016  tc = build_indirect_ref (tc , NULL);
1017  t = build_t_desc (TREE_TYPE (type), 1);
1018  t = build_indirect_ref (t , NULL);
1019  elems = tree_cons (NULL_TREE, tc,
1020            tree_cons (NULL_TREE, t, NULL_TREE));
1021  return build_generic_desc (tdecl, __ptmd_desc_type_node,  elems);
1022}
1023
1024struct uninst_st {
1025  tree type;
1026  struct uninst_st *next;
1027};
1028typedef struct uninst_st uninst_node;
1029static uninst_node * uninst_desc = (uninst_node *)NULL;
1030
1031static void
1032add_uninstantiated_desc (type)
1033     tree type;
1034{
1035  uninst_node *t;
1036
1037  t = (uninst_node *) xmalloc (sizeof (struct uninst_st));
1038  t->type = type;
1039  t->next = uninst_desc;
1040  uninst_desc = t;
1041}
1042
1043/* We may choose to link the emitting of certain high use TDs for certain
1044   objects, we do that here.  Return the type to link against if such a
1045   link exists, otherwise just return TYPE.  */
1046
1047tree
1048get_def_to_follow (type)
1049     tree type;
1050{
1051#if 0
1052  /* For now we don't lay out T&, T* TDs with the main TD for the object.  */
1053  /* Let T* and T& be written only when T is written (if T is an aggr).
1054     We do this for const, but not for volatile, since volatile
1055     is rare and const is not.  */
1056  if (!TYPE_VOLATILE (taggr)
1057      && (TREE_CODE (taggr) == POINTER_TYPE
1058          || TREE_CODE (taggr) == REFERENCE_TYPE)
1059      && IS_AGGR_TYPE (TREE_TYPE (taggr)))
1060    taggr = TREE_TYPE (taggr);
1061#endif
1062  return type;
1063}
1064
1065/* build a general type_info node. */
1066tree
1067build_t_desc (type, definition)
1068     tree type;
1069     int definition;
1070{
1071  tree tdecl;
1072  tree tname, name_string;
1073  tree elems;
1074  tree t, tt, taggr;
1075
1076  if (__ptmd_desc_type_node == NULL_TREE)
1077    {
1078      init_type_desc();
1079      if (__ptmd_desc_type_node)
1080        {
1081          for ( ; uninst_desc; uninst_desc = uninst_desc->next )
1082            build_t_desc (uninst_desc->type, 1);
1083        }
1084    }
1085  if (__t_desc_type_node == NULL_TREE)
1086    {
1087      static int warned = 0;
1088      if (! warned)
1089        {
1090          cp_error ("failed to build type descriptor node of '%T', maybe typeinfo.h not included", type);
1091        }
1092      warned = 1;
1093      return error_mark_node;
1094    }
1095  if (__ptmd_desc_type_node == NULL_TREE)
1096    {
1097      add_uninstantiated_desc (type);
1098      definition = 0;
1099    }
1100
1101  push_obstacks (&permanent_obstack, &permanent_obstack);
1102  tname = build_t_desc_overload (type);
1103
1104  if (!IDENTIFIER_AS_DESC (tname))
1105    {
1106      tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1107      DECL_EXTERNAL (tdecl) = 1;
1108      TREE_PUBLIC (tdecl) = 1;
1109      tdecl = pushdecl_top_level (tdecl);
1110      SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1111      if (!definition)
1112        cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1113    }
1114  else
1115    tdecl = TREE_OPERAND (IDENTIFIER_AS_DESC (tname), 0);
1116
1117  /* If it's not a definition, don't do anything more.  */
1118  if (!definition)
1119    return IDENTIFIER_AS_DESC (tname);
1120
1121  /* If it has already been written, don't to anything more.  */
1122  /* Should this be on tdecl? */
1123  if (TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname)))
1124    return IDENTIFIER_AS_DESC (tname);
1125
1126  /* If we previously defined it, return the defined result.  */
1127  if (DECL_INITIAL (tdecl))
1128    return IDENTIFIER_AS_DESC (tname);
1129   
1130  taggr = get_def_to_follow (type);
1131
1132  /* If we know that we don't need to write out this type's
1133     vtable, then don't write out it's type_info.  Somebody
1134     else will take care of that.  */
1135  if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
1136    {
1137      /* Let's play follow the vtable. */
1138      TREE_PUBLIC (tdecl) = CLASSTYPE_INTERFACE_KNOWN (taggr);
1139      DECL_EXTERNAL (tdecl) = CLASSTYPE_INTERFACE_ONLY (taggr);
1140    }
1141  else
1142    {
1143      DECL_EXTERNAL (tdecl) = 0;
1144      TREE_PUBLIC (tdecl) = (definition > 1);
1145    }
1146
1147  if (DECL_EXTERNAL (tdecl))
1148    return IDENTIFIER_AS_DESC (tname);
1149
1150  /* Show that we are defining the t_desc for this type.  */
1151  DECL_INITIAL (tdecl) = error_mark_node;
1152  t = DECL_CONTEXT (tdecl);
1153  if ( t && TREE_CODE_CLASS (TREE_CODE (t)) == 't')
1154    pushclass (t, 2);
1155
1156  if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1157    t = build_attr_desc (tdecl, type);
1158  else if (TREE_CODE (type) == ARRAY_TYPE)
1159    t = build_ptr_desc (tdecl, type);
1160  else if (TREE_CODE (type) == POINTER_TYPE)
1161    {
1162      if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1163        {
1164          type = TREE_TYPE (type);
1165          t = build_ptmd_desc (tdecl, type);
1166        }
1167      else
1168        {
1169          t = build_ptr_desc (tdecl, type);
1170        }
1171    }
1172  else if (TYPE_BUILT_IN (type))
1173    t = build_bltn_desc (tdecl, type);
1174  else if (IS_AGGR_TYPE (type))
1175    {
1176      if (TYPE_PTRMEMFUNC_P (type))
1177        {
1178          t = build_ptmf_desc (tdecl, type);
1179        }
1180      else
1181        {
1182          t = build_class_desc (tdecl, type);
1183        }
1184    }
1185  else if (TREE_CODE (type) == FUNCTION_TYPE)
1186    t = build_func_desc (tdecl);
1187  else
1188    t = build_user_desc (tdecl);
1189
1190  pop_obstacks ();
1191  return t;
1192}
1193
1194#if 0
1195/* This is the old dossier type descriptor generation code, it's much
1196   more extended than rtti. It's reserved for later use. */
1197/* Build an initializer for a __t_desc node.  So that we can take advantage
1198   of recursion, we accept NULL for TYPE.
1199   DEFINITION is greater than zero iff we must define the type descriptor
1200   (as opposed to merely referencing it).  1 means treat according to
1201   #pragma interface/#pragma implementation rules.  2 means define as
1202   global and public, no matter what.  */
1203tree
1204build_t_desc (type, definition)
1205     tree type;
1206     int definition;
1207{
1208  tree tdecl;
1209  tree tname, name_string;
1210  tree elems, fields;
1211  tree parents, vbases, offsets, ivars, methods, target_type;
1212  int method_count = 0, field_count = 0;
1213
1214  if (type == NULL_TREE)
1215    return NULL_TREE;
1216
1217  tname = build_t_desc_overload (type);
1218  if (IDENTIFIER_AS_DESC (tname)
1219      && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
1220    return IDENTIFIER_AS_DESC (tname);
1221
1222  tdecl = lookup_name (tname, 0);
1223  if (tdecl == NULL_TREE)
1224    {
1225      tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1226      DECL_EXTERNAL (tdecl) = 1;
1227      TREE_PUBLIC (tdecl) = 1;
1228      tdecl = pushdecl_top_level (tdecl);
1229    }
1230  /* If we previously defined it, return the defined result.  */
1231  else if (definition && DECL_INITIAL (tdecl))
1232    return IDENTIFIER_AS_DESC (tname);
1233
1234  if (definition)
1235    {
1236      tree taggr = type;
1237      /* Let T* and T& be written only when T is written (if T is an aggr).
1238         We do this for const, but not for volatile, since volatile
1239         is rare and const is not.  */
1240      if (!TYPE_VOLATILE (taggr)
1241          && (TREE_CODE (taggr) == POINTER_TYPE
1242              || TREE_CODE (taggr) == REFERENCE_TYPE)
1243          && IS_AGGR_TYPE (TREE_TYPE (taggr)))
1244        taggr = TREE_TYPE (taggr);
1245
1246      /* If we know that we don't need to write out this type's
1247         vtable, then don't write out it's dossier.  Somebody
1248         else will take care of that.  */
1249      if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
1250        {
1251          if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
1252            {
1253              TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
1254                && CLASSTYPE_INTERFACE_KNOWN (taggr);
1255              DECL_EXTERNAL (tdecl) = 0;
1256            }
1257          else
1258            {
1259              if (write_virtuals != 0)
1260                TREE_PUBLIC (tdecl) = 1;
1261            }
1262        }
1263      else
1264        {
1265          DECL_EXTERNAL (tdecl) = 0;
1266          TREE_PUBLIC (tdecl) = (definition > 1);
1267        }
1268    }
1269  SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1270
1271  if (!definition || DECL_EXTERNAL (tdecl))
1272    {
1273      /* That's it!  */
1274      cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1275      return IDENTIFIER_AS_DESC (tname);
1276    }
1277
1278  /* Show that we are defining the t_desc for this type.  */
1279  DECL_INITIAL (tdecl) = error_mark_node;
1280
1281  parents = build_tree_list (NULL_TREE, integer_zero_node);
1282  vbases = build_tree_list (NULL_TREE, integer_zero_node);
1283  offsets = build_tree_list (NULL_TREE, integer_zero_node);
1284  methods = NULL_TREE;
1285  ivars = NULL_TREE;
1286
1287  if (TYPE_LANG_SPECIFIC (type))
1288    {
1289      int i = CLASSTYPE_N_BASECLASSES (type);
1290      tree method_vec = CLASSTYPE_METHOD_VEC (type);
1291      tree *meth, *end;
1292      tree binfos = TYPE_BINFO_BASETYPES (type);
1293      tree vb = CLASSTYPE_VBASECLASSES (type);
1294
1295      while (--i >= 0)
1296        parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
1297
1298      while (vb)
1299        {
1300          vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
1301          offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
1302          vb = TREE_CHAIN (vb);
1303        }
1304
1305      if (method_vec)
1306        for (meth = TREE_VEC_END (method_vec),
1307             end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
1308          if (*meth)
1309            {
1310              methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
1311              method_count++;
1312            }
1313    }
1314
1315  if (IS_AGGR_TYPE (type))
1316    {
1317      for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
1318        if (TREE_CODE (fields) == FIELD_DECL
1319            || TREE_CODE (fields) == VAR_DECL)
1320          {
1321            ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
1322            field_count++;
1323          }
1324      ivars = nreverse (ivars);
1325    }
1326
1327  parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0);
1328  vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0);
1329  offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0);
1330  if (methods == NULL_TREE)
1331    methods = null_pointer_node;
1332  else
1333    methods = build_unary_op (ADDR_EXPR,
1334                              finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1335                              0);
1336  if (ivars == NULL_TREE)
1337    ivars = null_pointer_node;
1338  else
1339    ivars = build_unary_op (ADDR_EXPR,
1340                            finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1341                            0);
1342  if (TREE_TYPE (type))
1343    target_type = build_t_desc (TREE_TYPE (type), definition);
1344  else
1345    target_type = integer_zero_node;
1346
1347  name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
1348
1349  elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1350           tree_cons (NULL_TREE,
1351                      TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
1352             /* really should use bitfield initialization here.  */
1353             tree_cons (NULL_TREE, integer_zero_node,
1354              tree_cons (NULL_TREE, target_type,
1355               tree_cons (NULL_TREE, build_int_2 (field_count, 2),
1356                tree_cons (NULL_TREE, build_int_2 (method_count, 2),
1357                 tree_cons (NULL_TREE, ivars,
1358                  tree_cons (NULL_TREE, methods,
1359                   tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
1360                    tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
1361                     build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
1362  return build_generic_desc (tdecl, elems);
1363}
1364
1365/* Build an initializer for a __i_desc node.  */
1366tree
1367build_i_desc (decl)
1368     tree decl;
1369{
1370  tree elems, name_string;
1371  tree taggr;
1372
1373  name_string = DECL_NAME (decl);
1374  name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1375
1376  /* Now decide whether this ivar should cause it's type to get
1377     def'd or ref'd in this file.  If the type we are looking at
1378     has a proxy definition, we look at the proxy (i.e., a
1379     `foo *' is equivalent to a `foo').  */
1380  taggr = TREE_TYPE (decl);
1381
1382  if ((TREE_CODE (taggr) == POINTER_TYPE
1383       || TREE_CODE (taggr) == REFERENCE_TYPE)
1384      && TYPE_VOLATILE (taggr) == 0)
1385    taggr = TREE_TYPE (taggr);
1386
1387  elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1388             tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
1389                build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
1390                                                          ! IS_AGGR_TYPE (taggr)))));
1391  taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
1392  TREE_CONSTANT (taggr) = 1;
1393  TREE_STATIC (taggr) = 1;
1394  TREE_READONLY (taggr) = 1;
1395  return taggr;
1396}
1397
1398/* Build an initializer for a __m_desc node.  */
1399tree
1400build_m_desc (decl)
1401     tree decl;
1402{
1403  tree taggr, elems, name_string;
1404  tree parm_count, req_count, vindex, vcontext;
1405  tree parms;
1406  int p_count, r_count;
1407  tree parm_types = NULL_TREE;
1408
1409  for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
1410       parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
1411    {
1412      taggr = TREE_VALUE (parms);
1413      if ((TREE_CODE (taggr) == POINTER_TYPE
1414           || TREE_CODE (taggr) == REFERENCE_TYPE)
1415          && TYPE_VOLATILE (taggr) == 0)
1416        taggr = TREE_TYPE (taggr);
1417
1418      parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
1419                                                       ! IS_AGGR_TYPE (taggr)),
1420                              parm_types);
1421      if (TREE_PURPOSE (parms) == NULL_TREE)
1422        r_count++;
1423    }
1424
1425  parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
1426                             nreverse (parm_types), 0);
1427  parm_count = build_int_2 (p_count, 0);
1428  req_count = build_int_2 (r_count, 0);
1429
1430  if (DECL_VINDEX (decl))
1431    vindex = DECL_VINDEX (decl);
1432  else
1433    vindex = integer_zero_node;
1434  if (DECL_CONTEXT (decl)
1435      && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
1436    vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
1437  else
1438    vcontext = integer_zero_node;
1439  name_string = DECL_NAME (decl);
1440  if (name_string == NULL)
1441      name_string = DECL_ASSEMBLER_NAME (decl);
1442  name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1443
1444  /* Now decide whether the return type of this mvar
1445     should cause it's type to get def'd or ref'd in this file.
1446     If the type we are looking at has a proxy definition,
1447     we look at the proxy (i.e., a `foo *' is equivalent to a `foo').  */
1448  taggr = TREE_TYPE (TREE_TYPE (decl));
1449
1450  if ((TREE_CODE (taggr) == POINTER_TYPE
1451       || TREE_CODE (taggr) == REFERENCE_TYPE)
1452      && TYPE_VOLATILE (taggr) == 0)
1453    taggr = TREE_TYPE (taggr);
1454
1455  elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1456             tree_cons (NULL_TREE, vindex,
1457                tree_cons (NULL_TREE, vcontext,
1458                   tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
1459                                                       ! IS_AGGR_TYPE (taggr)),
1460                      tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0), 0),
1461                         tree_cons (NULL_TREE, parm_count,
1462                            tree_cons (NULL_TREE, req_count,
1463                               build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
1464
1465  taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
1466  TREE_CONSTANT (taggr) = 1;
1467  TREE_STATIC (taggr) = 1;
1468  TREE_READONLY (taggr) = 1;
1469  return taggr;
1470}
1471#endif /* dossier */
1472
1473
1474/* Conditionally emit code to set up an unwind-protect for the
1475   garbage collector.  If this function doesn't do anything that involves
1476   the garbage collector, then do nothing.  Otherwise, call __gc_push
1477   at the beginning and __gc_pop at the end.
1478
1479   NOTE!  The __gc_pop function must operate transparently, since
1480   it comes where the logical return label lies.  This means that
1481   at runtime *it* must preserve any return value registers.  */
1482
1483void
1484expand_gc_prologue_and_epilogue ()
1485{
1486  extern tree maybe_gc_cleanup;
1487  struct rtx_def *last_parm_insn, *mark;
1488  extern struct rtx_def *get_last_insn ();
1489  extern struct rtx_def *get_first_nonparm_insn ();
1490  extern struct rtx_def *previous_insn ();
1491  tree action;
1492
1493  /* If we didn't need the obstack, don't cons any space.  */
1494  if (current_function_obstack_index == 0
1495      || current_function_obstack_usage == 0)
1496    return;
1497
1498  mark = get_last_insn ();
1499  last_parm_insn = get_first_nonparm_insn ();
1500  if (last_parm_insn == 0) last_parm_insn = mark;
1501  else last_parm_insn = previous_insn (last_parm_insn);
1502
1503  action = build_function_call (gc_push_fndecl,
1504                                build_tree_list (NULL_TREE, size_int (++current_function_obstack_index)));
1505  expand_expr_stmt (action);
1506
1507  reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
1508
1509  /* This will be expanded as a cleanup.  */
1510  TREE_VALUE (maybe_gc_cleanup)
1511    = build_function_call (gc_pop_fndecl, NULL_TREE);
1512}
1513
1514/* Some day we'll use this function as a call-back and clean
1515   up all the unnecessary gc dribble that we otherwise create.  */
1516void
1517lang_expand_end_bindings (first, last)
1518     struct rtx_def *first, *last;
1519{
1520}
1521
1522void
1523init_gc_processing ()
1524{
1525  tree parmtypes = hash_tree_chain (class_star_type_node,
1526                                    hash_tree_chain (integer_type_node, NULL_TREE));
1527  gc_protect_fndecl = define_function ("__gc_protect",
1528                                       build_function_type (class_star_type_node, parmtypes),
1529                                       NOT_BUILT_IN, 0, 0);
1530
1531  parmtypes = hash_tree_chain (integer_type_node, NULL_TREE);
1532  gc_unprotect_fndecl = define_function ("__gc_unprotect",
1533                                         build_function_type (void_type_node, parmtypes),
1534                                         NOT_BUILT_IN, 0, 0);
1535
1536  gc_push_fndecl = define_function ("__gc_push",
1537                                    TREE_TYPE (gc_unprotect_fndecl),
1538                                    NOT_BUILT_IN, 0, 0);
1539
1540  gc_pop_fndecl = define_function ("__gc_pop",
1541                                   build_function_type (void_type_node,
1542                                                        void_list_node),
1543                                   NOT_BUILT_IN, 0, 0);
1544  gc_nonobject = build_int_2 (0x80000000, 0);
1545  gc_visible = build_int_2 (0x40000000, 0);
1546  gc_white = integer_zero_node;
1547  gc_offwhite = build_int_2 (0x10000000, 0);
1548  gc_grey = build_int_2 (0x20000000, 0);
1549  gc_black = build_int_2 (0x30000000, 0);
1550}
Note: See TracBrowser for help on using the repository browser.