Annotation of gcc/cp-gc.c, revision 1.1.1.4

1.1       root        1: /* Garbage collection primitives for GNU C++.
                      2:    Copyright (C) 1992 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"
1.1.1.2   root       26: 
1.1       root       27: #define NULL 0
                     28: 
                     29: extern tree build_t_desc_overload ();
                     30: 
                     31: /* This is the function decl for the (pseudo-builtin) __gc_protect
                     32:    function.  Args are (class *value, int index); Returns value.  */
                     33: tree gc_protect_fndecl;
                     34: 
                     35: /* This is the function decl for the (pseudo-builtin) __gc_unprotect
                     36:    function.  Args are (int index); void return.  */
                     37: tree gc_unprotect_fndecl;
                     38: 
                     39: /* This is the function decl for the (pseudo-builtin) __gc_push
                     40:    function.  Args are (int length); void return.  */
                     41: tree gc_push_fndecl;
                     42: 
                     43: /* This is the function decl for the (pseudo-builtin) __gc_pop
                     44:    function.  Args are void; void return.  */
                     45: tree gc_pop_fndecl;
                     46: 
                     47: /* Special integers that are used to represent bits in gc-safe objects.  */
                     48: tree gc_nonobject;
                     49: tree gc_visible;
                     50: tree gc_white;
                     51: tree gc_offwhite;
                     52: tree gc_grey;
                     53: tree gc_black;
                     54: 
                     55: /* Predicate that returns non-zero if TYPE needs some kind of
                     56:    entry for the GC.  Returns zero otherwise.  */
                     57: int
                     58: type_needs_gc_entry (type)
                     59:      tree type;
                     60: {
                     61:   tree ttype = type;
                     62: 
                     63:   if (! flag_gc || type == error_mark_node)
                     64:     return 0;
                     65: 
                     66:   /* Aggregate types need gc entries if any of their members
                     67:      need gc entries.  */
                     68:   if (IS_AGGR_TYPE (type))
                     69:     {
                     70:       tree binfos;
                     71:       tree fields = TYPE_FIELDS (type);
                     72:       int i;
                     73: 
                     74:       /* We don't care about certain pointers.  Pointers
                     75:         to virtual baseclasses are always up front.  We also
                     76:         cull out virtual function table pointers because it's
                     77:         easy, and it simplifies the logic.*/
                     78:       while (fields
                     79:             && (DECL_NAME (fields) == NULL_TREE
                     80:                 || VFIELD_NAME_P (DECL_NAME (fields))
                     81:                 || VBASE_NAME_P (DECL_NAME (fields))
                     82:                 || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits")))
                     83:        fields = TREE_CHAIN (fields);
                     84: 
                     85:       while (fields)
                     86:        {
                     87:          if (type_needs_gc_entry (TREE_TYPE (fields)))
                     88:            return 1;
                     89:          fields = TREE_CHAIN (fields);
                     90:        }
                     91: 
                     92:       binfos = TYPE_BINFO_BASETYPES (type);
                     93:       if (binfos)
                     94:        for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
                     95:          if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))
                     96:            return 1;
                     97: 
                     98:       return 0;
                     99:     }
                    100: 
                    101:   while (TREE_CODE (ttype) == ARRAY_TYPE
                    102:         && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE)
                    103:     ttype = TREE_TYPE (ttype);
                    104:   if ((TREE_CODE (ttype) == POINTER_TYPE
                    105:        || TREE_CODE (ttype) == ARRAY_TYPE
                    106:        || TREE_CODE (ttype) == REFERENCE_TYPE)
                    107:       && IS_AGGR_TYPE (TREE_TYPE (ttype))
                    108:       && CLASSTYPE_DOSSIER (TREE_TYPE (ttype)))
                    109:     return 1;
                    110: 
                    111:   return 0;
                    112: }
                    113: 
                    114: /* Predicate that returns non-zero iff FROM is safe from the GC.
                    115:    
                    116:    If TO is nonzero, it means we know that FROM is being stored
                    117:    in TO, which make make it safe.  */
                    118: int
                    119: value_safe_from_gc (to, from)
                    120:      tree to, from;
                    121: {
                    122:   /* First, return non-zero for easy cases: parameters,
                    123:      static variables.  */
                    124:   if (TREE_CODE (from) == PARM_DECL
                    125:       || (TREE_CODE (from) == VAR_DECL
                    126:          && TREE_STATIC (from)))
                    127:     return 1;
                    128: 
                    129:   /* If something has its address taken, it cannot be
                    130:      in the heap, so it doesn't need to be protected.  */
                    131:   if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from))
                    132:     return 1;
                    133: 
                    134:   /* If we are storing into a static variable, then what
                    135:      we store will be safe from the gc.  */
                    136:   if (to && TREE_CODE (to) == VAR_DECL
                    137:       && TREE_STATIC (to))
                    138:     return 1;
                    139: 
                    140:   /* Now recurse on structure of FROM.  */
                    141:   switch (TREE_CODE (from))
                    142:     {
                    143:     case COMPONENT_REF:
                    144:       /* These guys are special, and safe.  */
                    145:       if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL
                    146:          && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))
                    147:              || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))))
                    148:        return 1;
                    149:       /* fall through...  */
                    150:     case NOP_EXPR:
                    151:     case CONVERT_EXPR:
                    152:     case NON_LVALUE_EXPR:
                    153:     case WITH_CLEANUP_EXPR:
                    154:     case SAVE_EXPR:
                    155:     case PREDECREMENT_EXPR:
                    156:     case PREINCREMENT_EXPR:
                    157:     case POSTDECREMENT_EXPR:
                    158:     case POSTINCREMENT_EXPR:
                    159:       if (value_safe_from_gc (to, TREE_OPERAND (from, 0)))
                    160:        return 1;
                    161:       break;
                    162: 
                    163:     case VAR_DECL:
                    164:     case PARM_DECL:
                    165:       /* We can safely pass these things as parameters to functions.  */
                    166:       if (to == 0)
                    167:        return 1;
                    168: 
                    169:     case ARRAY_REF:
                    170:     case INDIRECT_REF:
                    171:     case RESULT_DECL:
                    172:     case OFFSET_REF:
                    173:     case CALL_EXPR:
                    174:     case METHOD_CALL_EXPR:
                    175:       break;
                    176: 
                    177:     case COMPOUND_EXPR:
                    178:     case TARGET_EXPR:
                    179:       if (value_safe_from_gc (to, TREE_OPERAND (from, 1)))
                    180:        return 1;
                    181:       break;
                    182: 
                    183:     case COND_EXPR:
                    184:       if (value_safe_from_gc (to, TREE_OPERAND (from, 1))
                    185:          && value_safe_from_gc (to, TREE_OPERAND (from, 2)))
                    186:        return 1;
                    187:       break;
                    188: 
                    189:     case PLUS_EXPR:
                    190:     case MINUS_EXPR:
                    191:       if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0)))
                    192:           || value_safe_from_gc (to, TREE_OPERAND (from, 0)))
                    193:          && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0
                    194:              || value_safe_from_gc (to, TREE_OPERAND (from, 1))))
                    195:        return 1;
                    196:       break;
                    197: 
                    198:     case RTL_EXPR:
                    199:       /* Every time we build an RTL_EXPR in the front-end, we must
                    200:         ensure that everything in it is safe from the garbage collector.
                    201:         ??? This has only been done for `build_new'.  */
                    202:       return 1;
                    203: 
                    204:     default:
