Annotation of gcc/cp/gc.c, revision 1.1.1.2

1.1       root        1: /* Garbage collection primitives for GNU C++.
1.1.1.2 ! root        2:    Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
1.1       root        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
1.1.1.2 ! root       19: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            20: Boston, MA 02111-1307, USA.  */
1.1       root       21: 
                     22: 
                     23: #include "config.h"
                     24: #include "tree.h"
                     25: #include "cp-tree.h"
                     26: #include "flags.h"
1.1.1.2 ! root       27: #include "output.h"
1.1       root       28: 
                     29: #undef NULL
                     30: #define NULL 0
                     31: 
                     32: extern tree define_function ();
                     33: extern tree build_t_desc_overload ();
1.1.1.2 ! root       34: extern struct obstack *permanent_obstack;
1.1       root       35: 
                     36: /* This is the function decl for the (pseudo-builtin) __gc_protect
                     37:    function.  Args are (class *value, int index); Returns value.  */
                     38: tree gc_protect_fndecl;
                     39: 
                     40: /* This is the function decl for the (pseudo-builtin) __gc_unprotect
                     41:    function.  Args are (int index); void return.  */
                     42: tree gc_unprotect_fndecl;
                     43: 
                     44: /* This is the function decl for the (pseudo-builtin) __gc_push
                     45:    function.  Args are (int length); void return.  */
                     46: tree gc_push_fndecl;
                     47: 
                     48: /* This is the function decl for the (pseudo-builtin) __gc_pop
                     49:    function.  Args are void; void return.  */
                     50: tree gc_pop_fndecl;
                     51: 
                     52: /* Special integers that are used to represent bits in gc-safe objects.  */
                     53: tree gc_nonobject;
                     54: tree gc_visible;
                     55: tree gc_white;
                     56: tree gc_offwhite;
                     57: tree gc_grey;
                     58: tree gc_black;
                     59: 
                     60: /* in c-common.c */
                     61: extern 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.  */
                     65: int
                     66: type_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))
1.1.1.2 ! root      116:       && CLASSTYPE_RTTI (TREE_TYPE (ttype)))
1.1       root      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.  */
                    126: int
                    127: value_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.  */
                    277: void
                    278: build_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;
1.1.1.2 ! root      291:       cp_finish_decl (ref, DECL_INITIAL (ref), NULL_TREE, 0, 0);
1.1       root      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: 
                    310: tree
                    311: protect_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: 
1.1.1.2 ! root      325:       if (! cp_expand_decl_cleanup (to, cleanup))
1.1       root      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.  */
                    377: tree
                    378: build_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:     }
1.1.1.2 ! root      389:   type = TREE_TYPE (type);
1.1       root      390: 
1.1.1.2 ! root      391:   if (!TYPE_VIRTUAL_P (type) || CLASSTYPE_VFIELD (type) == NULL_TREE)
        !           392:     return exp;
1.1       root      393: 
1.1.1.2 ! root      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);
1.1       root      400: 
1.1.1.2 ! root      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));
1.1       root      412: }
                    413: 
1.1.1.2 ! root      414: /* Return the type_info node associated with the expression EXP.  If EXP is
1.1       root      415:    a reference to a polymorphic class, return the dynamic type; otherwise
                    416:    return the static type of the expression.  */
                    417: tree
                    418: build_typeid (exp)
                    419:      tree exp;
                    420: {
                    421:   tree type;
                    422: 
1.1.1.2 ! root      423:   if (!flag_rtti)
        !           424:     cp_error ("cannot take typeid of object when -frtti is not specified");
        !           425: 
1.1       root      426:   if (exp == error_mark_node)
                    427:     return error_mark_node;
                    428: 
                    429:   type = TREE_TYPE (exp);
1.1.1.2 ! root      430: 
        !           431:   /* Strip top-level cv-qualifiers.  */
        !           432:   type = TYPE_MAIN_VARIANT (type);
        !           433: 
1.1       root      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: 
1.1.1.2 ! root      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: 
1.1       root      446:   /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
                    447:   if (TREE_CODE (type) == RECORD_TYPE)
                    448:     type = build_reference_type (type);
                    449: 
1.1.1.2 ! root      450:   /* If exp is a reference to polymorphic type, get the real type_info.  */
1.1       root      451:   if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type)))
                    452:     {
1.1.1.2 ! root      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;
1.1       root      464:     }
                    465: 
1.1.1.2 ! root      466:   /* otherwise return the type_info for the static type of the expr.  */
1.1       root      467:   return get_typeid (type);
                    468: }
                    469: 
1.1.1.2 ! root      470: /* Return the type_info object for TYPE, creating it if necessary.  */
1.1       root      471: tree
                    472: get_typeid (type)
                    473:      tree type;
                    474: {
1.1.1.2 ! root      475:   tree t, td;
        !           476: 
1.1       root      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: 
1.1.1.2 ! root      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: }
1.1       root      492: 
1.1.1.2 ! root      493: /* Get a bad_cast node for the program to throw...
1.1       root      494: 
1.1.1.2 ! root      495:    See libstdc++::exception{,.cc} for __bad_cast_object */
        !           496: tree
        !           497: get_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;
1.1       root      508: }
                    509: 
                    510: /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
                    511:    paper.  */
                    512: tree
                    513: build_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:
