home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / cp-gc.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  25KB  |  789 lines

  1. /* Garbage collection primitives for GNU C++.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@cygnus.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. #include "config.h"
  23. #include "tree.h"
  24. #include "cp-tree.h"
  25. #include "flags.h"
  26.  
  27. #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:
  205.       my_friendly_abort (41);
  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:
  252.       my_friendly_abort (42);
  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.       T