1.1.1.3   root      205:       my_friendly_abort (41);
1.1       root      206:     }
                    207: 
                    208:   if (to == 0)
                    209:     return 0;
                    210: 
                    211:   /* FROM wasn't safe.  But other properties of TO might make it safe.  */
                    212:   switch (TREE_CODE (to))
                    213:     {
                    214:     case VAR_DECL:
                    215:     case PARM_DECL:
                    216:       /* We already culled out static VAR_DECLs above.  */
                    217:       return 0;
                    218: 
                    219:     case COMPONENT_REF:
                    220:       /* These guys are special, and safe.  */
                    221:       if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL
                    222:          && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))
                    223:              || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))))
                    224:        return 1;
                    225:       /* fall through...  */
                    226: 
                    227:     case NOP_EXPR:
                    228:     case NON_LVALUE_EXPR:
                    229:     case WITH_CLEANUP_EXPR:
                    230:     case SAVE_EXPR:
                    231:     case PREDECREMENT_EXPR:
                    232:     case PREINCREMENT_EXPR:
                    233:     case POSTDECREMENT_EXPR:
                    234:     case POSTINCREMENT_EXPR:
                    235:       return value_safe_from_gc (TREE_OPERAND (to, 0), from);
                    236: 
                    237:     case COMPOUND_EXPR:
                    238:     case TARGET_EXPR:
                    239:       return value_safe_from_gc (TREE_OPERAND (to, 1), from);
                    240: 
                    241:     case COND_EXPR:
                    242:       return (value_safe_from_gc (TREE_OPERAND (to, 1), from)
                    243:              && value_safe_from_gc (TREE_OPERAND (to, 2), from));
                    244: 
                    245:     case INDIRECT_REF:
                    246:     case ARRAY_REF:
                    247:       /* This used to be 0, but our current restricted model
                    248:         allows this to be 1.  We'll never get arrays this way.  */
                    249:       return 1;
                    250: 
                    251:     default:
1.1.1.3   root      252:       my_friendly_abort (42);
1.1       root      253:     }
                    254: 
                    255:   /* Catch-all case is that TO/FROM is not safe.  */
                    256:   return 0;
                    257: }
                    258: 
                    259: /* Function to build a static GC entry for DECL.  TYPE is DECL's type.
                    260: 
                    261:    For objects of type `class *', this is just an entry in the
                    262:    static vector __PTR_LIST__.
                    263: 
                    264:    For objects of type `class[]', this requires building an entry
                    265:    in the static vector __ARR_LIST__.
                    266: 
                    267:    For aggregates, this records all fields of type `class *'
                    268:    and `class[]' in the respective lists above.  */
                    269: void
                    270: build_static_gc_entry (decl, type)
                    271:      tree decl;
                    272:      tree type;
                    273: {
                    274:   /* Now, figure out what sort of entry to build.  */
                    275:   if (TREE_CODE (type) == POINTER_TYPE
                    276:       || TREE_CODE (type) == REFERENCE_TYPE)
                    277:     assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl)));
                    278:   else if (TREE_CODE (type) == RECORD_TYPE)
                    279:     {
                    280:       tree ref = get_temp_name (build_reference_type (type), 1);
                    281:       DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl);
                    282:       TREE_CONSTANT (DECL_INITIAL (ref)) = 1;
                    283:       finish_decl (ref, DECL_INITIAL (ref), 0, 0);
                    284:     }
                    285:   else
                    286:     {
                    287:       /* Not yet implemented.
                    288:         
                    289:         Cons up a static variable that holds address and length info
                    290:         and add that to ___ARR_LIST__.  */
1.1.1.3   root      291:       my_friendly_abort (43);
1.1       root      292:     }
                    293: }
                    294: 
                    295: /* Protect FROM from the GC, assuming FROM is going to be
                    296:    stored into TO.  We handle three cases for TO here:
                    297: 
                    298:    case 1: TO is a stack variable.
                    299:    case 2: TO is zero (which means it is a parameter).
                    300:    case 3: TO is a return value.  */
                    301: 
                    302: tree
                    303: protect_value_from_gc (to, from)
                    304:      tree to, from;
                    305: {
                    306:   if (to == 0)
                    307:     {
                    308:       tree cleanup;
                    309: 
                    310:       to = get_temp_regvar (TREE_TYPE (from), from);
                    311: 
                    312:       /* Convert from integer to list form since we'll use it twice.  */
                    313:       DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
                    314:       cleanup = build_function_call (gc_unprotect_fndecl,
                    315:                                     DECL_GC_OFFSET (to));
                    316: 
                    317:       if (! expand_decl_cleanup (to, cleanup))
                    318:        {
                    319:          compiler_error ("cannot unprotect parameter in this scope");
                    320:          return error_mark_node;
                    321:        }
                    322:     }
                    323: 
                    324:   /* Should never need to protect a value that's headed for static storage.  */
                    325:   if (TREE_STATIC (to))
1.1.1.3   root      326:     my_friendly_abort (44);
1.1       root      327: 
                    328:   switch (TREE_CODE (to))
                    329:     {
                    330:     case COMPONENT_REF:
                    331:     case INDIRECT_REF:
                    332:       return protect_value_from_gc (TREE_OPERAND (to, 0), from);
                    333: 
                    334:     case VAR_DECL:
                    335:     case PARM_DECL:
                    336:       {
                    337:        tree rval;
                    338:        if (DECL_GC_OFFSET (to) == NULL_TREE)
                    339:          {
                    340:            /* Because of a cast or a conversion, we might stick
                    341:               a value into a variable that would not normally
                    342:               have a GC entry.  */
                    343:            DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index);
                    344:          }
                    345: 
                    346:        if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST)
                    347:          {
                    348:            DECL_GC_OFFSET (to)
                    349:              = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
                    350:          }
                    351: 
                    352:        current_function_obstack_usage = 1;
                    353:        rval = build_function_call (gc_protect_fndecl,
                    354:                                    tree_cons (NULL_TREE, from,
                    355:                                               DECL_GC_OFFSET (to)));
                    356:        TREE_TYPE (rval) = TREE_TYPE (from);
                    357:        return rval;
                    358:       }
                    359:     }
                    360: 
                    361:   /* If we fall through the switch, assume we lost.  */