1.1.1.2 ! root      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)
1.1       root      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:
1.1.1.2 ! root      551:       goto fail;
1.1       root      552:     }
                    553: 
                    554:   /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
                    555:   if (ec == RECORD_TYPE)
                    556:     {
1.1.1.2 ! root      557:       exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
        !           558:                                     TREE_THIS_VOLATILE (expr));
1.1       root      559:       exprtype = build_reference_type (exprtype);
1.1.1.2 ! root      560:       expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
        !           561:                                   LOOKUP_NORMAL, NULL_TREE);
1.1       root      562:       ec = REFERENCE_TYPE;
                    563:     }
1.1.1.2 ! root      564: 
        !           565:   if (tc == REFERENCE_TYPE)
1.1       root      566:     {
1.1.1.2 ! root      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;
1.1       root      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.  */
1.1.1.2 ! root      591:       if (tc == POINTER_TYPE
        !           592:          && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
1.1       root      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: 
1.1.1.2 ! root      600:          return build_headof (expr);
1.1       root      601:        }
                    602:       else
                    603:        {
                    604:          tree retval;
1.1.1.2 ! root      605:           tree result, td1, td2, elems, tmp1, expr1;
1.1       root      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);
1.1.1.2 ! root      616:                  return build_throw (get_bad_cast_node ());
1.1       root      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:                {
1.1.1.2 ! root      626:                  cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
1.1       root      627:                              expr, type);
                    628:                  retval = build_int_2 (0, 0); 
                    629:                  TREE_TYPE (retval) = type; 
                    630:                  return retval;
                    631:                }
                    632:            }
1.1.1.2 ! root      633: 
        !           634:          expr1 = expr;
        !           635:          if (tc == REFERENCE_TYPE)
        !           636:            expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
        !           637: 
1.1       root      638:          /* Build run-time conversion.  */
1.1.1.2 ! root      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;
1.1       root      669:        }
                    670:     }
                    671: 
1.1.1.2 ! root      672:  fail:
1.1       root      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: 
                    692: static tree
1.1.1.2 ! root      693: build_generic_desc (tdecl, type, elems)
        !           694:      tree tdecl;
        !           695:      tree type;
1.1       root      696:      tree elems;
                    697: {
1.1.1.2 ! root      698:   tree init = elems;
        !           699:   int toplev = global_bindings_p ();
        !           700: 
1.1       root      701:   TREE_CONSTANT (init) = 1;
                    702:   TREE_STATIC (init) = 1;
                    703:   TREE_READONLY (init) = 1;
                    704: 
1.1.1.2 ! root      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.  */
        !           726: static tree
        !           727: build_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.  */
        !           794: static tree
        !           795: build_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. */
        !           808: static tree
        !           809: build_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: 
1.1       root      922: 
1.1.1.2 ! root      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);
1.1       root      933: }
                    934: 
1.1.1.2 ! root      935: /* Build an initializer for a __pointer_type_info node.  */
        !           936: static tree
        !           937: build_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.  */
        !           951: static tree
        !           952: build_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.  */
        !           980: static tree
        !           981: build_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.  */
        !           994: static tree
        !           995: build_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.  */
        !          1009: static tree
        !          1010: build_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: 
        !          1024: struct uninst_st {
        !          1025:   tree type;
        !          1026:   struct uninst_st *next;
        !          1027: };
        !          1028: typedef struct uninst_st uninst_node;
        !          1029: static uninst_node * uninst_desc = (uninst_node *)NULL;
        !          1030: 
        !          1031: static void
        !          1032: add_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: 
        !          1047: tree
        !          1048: get_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. */
        !          1066: tree
        !          1067: build_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. */
1.1       root     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.  */
                   1203: tree
                   1204: build_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));
1.1.1.2 ! root     1270: 
1.1       root     1271:   if (!definition || DECL_EXTERNAL (tdecl))
                   1272:     {
                   1273:       /* That's it!  */
1.1.1.2 ! root     1274:       cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1.1       root     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: 
1.1.1.2 ! root     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);
1.1       root     1330:   if (methods == NULL_TREE)
                   1331:     methods = null_pointer_node;
                   1332:   else
                   1333:     methods = build_unary_op (ADDR_EXPR,
1.1.1.2 ! root     1334:                              finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1.1       root     1335:                              0);
                   1336:   if (ivars == NULL_TREE)
                   1337:     ivars = null_pointer_node;
                   1338:   else
                   1339:     ivars = build_unary_op (ADDR_EXPR,
1.1.1.2 ! root     1340:                            finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1.1       root     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.  */
                   1366: tree
                   1367: build_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.  */
                   1399: tree
                   1400: build_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: 
1.1.1.2 ! root     1425:   parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
1.1       root     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)),
1.1.1.2 ! root     1460:                      tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0), 0),
1.1       root     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: }
1.1.1.2 ! root     1471: #endif /* dossier */
        !          1472: 
1.1       root     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: 
                   1483: void
                   1484: expand_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.  */
                   1516: void
                   1517: lang_expand_end_bindings (first, last)
                   1518:      struct rtx_def *first, *last;
                   1519: {
                   1520: }
                   1521: 
                   1522: void
                   1523: init_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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.