Annotation of GNUtools/cc/cp-gc.c, revision 1.1.1.1

1.1       root        1: /* Garbage collection primitives for GNU C++.
                      2:    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
                      3:    Contributed by Michael Tiemann ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU CC; see the file COPYING.  If not, write to
                     19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     20: 
                     21: 
                     22: #include "config.h"
                     23: #include "tree.h"
                     24: #include "cp-tree.h"
                     25: #include "flags.h"
                     26: 
                     27: #undef NULL
                     28: #define NULL 0
                     29: 
                     30: extern tree define_function ();
                     31: extern tree build_t_desc_overload ();
                     32: 
                     33: /* This is the function decl for the (pseudo-builtin) __gc_protect
                     34:    function.  Args are (class *value, int index); Returns value.  */
                     35: tree gc_protect_fndecl;
                     36: 
                     37: /* This is the function decl for the (pseudo-builtin) __gc_unprotect
                     38:    function.  Args are (int index); void return.  */
                     39: tree gc_unprotect_fndecl;
                     40: 
                     41: /* This is the function decl for the (pseudo-builtin) __gc_push
                     42:    function.  Args are (int length); void return.  */
                     43: tree gc_push_fndecl;
                     44: 
                     45: /* This is the function decl for the (pseudo-builtin) __gc_pop
                     46:    function.  Args are void; void return.  */
                     47: tree gc_pop_fndecl;
                     48: 
                     49: /* Special integers that are used to represent bits in gc-safe objects.  */
                     50: tree gc_nonobject;
                     51: tree gc_visible;
                     52: tree gc_white;
                     53: tree gc_offwhite;
                     54: tree gc_grey;
                     55: tree gc_black;
                     56: 
                     57: /* in c-common.c */
                     58: extern tree combine_strings PROTO((tree));
                     59: 
                     60: /* Predicate that returns non-zero if TYPE needs some kind of
                     61:    entry for the GC.  Returns zero otherwise.  */
                     62: int
                     63: type_needs_gc_entry (type)
                     64:      tree type;
                     65: {
                     66:   tree ttype = type;
                     67: 
                     68:   if (! flag_gc || type == error_mark_node)
                     69:     return 0;
                     70: 
                     71:   /* Aggregate types need gc entries if any of their members
                     72:      need gc entries.  */
                     73:   if (IS_AGGR_TYPE (type))
                     74:     {
                     75:       tree binfos;
                     76:       tree fields = TYPE_FIELDS (type);
                     77:       int i;
                     78: 
                     79:       /* We don't care about certain pointers.  Pointers
                     80:         to virtual baseclasses are always up front.  We also
                     81:         cull out virtual function table pointers because it's
                     82:         easy, and it simplifies the logic.*/
                     83:       while (fields
                     84:             && (DECL_NAME (fields) == NULL_TREE
                     85:                 || VFIELD_NAME_P (DECL_NAME (fields))
                     86:                 || VBASE_NAME_P (DECL_NAME (fields))
                     87:                 || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits")))
                     88:        fields = TREE_CHAIN (fields);
                     89: 
                     90:       while (fields)
                     91:        {
                     92:          if (type_needs_gc_entry (TREE_TYPE (fields)))
                     93:            return 1;
                     94:          fields = TREE_CHAIN (fields);
                     95:        }
                     96: 
                     97:       binfos = TYPE_BINFO_BASETYPES (type);
                     98:       if (binfos)
                     99:        for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
                    100:          if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))
                    101:            return 1;
                    102: 
                    103:       return 0;
                    104:     }
                    105: 
                    106:   while (TREE_CODE (ttype) == ARRAY_TYPE
                    107:         && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE)
                    108:     ttype = TREE_TYPE (ttype);
                    109:   if ((TREE_CODE (ttype) == POINTER_TYPE
                    110:        || TREE_CODE (ttype) == ARRAY_TYPE
                    111:        || TREE_CODE (ttype) == REFERENCE_TYPE)
                    112:       && IS_AGGR_TYPE (TREE_TYPE (ttype))
                    113:       && CLASSTYPE_DOSSIER (TREE_TYPE (ttype)))
                    114:     return 1;
                    115: 
                    116:   return 0;
                    117: }
                    118: 
                    119: /* Predicate that returns non-zero iff FROM is safe from the GC.
                    120:    
                    121:    If TO is nonzero, it means we know that FROM is being stored
                    122:    in TO, which make make it safe.  */
                    123: int
                    124: value_safe_from_gc (to, from)
                    125:      tree to, from;
                    126: {
                    127:   /* First, return non-zero for easy cases: parameters,
                    128:      static variables.  */
                    129:   if (TREE_CODE (from) == PARM_DECL
                    130:       || (TREE_CODE (from) == VAR_DECL
                    131:          && TREE_STATIC (from)))
                    132:     return 1;
                    133: 
                    134:   /* If something has its address taken, it cannot be
                    135:      in the heap, so it doesn't need to be protected.  */
                    136:   if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from))
                    137:     return 1;
                    138: 
                    139:   /* If we are storing into a static variable, then what
                    140:      we store will be safe from the gc.  */
                    141:   if (to && TREE_CODE (to) == VAR_DECL
                    142:       && TREE_STATIC (to))
                    143:     return 1;
                    144: 
                    145:   /* Now recurse on structure of FROM.  */
                    146:   switch (TREE_CODE (from))
                    147:     {
                    148:     case COMPONENT_REF:
                    149:       /* These guys are special, and safe.  */
                    150:       if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL
                    151:          && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))
                    152:              || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))))
                    153:        return 1;
                    154:       /* fall through...  */
                    155:     case NOP_EXPR:
                    156:     case CONVERT_EXPR:
                    157:     case NON_LVALUE_EXPR:
                    158:     case WITH_CLEANUP_EXPR:
                    159:     case SAVE_EXPR:
                    160:     case PREDECREMENT_EXPR:
                    161:     case PREINCREMENT_EXPR:
                    162:     case POSTDECREMENT_EXPR:
                    163:     case POSTINCREMENT_EXPR:
                    164:       if (value_safe_from_gc (to, TREE_OPERAND (from, 0)))
                    165:        return 1;
                    166:       break;
                    167: 
                    168:     case VAR_DECL:
                    169:     case PARM_DECL:
                    170:       /* We can safely pass these things as parameters to functions.  */
                    171:       if (to == 0)
                    172:        return 1;
                    173: 
                    174:     case ARRAY_REF:
                    175:     case INDIRECT_REF:
                    176:     case RESULT_DECL:
                    177:     case OFFSET_REF:
                    178:     case CALL_EXPR:
                    179:     case METHOD_CALL_EXPR:
                    180:       break;
                    181: 
                    182:     case COMPOUND_EXPR:
                    183:     case TARGET_EXPR:
                    184:       if (value_safe_from_gc (to, TREE_OPERAND (from, 1)))
                    185:        return 1;
                    186:       break;
                    187: 
                    188:     case COND_EXPR:
                    189:       if (value_safe_from_gc (to, TREE_OPERAND (from, 1))
                    190:          && value_safe_from_gc (to, TREE_OPERAND (from, 2)))
                    191:        return 1;
                    192:       break;
                    193: 
                    194:     case PLUS_EXPR:
                    195:     case MINUS_EXPR:
                    196:       if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0)))
                    197:           || value_safe_from_gc (to, TREE_OPERAND (from, 0)))
                    198:          && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0
                    199:              || value_safe_from_gc (to, TREE_OPERAND (from, 1))))
                    200:        return 1;
                    201:       break;
                    202: 
                    203:     case RTL_EXPR:
                    204:       /* Every time we build an RTL_EXPR in the front-end, we must
                    205:         ensure that everything in it is safe from the garbage collector.
                    206:         ??? This has only been done for `build_new'.  */
                    207:       return 1;
                    208: 
                    209:     default:
                    210:       my_friendly_abort (41);
                    211:     }
                    212: 
                    213:   if (to == 0)
                    214:     return 0;
                    215: 
                    216:   /* FROM wasn't safe.  But other properties of TO might make it safe.  */
                    217:   switch (TREE_CODE (to))
                    218:     {
                    219:     case VAR_DECL:
                    220:     case PARM_DECL:
                    221:       /* We already culled out static VAR_DECLs above.  */
                    222:       return 0;
                    223: 
                    224:     case COMPONENT_REF:
                    225:       /* These guys are special, and safe.  */
                    226:       if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL
                    227:          && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))
                    228:              || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))))
                    229:        return 1;
                    230:       /* fall through...  */
                    231: 
                    232:     case NOP_EXPR:
                    233:     case NON_LVALUE_EXPR:
                    234:     case WITH_CLEANUP_EXPR:
                    235:     case SAVE_EXPR:
                    236:     case PREDECREMENT_EXPR:
                    237:     case PREINCREMENT_EXPR:
                    238:     case POSTDECREMENT_EXPR:
                    239:     case POSTINCREMENT_EXPR:
                    240:       return value_safe_from_gc (TREE_OPERAND (to, 0), from);
                    241: 
                    242:     case COMPOUND_EXPR:
                    243:     case TARGET_EXPR:
                    244:       return value_safe_from_gc (TREE_OPERAND (to, 1), from);
                    245: 
                    246:     case COND_EXPR:
                    247:       return (value_safe_from_gc (TREE_OPERAND (to, 1), from)
                    248:              && value_safe_from_gc (TREE_OPERAND (to, 2), from));
                    249: 
                    250:     case INDIRECT_REF:
                    251:     case ARRAY_REF:
                    252:       /* This used to be 0, but our current restricted model
                    253:         allows this to be 1.  We'll never get arrays this way.  */
                    254:       return 1;
                    255: 
                    256:     default:
                    257:       my_friendly_abort (42);
                    258:     }
                    259: 
                    260:   /* Catch-all case is that TO/FROM is not safe.  */
                    261:   return 0;
                    262: }
                    263: 
                    264: /* Function to build a static GC entry for DECL.  TYPE is DECL's type.
                    265: 
                    266:    For objects of type `class *', this is just an entry in the
                    267:    static vector __PTR_LIST__.
                    268: 
                    269:    For objects of type `class[]', this requires building an entry
                    270:    in the static vector __ARR_LIST__.
                    271: 
                    272:    For aggregates, this records all fields of type `class *'
                    273:    and `class[]' in the respective lists above.  */
                    274: void
                    275: build_static_gc_entry (decl, type)
                    276:      tree decl;
                    277:      tree type;
                    278: {
                    279:   /* Now, figure out what sort of entry to build.  */
                    280:   if (TREE_CODE (type) == POINTER_TYPE
                    281:       || TREE_CODE (type) == REFERENCE_TYPE)
                    282:     assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl)));
                    283:   else if (TREE_CODE (type) == RECORD_TYPE)
                    284:     {
                    285:       tree ref = get_temp_name (build_reference_type (type), 1);
                    286:       DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl);
                    287:       TREE_CONSTANT (DECL_INITIAL (ref)) = 1;
                    288:       finish_decl (ref, DECL_INITIAL (ref), 0, 0);
                    289:     }
                    290:   else
                    291:     {
                    292:       /* Not yet implemented.
                    293:         
                    294:         Cons up a static variable that holds address and length info
                    295:         and add that to ___ARR_LIST__.  */
                    296:       my_friendly_abort (43);
                    297:     }
                    298: }
                    299: 
                    300: /* Protect FROM from the GC, assuming FROM is going to be
                    301:    stored into TO.  We handle three cases for TO here:
                    302: 
                    303:    case 1: TO is a stack variable.
                    304:    case 2: TO is zero (which means it is a parameter).
                    305:    case 3: TO is a return value.  */
                    306: 
                    307: tree
                    308: protect_value_from_gc (to, from)
                    309:      tree to, from;
                    310: {
                    311:   if (to == 0)
                    312:     {
                    313:       tree cleanup;
                    314: 
                    315:       to = get_temp_regvar (TREE_TYPE (from), from);
                    316: 
                    317:       /* Convert from integer to list form since we'll use it twice.  */
                    318:       DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
                    319:       cleanup = build_function_call (gc_unprotect_fndecl,
                    320:                                     DECL_GC_OFFSET (to));
                    321: 
                    322:       if (! expand_decl_cleanup (to, cleanup))
                    323:        {
                    324:          compiler_error ("cannot unprotect parameter in this scope");
                    325:          return error_mark_node;
                    326:        }
                    327:     }
                    328: 
                    329:   /* Should never need to protect a value that's headed for static storage.  */
                    330:   if (TREE_STATIC (to))
                    331:     my_friendly_abort (44);
                    332: 
                    333:   switch (TREE_CODE (to))
                    334:     {
                    335:     case COMPONENT_REF:
                    336:     case INDIRECT_REF:
                    337:       return protect_value_from_gc (TREE_OPERAND (to, 0), from);
                    338: 
                    339:     case VAR_DECL:
                    340:     case PARM_DECL:
                    341:       {
                    342:        tree rval;
                    343:        if (DECL_GC_OFFSET (to) == NULL_TREE)
                    344:          {
                    345:            /* Because of a cast or a conversion, we might stick
                    346:               a value into a variable that would not normally
                    347:               have a GC entry.  */
                    348:            DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index);
                    349:          }
                    350: 
                    351:        if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST)
                    352:          {
                    353:            DECL_GC_OFFSET (to)
                    354:              = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
                    355:          }
                    356: 
                    357:        current_function_obstack_usage = 1;
                    358:        rval = build_function_call (gc_protect_fndecl,
                    359:                                    tree_cons (NULL_TREE, from,
                    360:                                               DECL_GC_OFFSET (to)));
                    361:        TREE_TYPE (rval) = TREE_TYPE (from);
                    362:        return rval;
                    363:       }
                    364:     }
                    365: 
                    366:   /* If we fall through the switch, assume we lost.  */
                    367:   my_friendly_abort (45);
                    368:   /* NOTREACHED */
                    369:   return NULL_TREE;
                    370: }
                    371: 
                    372: /* Given the expression EXP of type `class *', return the head
                    373:    of the object pointed to by EXP.  */
                    374: tree
                    375: build_headof (exp)
                    376:      tree exp;
                    377: {
                    378:   tree type = TREE_TYPE (exp);
                    379:   tree vptr, offset;
                    380: 
                    381:   if (TREE_CODE (type) != POINTER_TYPE)
                    382:     {
                    383:       error ("`headof' applied to non-pointer type");
                    384:       return error_mark_node;
                    385:     }
                    386: 
                    387:   vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
                    388:   offset = build_component_ref (build_array_ref (vptr, integer_one_node),
                    389:                                get_identifier (VTABLE_DELTA_NAME),
                    390:                                NULL_TREE, 0);
                    391:   return build (PLUS_EXPR, class_star_type_node, exp,
                    392:                convert (integer_type_node, offset));
                    393: }
                    394: 
                    395: /* Given the expression EXP of type `class *', return the
                    396:    type descriptor for the object pointed to by EXP.  */
                    397: tree
                    398: build_classof (exp)
                    399:      tree exp;
                    400: {
                    401:   tree type = TREE_TYPE (exp);
                    402:   tree vptr;
                    403:   tree t_desc_entry;
                    404: 
                    405:   if (TREE_CODE (type) != POINTER_TYPE)
                    406:     {
                    407:       error ("`classof' applied to non-pointer type");
                    408:       return error_mark_node;
                    409:     }
                    410: 
                    411:   vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
                    412:   t_desc_entry = build_component_ref (build_array_ref (vptr, integer_one_node),
                    413:                                      get_identifier (VTABLE_PFN_NAME),
                    414:                                      NULL_TREE, 0);
                    415:   TREE_TYPE (t_desc_entry) = TYPE_POINTER_TO (__t_desc_type_node);
                    416:   return t_desc_entry;
                    417: }
                    418: 
                    419: /* Return the Type_info node associated with the expression EXP.  If EXP is
                    420:    a reference to a polymorphic class, return the dynamic type; otherwise
                    421:    return the static type of the expression.  */
                    422: tree
                    423: build_typeid (exp)
                    424:      tree exp;
                    425: {
                    426:   tree type;
                    427: 
                    428:   if (exp == error_mark_node)
                    429:     return error_mark_node;
                    430: 
                    431:   type = TREE_TYPE (exp);
                    432:   
                    433:   /* if b is an instance of B, typeid(b) == typeid(B).  Do this before
                    434:      reference trickiness.  */
                    435:   if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (type) == RECORD_TYPE)
                    436:     return get_typeid (type);
                    437: 
                    438:   /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
                    439:   if (TREE_CODE (type) == RECORD_TYPE)
                    440:     type = build_reference_type (type);
                    441: 
                    442:   /* If exp is a reference to polymorphic type, get the real Type_info.  */
                    443:   if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type)))
                    444:     {
                    445:       /* build reference to Type_info from vtable.  */
                    446:       
                    447:       sorry ("finding Type_info for an object");
                    448:       return error_mark_node;
                    449:     }
                    450: 
                    451:   /* otherwise return the Type_info for the static type of the expr.  */
                    452:   return get_typeid (type);
                    453: }
                    454: 
                    455: /* Return the Type_info object for TYPE, creating it if necessary.  */
                    456: tree
                    457: get_typeid (type)
                    458:      tree type;
                    459: {
                    460:   if (type == error_mark_node)
                    461:     return error_mark_node;
                    462:   
                    463:   /* Is it useful (and/or correct) to have different typeids for `T &'
                    464:      and `T'?  */
                    465:   if (TREE_CODE (type) == REFERENCE_TYPE)
                    466:     type = TREE_TYPE (type);
                    467:   
                    468:   /* build reference to static Type_info */
                    469: #if 1
                    470:   sorry ("finding Type_info for a type");
                    471:   return error_mark_node;
                    472: #else
                    473:   register tree t = TYPE_TINFO (type);
                    474: 
                    475:   if (t)
                    476:     return t;
                    477: 
                    478:   /* ... */
                    479: 
                    480: #endif  
                    481: }
                    482: 
                    483: /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
                    484:    paper.  */
                    485: tree
                    486: build_dynamic_cast (type, expr)
                    487:      tree type, expr;
                    488: {
                    489:   enum tree_code tc = TREE_CODE (type);
                    490:   tree exprtype = TREE_TYPE (expr);
                    491:   enum tree_code ec = TREE_CODE (exprtype);
                    492:   tree retval;
                    493: 
                    494:   if (type == error_mark_node || expr == error_mark_node)
                    495:     return error_mark_node;
                    496:   
                    497:   switch (tc)
                    498:     {
                    499:     case POINTER_TYPE:
                    500:       if (TREE_TYPE (type) == void_type_node)
                    501:        break;
                    502:       /* else fall through */
                    503:     case REFERENCE_TYPE:
                    504:       if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
                    505:          && TYPE_SIZE (TREE_TYPE (type)) != NULL_TREE)
                    506:        break;
                    507:       /* else fall through */
                    508:     default:
                    509:       cp_error ("`%#T' is not a valid type argument for dynamic_cast", type);
                    510:       error ("(must be either pointer or reference to defined class or void *)");
                    511:       return error_mark_node;
                    512:     }
                    513: 
                    514:   /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
                    515:   if (ec == RECORD_TYPE)
                    516:     {
                    517:       exprtype = build_reference_type (exprtype);
                    518:       ec = REFERENCE_TYPE;
                    519:     }
                    520:   
                    521:   /* the TREE_CODE of exprtype must match that of type.  */
                    522:   if (ec != tc)
                    523:     {
                    524:       cp_error ("`%E' (of type `%#T') fails to be of %s type", expr, exprtype,
                    525:                tc == POINTER_TYPE ? "pointer" : "reference");
                    526:       return error_mark_node;
                    527:     }
                    528: 
                    529:   /* If *type is an unambiguous accessible base class of *exprtype,
                    530:      convert statically.  */
                    531:   {
                    532:     int distance;
                    533:     tree path;
                    534: 
                    535:     distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
                    536:                                  &path);
                    537:     if (distance >= 0)
                    538:       return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
                    539:   }
                    540: 
                    541:   /* Otherwise *exprtype must be a polymorphic class (have a vtbl).  */
                    542:   if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
                    543:     {
                    544:       /* if TYPE is `void *', return pointer to complete object.  */
                    545:       if (tc == POINTER_TYPE && TREE_TYPE (type) == void_type_node)
                    546:        {
                    547:          /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b.  */
                    548:          if (TREE_CODE (expr) == ADDR_EXPR
                    549:              && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
                    550:              && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
                    551:            return build1 (NOP_EXPR, type, expr);
                    552: 
                    553:          sorry ("finding pointer to complete object");
                    554:          return build1 (NOP_EXPR, type, expr);
                    555:        }
                    556:       else
                    557:        {
                    558:          tree retval;
                    559: 
                    560:          /* If we got here, we can't convert statically.  Therefore,
                    561:             dynamic_cast<D&>(b) (b an object) cannot succeed.  */
                    562:          if (ec == REFERENCE_TYPE)
                    563:            {
                    564:              if (TREE_CODE (expr) == VAR_DECL
                    565:                  && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
                    566:                {
                    567:                  cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
                    568:                              expr, type);
                    569:                  /* cplus_expand_throw (Bad_cast_node); */
                    570:                  sorry ("throwing Bad_cast");
                    571:                  return error_mark_node;
                    572:                }
                    573:            }
                    574:          /* Ditto for dynamic_cast<D*>(&b).  */
                    575:          else if (TREE_CODE (expr) == ADDR_EXPR)
                    576:            {
                    577:              tree op = TREE_OPERAND (expr, 0);
                    578:              if (TREE_CODE (op) == VAR_DECL
                    579:                  && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
                    580:                {
                    581:                  cp_warning ("dynamic_cast of `%E' to `%#T' can never succeed",
                    582:                              expr, type);
                    583:                  retval = build_int_2 (0, 0); 
                    584:                  TREE_TYPE (retval) = type; 
                    585:                  return retval;
                    586:                }
                    587:            }
                    588:          /* Build run-time conversion.  */
                    589:          sorry ("run-time type conversion");
                    590:          retval = build_int_2 (0, 0); 
                    591:          TREE_TYPE (retval) = type; 
                    592:          return retval;
                    593:        }
                    594:     }
                    595: 
                    596:   cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
                    597:            expr, exprtype, type);
                    598:   return error_mark_node;
                    599: }
                    600: 
                    601: /* Build and initialize various sorts of descriptors.  Every descriptor
                    602:    node has a name associated with it (the name created by mangling).
                    603:    For this reason, we use the identifier as our access to the __*_desc
                    604:    nodes, instead of sticking them directly in the types.  Otherwise we
                    605:    would burden all built-in types (and pointer types) with slots that
                    606:    we don't necessarily want to use.
                    607: 
                    608:    For each descriptor we build, we build a variable that contains
                    609:    the descriptor's information.  When we need this info at runtime,
                    610:    all we need is access to these variables.
                    611: 
                    612:    Note: these constructors always return the address of the descriptor
                    613:    info, since that is simplest for their mutual interaction.  */
                    614: 
                    615: static tree
                    616: build_generic_desc (decl, elems)
                    617:      tree decl;
                    618:      tree elems;
                    619: {
                    620:   tree init = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, elems);
                    621:   TREE_CONSTANT (init) = 1;
                    622:   TREE_STATIC (init) = 1;
                    623:   TREE_READONLY (init) = 1;
                    624: 
                    625:   DECL_INITIAL (decl) = init;
                    626:   TREE_STATIC (decl) = 1;
                    627:   layout_decl (decl, 0);
                    628:   finish_decl (decl, init, 0, 0);
                    629: 
                    630:   return IDENTIFIER_AS_DESC (DECL_NAME (decl));
                    631: }
                    632: 
                    633: /* Build an initializer for a __t_desc node.  So that we can take advantage
                    634:    of recursion, we accept NULL for TYPE.
                    635:    DEFINITION is greater than zero iff we must define the type descriptor
                    636:    (as opposed to merely referencing it).  1 means treat according to
                    637:    #pragma interface/#pragma implementation rules.  2 means define as
                    638:    global and public, no matter what.  */
                    639: tree
                    640: build_t_desc (type, definition)
                    641:      tree type;
                    642:      int definition;
                    643: {
                    644:   tree tdecl;
                    645:   tree tname, name_string;
                    646:   tree elems, fields;
                    647:   tree parents, vbases, offsets, ivars, methods, target_type;
                    648:   int method_count = 0, field_count = 0;
                    649: 
                    650:   if (type == NULL_TREE)
                    651:     return NULL_TREE;
                    652: 
                    653:   tname = build_t_desc_overload (type);
                    654:   if (IDENTIFIER_AS_DESC (tname)
                    655:       && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
                    656:     return IDENTIFIER_AS_DESC (tname);
                    657: 
                    658:   tdecl = lookup_name (tname, 0);
                    659:   if (tdecl == NULL_TREE)
                    660:     {
                    661:       tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
                    662:       DECL_EXTERNAL (tdecl) = 1;
                    663:       TREE_PUBLIC (tdecl) = 1;
                    664:       tdecl = pushdecl_top_level (tdecl);
                    665:     }
                    666:   /* If we previously defined it, return the defined result.  */
                    667:   else if (definition && DECL_INITIAL (tdecl))
                    668:     return IDENTIFIER_AS_DESC (tname);
                    669: 
                    670:   if (definition)
                    671:     {
                    672:       tree taggr = type;
                    673:       /* Let T* and T& be written only when T is written (if T is an aggr).
                    674:          We do this for const, but not for volatile, since volatile
                    675:         is rare and const is not.  */
                    676:       if (!TYPE_VOLATILE (taggr)
                    677:          && (TREE_CODE (taggr) == POINTER_TYPE
                    678:              || TREE_CODE (taggr) == REFERENCE_TYPE)
                    679:          && IS_AGGR_TYPE (TREE_TYPE (taggr)))
                    680:        taggr = TREE_TYPE (taggr);
                    681: 
                    682:       /* If we know that we don't need to write out this type's
                    683:         vtable, then don't write out it's dossier.  Somebody
                    684:         else will take care of that.  */
                    685:       if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
                    686:        {
                    687:          if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
                    688:            {
                    689:              TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
                    690:                && CLASSTYPE_INTERFACE_KNOWN (taggr);
                    691:              TREE_STATIC (tdecl) = 1;
                    692:              DECL_EXTERNAL (tdecl) = 0;
                    693:            }
                    694:          else
                    695:            {
                    696:              if (write_virtuals != 0)
                    697:                TREE_PUBLIC (tdecl) = 1;
                    698:            }
                    699:        }
                    700:       else
                    701:        {
                    702:          DECL_EXTERNAL (tdecl) = 0;
                    703:          TREE_STATIC (tdecl) = 1;
                    704:          TREE_PUBLIC (tdecl) = (definition > 1);
                    705:        }
                    706:     }
                    707:   SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
                    708:   if (!definition || DECL_EXTERNAL (tdecl))
                    709:     {
                    710:       /* That's it!  */
                    711:       finish_decl (tdecl, 0, 0, 0);
                    712:       return IDENTIFIER_AS_DESC (tname);
                    713:     }
                    714: 
                    715:   /* Show that we are defining the t_desc for this type.  */
                    716:   DECL_INITIAL (tdecl) = error_mark_node;
                    717: 
                    718:   parents = build_tree_list (NULL_TREE, integer_zero_node);
                    719:   vbases = build_tree_list (NULL_TREE, integer_zero_node);
                    720:   offsets = build_tree_list (NULL_TREE, integer_zero_node);
                    721:   methods = NULL_TREE;
                    722:   ivars = NULL_TREE;
                    723: 
                    724:   if (TYPE_LANG_SPECIFIC (type))
                    725:     {
                    726:       int i = CLASSTYPE_N_BASECLASSES (type);
                    727:       tree method_vec = CLASSTYPE_METHOD_VEC (type);
                    728:       tree *meth, *end;
                    729:       tree binfos = TYPE_BINFO_BASETYPES (type);
                    730:       tree vb = CLASSTYPE_VBASECLASSES (type);
                    731: 
                    732:       while (--i >= 0)
                    733:        parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
                    734: 
                    735:       while (vb)
                    736:        {
                    737:          vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
                    738:          offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
                    739:          vb = TREE_CHAIN (vb);
                    740:        }
                    741: 
                    742:       if (method_vec)
                    743:        for (meth = TREE_VEC_END (method_vec),
                    744:             end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
                    745:          if (*meth)
                    746:            {
                    747:              methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
                    748:              method_count++;
                    749:            }
                    750:     }
                    751: 
                    752:   if (IS_AGGR_TYPE (type))
                    753:     {
                    754:       for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
                    755:        if (TREE_CODE (fields) == FIELD_DECL
                    756:            || TREE_CODE (fields) == VAR_DECL)
                    757:          {
                    758:            ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
                    759:            field_count++;
                    760:          }
                    761:       ivars = nreverse (ivars);
                    762:     }
                    763: 
                    764:   parents = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), parents, 0);
                    765:   vbases = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), vbases, 0);
                    766:   offsets = finish_table (0, integer_type_node, offsets, 0);
                    767:   if (methods == NULL_TREE)
                    768:     methods = null_pointer_node;
                    769:   else
                    770:     methods = build_unary_op (ADDR_EXPR,
                    771:                              finish_table (0, __m_desc_type_node, methods, 0),
                    772:                              0);
                    773:   if (ivars == NULL_TREE)
                    774:     ivars = null_pointer_node;
                    775:   else
                    776:     ivars = build_unary_op (ADDR_EXPR,
                    777:                            finish_table (0, __i_desc_type_node, ivars, 0),
                    778:                            0);
                    779:   if (TREE_TYPE (type))
                    780:     target_type = build_t_desc (TREE_TYPE (type), definition);
                    781:   else
                    782:     target_type = integer_zero_node;
                    783: 
                    784:   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
                    785: 
                    786:   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
                    787:           tree_cons (NULL_TREE,
                    788:                      TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
                    789:             /* really should use bitfield initialization here.  */
                    790:             tree_cons (NULL_TREE, integer_zero_node,
                    791:              tree_cons (NULL_TREE, target_type,
                    792:               tree_cons (NULL_TREE, build_int_2 (field_count, 2),
                    793:                tree_cons (NULL_TREE, build_int_2 (method_count, 2),
                    794:                 tree_cons (NULL_TREE, ivars,
                    795:                  tree_cons (NULL_TREE, methods,
                    796:                   tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
                    797:                    tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
                    798:                     build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
                    799:   return build_generic_desc (tdecl, elems);
                    800: }
                    801: 
                    802: /* Build an initializer for a __i_desc node.  */
                    803: tree
                    804: build_i_desc (decl)
                    805:      tree decl;
                    806: {
                    807:   tree elems, name_string;
                    808:   tree taggr;
                    809: 
                    810:   name_string = DECL_NAME (decl);
                    811:   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
                    812: 
                    813:   /* Now decide whether this ivar should cause it's type to get
                    814:      def'd or ref'd in this file.  If the type we are looking at
                    815:      has a proxy definition, we look at the proxy (i.e., a
                    816:      `foo *' is equivalent to a `foo').  */
                    817:   taggr = TREE_TYPE (decl);
                    818: 
                    819:   if ((TREE_CODE (taggr) == POINTER_TYPE
                    820:        || TREE_CODE (taggr) == REFERENCE_TYPE)
                    821:       && TYPE_VOLATILE (taggr) == 0)
                    822:     taggr = TREE_TYPE (taggr);
                    823: 
                    824:   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
                    825:             tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
                    826:                build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
                    827:                                                          ! IS_AGGR_TYPE (taggr)))));
                    828:   taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
                    829:   TREE_CONSTANT (taggr) = 1;
                    830:   TREE_STATIC (taggr) = 1;
                    831:   TREE_READONLY (taggr) = 1;
                    832:   return taggr;
                    833: }
                    834: 
                    835: /* Build an initializer for a __m_desc node.  */
                    836: tree
                    837: build_m_desc (decl)
                    838:      tree decl;
                    839: {
                    840:   tree taggr, elems, name_string;
                    841:   tree parm_count, req_count, vindex, vcontext;
                    842:   tree parms;
                    843:   int p_count, r_count;
                    844:   tree parm_types = NULL_TREE;
                    845: 
                    846:   for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
                    847:        parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
                    848:     {
                    849:       taggr = TREE_VALUE (parms);
                    850:       if ((TREE_CODE (taggr) == POINTER_TYPE
                    851:           || TREE_CODE (taggr) == REFERENCE_TYPE)
                    852:          && TYPE_VOLATILE (taggr) == 0)
                    853:        taggr = TREE_TYPE (taggr);
                    854: 
                    855:       parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
                    856:                                                       ! IS_AGGR_TYPE (taggr)),
                    857:                              parm_types);
                    858:       if (TREE_PURPOSE (parms) == NULL_TREE)
                    859:        r_count++;
                    860:     }
                    861: 
                    862:   parm_types = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node),
                    863:                             nreverse (parm_types), 0);
                    864:   parm_count = build_int_2 (p_count, 0);
                    865:   req_count = build_int_2 (r_count, 0);
                    866: 
                    867:   if (DECL_VINDEX (decl))
                    868:     vindex = DECL_VINDEX (decl);
                    869:   else
                    870:     vindex = integer_zero_node;
                    871:   if (DECL_CONTEXT (decl)
                    872:       && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
                    873:     vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
                    874:   else
                    875:     vcontext = integer_zero_node;
                    876:   name_string = DECL_NAME (decl);
                    877:   if (name_string == NULL)
                    878:       name_string = DECL_ASSEMBLER_NAME (decl);
                    879:   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
                    880: 
                    881:   /* Now decide whether the return type of this mvar
                    882:      should cause it's type to get def'd or ref'd in this file.
                    883:      If the type we are looking at has a proxy definition,
                    884:      we look at the proxy (i.e., a `foo *' is equivalent to a `foo').  */
                    885:   taggr = TREE_TYPE (TREE_TYPE (decl));
                    886: 
                    887:   if ((TREE_CODE (taggr) == POINTER_TYPE
                    888:        || TREE_CODE (taggr) == REFERENCE_TYPE)
                    889:       && TYPE_VOLATILE (taggr) == 0)
                    890:     taggr = TREE_TYPE (taggr);
                    891: 
                    892:   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
                    893:             tree_cons (NULL_TREE, vindex,
                    894:                tree_cons (NULL_TREE, vcontext,
                    895:                   tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
                    896:                                                       ! IS_AGGR_TYPE (taggr)),
                    897:                      tree_cons (NULL_TREE, build_c_cast (TYPE_POINTER_TO (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
                    898:                         tree_cons (NULL_TREE, parm_count,
                    899:                            tree_cons (NULL_TREE, req_count,
                    900:                               build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
                    901: 
                    902:   taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
                    903:   TREE_CONSTANT (taggr) = 1;
                    904:   TREE_STATIC (taggr) = 1;
                    905:   TREE_READONLY (taggr) = 1;
                    906:   return taggr;
                    907: }
                    908: 
                    909: /* Conditionally emit code to set up an unwind-protect for the
                    910:    garbage collector.  If this function doesn't do anything that involves
                    911:    the garbage collector, then do nothing.  Otherwise, call __gc_push
                    912:    at the beginning and __gc_pop at the end.
                    913: 
                    914:    NOTE!  The __gc_pop function must operate transparently, since
                    915:    it comes where the logical return label lies.  This means that
                    916:    at runtime *it* must preserve any return value registers.  */
                    917: 
                    918: void
                    919: expand_gc_prologue_and_epilogue ()
                    920: {
                    921:   extern tree maybe_gc_cleanup;
                    922:   struct rtx_def *last_parm_insn, *mark;
                    923:   extern struct rtx_def *get_last_insn ();
                    924:   extern struct rtx_def *get_first_nonparm_insn ();
                    925:   extern struct rtx_def *previous_insn ();
                    926:   tree action;
                    927: 
                    928:   /* If we didn't need the obstack, don't cons any space.  */
                    929:   if (current_function_obstack_index == 0
                    930:       || current_function_obstack_usage == 0)
                    931:     return;
                    932: 
                    933:   mark = get_last_insn ();
                    934:   last_parm_insn = get_first_nonparm_insn ();
                    935:   if (last_parm_insn == 0) last_parm_insn = mark;
                    936:   else last_parm_insn = previous_insn (last_parm_insn);
                    937: 
                    938:   action = build_function_call (gc_push_fndecl,
                    939:                                build_tree_list (NULL_TREE, size_int (++current_function_obstack_index)));
                    940:   expand_expr_stmt (action);
                    941: 
                    942:   reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
                    943: 
                    944:   /* This will be expanded as a cleanup.  */
                    945:   TREE_VALUE (maybe_gc_cleanup)
                    946:     = build_function_call (gc_pop_fndecl, NULL_TREE);
                    947: }
                    948: 
                    949: /* Some day we'll use this function as a call-back and clean
                    950:    up all the unnecessary gc dribble that we otherwise create.  */
                    951: void
                    952: lang_expand_end_bindings (first, last)
                    953:      struct rtx_def *first, *last;
                    954: {
                    955: }
                    956: 
                    957: void
                    958: init_gc_processing ()
                    959: {
                    960:   tree parmtypes = hash_tree_chain (class_star_type_node,
                    961:                                    hash_tree_chain (integer_type_node, NULL_TREE));
                    962:   gc_protect_fndecl = define_function ("__gc_protect",
                    963:                                       build_function_type (class_star_type_node, parmtypes),
                    964:                                       NOT_BUILT_IN, 0, 0);
                    965: 
                    966:   parmtypes = hash_tree_chain (integer_type_node, NULL_TREE);
                    967:   gc_unprotect_fndecl = define_function ("__gc_unprotect",
                    968:                                         build_function_type (void_type_node, parmtypes),
                    969:                                         NOT_BUILT_IN, 0, 0);
                    970: 
                    971:   gc_push_fndecl = define_function ("__gc_push",
                    972:                                    TREE_TYPE (gc_unprotect_fndecl),
                    973:                                    NOT_BUILT_IN, 0, 0);
                    974: 
                    975:   gc_pop_fndecl = define_function ("__gc_pop",
                    976:                                   build_function_type (void_type_node,
                    977:                                                        void_list_node),
                    978:                                   NOT_BUILT_IN, 0, 0);
                    979:   gc_nonobject = build_int_2 (0x80000000, 0);
                    980:   gc_visible = build_int_2 (0x40000000, 0);
                    981:   gc_white = integer_zero_node;
                    982:   gc_offwhite = build_int_2 (0x10000000, 0);
                    983:   gc_grey = build_int_2 (0x20000000, 0);
                    984:   gc_black = build_int_2 (0x30000000, 0);
                    985: }

unix.superglobalmegacorp.com

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