1.1.1.3   root      362:   my_friendly_abort (45);
1.1       root      363:   /* NOTREACHED */
                    364:   return NULL_TREE;
                    365: }
                    366: 
                    367: /* Given the expression EXP of type `class *', return the head
                    368:    of the object pointed to by EXP.  */
                    369: tree
                    370: build_headof (exp)
                    371:      tree exp;
                    372: {
                    373:   tree type = TREE_TYPE (exp);
                    374:   tree vptr, offset;
                    375: 
                    376:   if (TREE_CODE (type) != POINTER_TYPE)
                    377:     {
                    378:       error ("`headof' applied to non-pointer type");
                    379:       return error_mark_node;
                    380:     }
                    381: 
                    382:   vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
                    383:   offset = build_component_ref (build_array_ref (vptr, integer_one_node),
                    384:                                get_identifier (VTABLE_DELTA_NAME),
                    385:                                NULL_TREE, 0);
                    386:   return build (PLUS_EXPR, class_star_type_node, exp,
                    387:                convert (integer_type_node, offset));
                    388: }
                    389: 
                    390: /* Given the expression EXP of type `class *', return the
                    391:    type descriptor for the object pointed to by EXP.  */
                    392: tree
                    393: build_classof (exp)
                    394:      tree exp;
                    395: {
                    396:   tree type = TREE_TYPE (exp);
                    397:   tree vptr;
                    398:   tree t_desc_entry;
                    399: 
                    400:   if (TREE_CODE (type) != POINTER_TYPE)
                    401:     {
                    402:       error ("`classof' applied to non-pointer type");
                    403:       return error_mark_node;
                    404:     }
                    405: 
                    406:   vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
                    407:   t_desc_entry = build_component_ref (build_array_ref (vptr, integer_one_node),
                    408:                                      get_identifier (VTABLE_PFN_NAME),
                    409:                                      NULL_TREE, 0);
                    410:   TREE_TYPE (t_desc_entry) = TYPE_POINTER_TO (__t_desc_type_node);
                    411:   return t_desc_entry;
                    412: }
                    413: 
                    414: /* Build and initialize various sorts of descriptors.  Every descriptor
                    415:    node has a name associated with it (the name created by mangling).
                    416:    For this reason, we use the identifier as our access to the __*_desc
                    417:    nodes, instead of sticking them directly in the types.  Otherwise we
                    418:    would burden all built-in types (and pointer types) with slots that
                    419:    we don't necessarily want to use.
                    420: 
                    421:    For each descriptor we build, we build a variable that contains
                    422:    the descriptor's information.  When we need this info at runtime,
                    423:    all we need is access to these variables.
                    424: 
                    425:    Note: these constructors always return the address of the descriptor
                    426:    info, since that is simplest for their mutual interaction.  */
                    427: 
                    428: static tree
                    429: build_generic_desc (decl, elems)
                    430:      tree decl;
                    431:      tree elems;
                    432: {
                    433:   tree init = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, elems);
                    434:   TREE_CONSTANT (init) = 1;
                    435:   TREE_STATIC (init) = 1;
                    436:   TREE_READONLY (init) = 1;
                    437: 
                    438:   DECL_INITIAL (decl) = init;
                    439:   TREE_STATIC (decl) = 1;
                    440:   layout_decl (decl, 0);
                    441:   finish_decl (decl, init, 0, 0);
                    442: 
                    443:   return IDENTIFIER_AS_DESC (DECL_NAME (decl));
                    444: }
                    445: 
                    446: /* Build an initializer for a __t_desc node.  So that we can take advantage
                    447:    of recursion, we accept NULL for TYPE.
                    448:    DEFINITION is greater than zero iff we must define the type descriptor
                    449:    (as opposed to merely referencing it).  1 means treat according to
                    450:    #pragma interface/#pragma implementation rules.  2 means define as
                    451:    global and public, no matter what.  */
                    452: tree
                    453: build_t_desc (type, definition)
                    454:      tree type;
                    455:      int definition;
                    456: {
                    457:   tree tdecl;
                    458:   tree tname, name_string;
                    459:   tree elems, fields;
                    460:   tree parents, vbases, offsets, ivars, methods, target_type;
                    461:   int method_count = 0, field_count = 0;
                    462: 
                    463:   if (type == NULL_TREE)
                    464:     return NULL_TREE;
                    465: 
                    466:   tname = build_t_desc_overload (type);
                    467:   if (IDENTIFIER_AS_DESC (tname)
                    468:       && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
                    469:     return IDENTIFIER_AS_DESC (tname);
                    470: 
                    471:   tdecl = lookup_name (tname, 0);
                    472:   if (tdecl == NULL_TREE)
                    473:     {
                    474:       tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1.1.1.4 ! root      475:       DECL_EXTERNAL (tdecl) = 1;
1.1       root      476:       TREE_PUBLIC (tdecl) = 1;
                    477:       tdecl = pushdecl_top_level (tdecl);
                    478:     }
                    479:   /* If we previously defined it, return the defined result.  */
                    480:   else if (definition && DECL_INITIAL (tdecl))
                    481:     return IDENTIFIER_AS_DESC (tname);
                    482: 
                    483:   if (definition)
                    484:     {
                    485:       tree taggr = type;
                    486:       /* Let T* and T& be written only when T is written (if T is an aggr).
                    487:          We do this for const, but not for volatile, since volatile
                    488:         is rare and const is not.  */
                    489:       if (!TYPE_VOLATILE (taggr)
                    490:          && (TREE_CODE (taggr) == POINTER_TYPE
                    491:              || TREE_CODE (taggr) == REFERENCE_TYPE)
                    492:          && IS_AGGR_TYPE (TREE_TYPE (taggr)))
                    493:        taggr = TREE_TYPE (taggr);
                    494: 
                    495:       /* If we know that we don't need to write out this type's
                    496:         vtable, then don't write out it's dossier.  Somebody
                    497:         else will take care of that.  */
                    498:       if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
                    499:        {
                    500:          if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
                    501:            {
                    502:              TREE_PUBLIC (tdecl) = !(CLASSTYPE_INTERFACE_ONLY (taggr)
                    503:                                      || CLASSTYPE_INTERFACE_UNKNOWN (taggr));
                    504:              TREE_STATIC (tdecl) = 1;
1.1.1.4 ! root      505:              DECL_EXTERNAL (tdecl) = 0;
1.1       root      506:            }
                    507:          else
                    508:            {
                    509:              if (write_virtuals != 0)
                    510:                TREE_PUBLIC (tdecl) = 1;
                    511:            }
                    512:        }
                    513:       else
                    514:        {
1.1.1.4 ! root      515:          DECL_EXTERNAL (tdecl) = 0;
1.1       root      516:          TREE_STATIC (tdecl) = 1;
                    517:          TREE_PUBLIC (tdecl) = (definition > 1);
                    518:        }
                    519:     }
                    520:   SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1.1.1.4 ! root      521:   if (!definition || DECL_EXTERNAL (tdecl))
1.1       root      522:     {
                    523:       /* That's it!  */
                    524:       finish_decl (tdecl, 0, 0, 0);
                    525:       return IDENTIFIER_AS_DESC (tname);
                    526:     }
                    527: 
                    528:   /* Show that we are defining the t_desc for this type.  */
                    529:   DECL_INITIAL (tdecl) = error_mark_node;
                    530: 
                    531:   parents = build_tree_list (NULL_TREE, integer_zero_node);
                    532:   vbases = build_tree_list (NULL_TREE, integer_zero_node);
                    533:   offsets = build_tree_list (NULL_TREE, integer_zero_node);
                    534:   methods = NULL_TREE;
                    535:   ivars = NULL_TREE;
                    536: 
                    537:   if (TYPE_LANG_SPECIFIC (type))
                    538:     {
                    539:       int i = CLASSTYPE_N_BASECLASSES (type);
                    540:       tree method_vec = CLASSTYPE_METHOD_VEC (type);
                    541:       tree *meth, *end;
                    542:       tree binfos = TYPE_BINFO_BASETYPES (type);
                    543:       tree vb = CLASSTYPE_VBASECLASSES (type);
                    544: 
                    545:       while (--i >= 0)
                    546:        parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
                    547: 
                    548:       while (vb)
                    549:        {
                    550:          vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
                    551:          offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
                    552:          vb = TREE_CHAIN (vb);
                    553:        }
                    554: 
                    555:       if (method_vec)
                    556:        for (meth = TREE_VEC_END (method_vec),
                    557:             end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
                    558:          if (*meth)
                    559:            {
                    560:              methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
                    561:              method_count++;
                    562:            }
                    563:     }
                    564: 
                    565:   if (IS_AGGR_TYPE (type))
                    566:     {
                    567:       for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
                    568:        if (TREE_CODE (fields) == FIELD_DECL
                    569:            || TREE_CODE (fields) == VAR_DECL)
                    570:          {
                    571:            ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
                    572:            field_count++;
                    573:          }
                    574:       ivars = nreverse (ivars);
                    575:     }
                    576: 
                    577:   parents = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), parents, 0);
                    578:   vbases = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), vbases, 0);
                    579:   offsets = finish_table (0, integer_type_node, offsets, 0);
                    580:   methods = finish_table (0, __m_desc_type_node, methods, 0);
                    581:   ivars = finish_table (0, __i_desc_type_node, ivars, 0);
                    582:   if (TREE_TYPE (type))
                    583:     target_type = build_t_desc (TREE_TYPE (type), definition);
                    584:   else
                    585:     target_type = integer_zero_node;
                    586: 
                    587:   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
                    588: 
                    589:   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
                    590:           tree_cons (NULL_TREE,
                    591:                      TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
                    592:             /* really should use bitfield initialization here.  */
                    593:             tree_cons (NULL_TREE, integer_zero_node,
                    594:              tree_cons (NULL_TREE, target_type,
                    595:               tree_cons (NULL_TREE, build_int_2 (field_count, 2),
                    596:                tree_cons (NULL_TREE, build_int_2 (method_count, 2),
                    597:                 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, ivars, 0),
                    598:                  tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, methods, 0),
                    599:                   tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
                    600:                    tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
                    601:                     build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
                    602:   return build_generic_desc (tdecl, elems);
                    603: }
                    604: 
                    605: /* Build an initializer for a __i_desc node.  */
                    606: tree
                    607: build_i_desc (decl)
                    608:      tree decl;
                    609: {
                    610:   tree elems, name_string;
                    611:   tree taggr;
                    612: 
                    613:   name_string = DECL_NAME (decl);
                    614:   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
                    615: 
                    616:   /* Now decide whether this ivar should cause it's type to get
                    617:      def'd or ref'd in this file.  If the type we are looking at
                    618:      has a proxy definition, we look at the proxy (i.e., a
                    619:      `foo *' is equivalent to a `foo').  */
                    620:   taggr = TREE_TYPE (decl);
                    621: 
                    622:   if ((TREE_CODE (taggr) == POINTER_TYPE
                    623:        || TREE_CODE (taggr) == REFERENCE_TYPE)
                    624:       && TYPE_VOLATILE (taggr) == 0)
                    625:     taggr = TREE_TYPE (taggr);
                    626: 
                    627:   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
                    628:             tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
                    629:                build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
                    630:                                                          ! IS_AGGR_TYPE (taggr)))));
                    631:   taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
                    632:   TREE_CONSTANT (taggr) = 1;
                    633:   TREE_STATIC (taggr) = 1;
                    634:   TREE_READONLY (taggr) = 1;
                    635:   return taggr;
                    636: }
                    637: 
                    638: /* Build an initializer for a __m_desc node.  */
                    639: tree
                    640: build_m_desc (decl)
                    641:      tree decl;
                    642: {
                    643:   tree taggr, elems, name_string;
                    644:   tree parm_count, req_count, vindex, vcontext;
                    645:   tree parms;
                    646:   int p_count, r_count;
                    647:   tree parm_types = NULL_TREE;
                    648: 
                    649:   for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
                    650:        parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
                    651:     {
                    652:       taggr = TREE_VALUE (parms);
                    653:       if ((TREE_CODE (taggr) == POINTER_TYPE
                    654:           || TREE_CODE (taggr) == REFERENCE_TYPE)
                    655:          && TYPE_VOLATILE (taggr) == 0)
                    656:        taggr = TREE_TYPE (taggr);
                    657: 
                    658:       parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
                    659:                                                       ! IS_AGGR_TYPE (taggr)),
                    660:                              parm_types);
                    661:       if (TREE_PURPOSE (parms) == NULL_TREE)
                    662:        r_count++;
                    663:     }
                    664: 
                    665:   parm_types = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node),
                    666:                             nreverse (parm_types), 0);
                    667:   parm_count = build_int_2 (p_count, 0);
                    668:   req_count = build_int_2 (r_count, 0);
                    669: 
                    670:   if (DECL_VINDEX (decl))
                    671:     vindex = DECL_VINDEX (decl);
                    672:   else
                    673:     vindex = integer_zero_node;
1.1.1.4 ! root      674:   if (DECL_CONTEXT (decl)
        !           675:       && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
1.1       root      676:     vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
                    677:   else
                    678:     vcontext = integer_zero_node;
                    679:   name_string = DECL_NAME (decl);
                    680:   if (name_string == NULL)
                    681:       name_string = DECL_ASSEMBLER_NAME (decl);
                    682:   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
                    683: 
                    684:   /* Now decide whether the return type of this mvar
                    685:      should cause it's type to get def'd or ref'd in this file.
                    686:      If the type we are looking at has a proxy definition,
                    687:      we look at the proxy (i.e., a `foo *' is equivalent to a `foo').  */
                    688:   taggr = TREE_TYPE (TREE_TYPE (decl));
                    689: 
                    690:   if ((TREE_CODE (taggr) == POINTER_TYPE
                    691:        || TREE_CODE (taggr) == REFERENCE_TYPE)
                    692:       && TYPE_VOLATILE (taggr) == 0)
                    693:     taggr = TREE_TYPE (taggr);
                    694: 
                    695:   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
                    696:             tree_cons (NULL_TREE, vindex,
                    697:                tree_cons (NULL_TREE, vcontext,
                    698:                   tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
                    699:                                                       ! IS_AGGR_TYPE (taggr)),
                    700:                      tree_cons (NULL_TREE, build_c_cast (TYPE_POINTER_TO (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
                    701:                         tree_cons (NULL_TREE, parm_count,
                    702:                            tree_cons (NULL_TREE, req_count,
                    703:                               build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
                    704: 
                    705:   taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
                    706:   TREE_CONSTANT (taggr) = 1;
                    707:   TREE_STATIC (taggr) = 1;
                    708:   TREE_READONLY (taggr) = 1;
                    709:   return taggr;
                    710: }
                    711: 
                    712: /* Conditionally emit code to set up an unwind-protect for the
                    713:    garbage collector.  If this function doesn't do anything that involves
                    714:    the garbage collector, then do nothing.  Otherwise, call __gc_push
                    715:    at the beginning and __gc_pop at the end.
                    716: 
                    717:    NOTE!  The __gc_pop function must operate transparently, since
                    718:    it comes where the logical return label lies.  This means that
                    719:    at runtime *it* must preserve any return value registers.  */
                    720: 
                    721: void
                    722: expand_gc_prologue_and_epilogue ()
                    723: {
                    724:   extern tree maybe_gc_cleanup;
                    725:   struct rtx_def *last_parm_insn, *mark;
                    726:   extern struct rtx_def *get_last_insn ();
                    727:   extern struct rtx_def *get_first_nonparm_insn ();
                    728:   extern struct rtx_def *previous_insn ();
                    729:   tree action;
                    730: 
                    731:   /* If we didn't need the obstack, don't cons any space.  */
                    732:   if (current_function_obstack_index == 0
                    733:       || current_function_obstack_usage == 0)
                    734:     return;
                    735: 
                    736:   mark = get_last_insn ();
                    737:   last_parm_insn = get_first_nonparm_insn ();
                    738:   if (last_parm_insn == 0) last_parm_insn = mark;
                    739:   else last_parm_insn = previous_insn (last_parm_insn);
                    740: 
                    741:   action = build_function_call (gc_push_fndecl,
                    742:                                build_tree_list (NULL_TREE, size_int (++current_function_obstack_index)));
                    743:   expand_expr_stmt (action);
                    744: 
                    745:   reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
                    746: 
                    747:   /* This will be expanded as a cleanup.  */
                    748:   TREE_VALUE (maybe_gc_cleanup)
                    749:     = build_function_call (gc_pop_fndecl, NULL_TREE);
                    750: }
                    751: 
                    752: /* Some day we'll use this function as a call-back and clean
                    753:    up all the unnecessary gc dribble that we otherwise create.  */
                    754: void
                    755: lang_expand_end_bindings (first, last)
                    756:      struct rtx_def *first, *last;
                    757: {
                    758: }
                    759: 
                    760: void
                    761: init_gc_processing ()
                    762: {
                    763:   tree parmtypes = hash_tree_chain (class_star_type_node,
                    764:                                    hash_tree_chain (integer_type_node, NULL_TREE));
                    765:   gc_protect_fndecl = define_function ("__gc_protect",
                    766:                                       build_function_type (class_star_type_node, parmtypes),
                    767:                                       NOT_BUILT_IN, 0, 0);
                    768: 
                    769:   parmtypes = hash_tree_chain (integer_type_node, NULL_TREE);
                    770:   gc_unprotect_fndecl = define_function ("__gc_unprotect",
                    771:                                         build_function_type (void_type_node, parmtypes),
                    772:                                         NOT_BUILT_IN, 0, 0);
                    773: 
                    774:   gc_push_fndecl = define_function ("__gc_push",
                    775:                                    TREE_TYPE (gc_unprotect_fndecl),
                    776:                                    NOT_BUILT_IN, 0, 0);
                    777: 
                    778:   gc_pop_fndecl = define_function ("__gc_pop",
                    779:                                   build_function_type (void_type_node,
                    780:                                                        void_list_node),
                    781:                                   NOT_BUILT_IN, 0, 0);
                    782:   gc_nonobject = build_int_2 (0x80000000, 0);
                    783:   gc_visible = build_int_2 (0x40000000, 0);
                    784:   gc_white = integer_zero_node;
                    785:   gc_offwhite = build_int_2 (0x10000000, 0);
                    786:   gc_grey = build_int_2 (0x20000000, 0);
                    787:   gc_black = build_int_2 (0x30000000, 0);
                    788: }

unix.superglobalmegacorp.com

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