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

1.1       root        1: /* Convert language-specific tree expression to rtl instructions,
                      2:    for GNU compiler.
1.1.1.2 ! root        3:    Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
1.1       root        4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU CC; see the file COPYING.  If not, write to
1.1.1.2 ! root       19: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            20: Boston, MA 02111-1307, USA.  */
1.1       root       21: 
                     22: 
                     23: #include "config.h"
                     24: #include "rtl.h"
                     25: #include "tree.h"
                     26: #include "flags.h"
                     27: #include "expr.h"
                     28: #include "cp-tree.h"
                     29: 
                     30: #undef NULL
                     31: #define NULL 0
                     32: 
                     33: /* Hook used by expand_expr to expand language-specific tree codes.  */
                     34: 
                     35: rtx
                     36: cplus_expand_expr (exp, target, tmode, modifier)
                     37:      tree exp;
                     38:      rtx target;
                     39:      enum machine_mode tmode;
                     40:      enum expand_modifier modifier;
                     41: {
                     42:   tree type = TREE_TYPE (exp);
                     43:   register enum machine_mode mode = TYPE_MODE (type);
                     44:   register enum tree_code code = TREE_CODE (exp);
                     45:   rtx original_target = target;
                     46:   int ignore = target == const0_rtx;
                     47: 
                     48:   if (ignore)
                     49:     target = 0, original_target = 0;
                     50: 
                     51:   /* No sense saving up arithmetic to be done
                     52:      if it's all in the wrong mode to form part of an address.
                     53:      And force_operand won't know whether to sign-extend or zero-extend.  */
                     54: 
                     55:   if (mode != Pmode && modifier == EXPAND_SUM)
                     56:     modifier = EXPAND_NORMAL;
                     57: 
                     58:   switch (code)
                     59:     {
                     60:     case NEW_EXPR:
                     61:       {
                     62:        /* Something needs to be initialized, but we didn't know
                     63:           where that thing was when building the tree.  For example,
                     64:           it could be the return value of a function, or a parameter
                     65:           to a function which lays down in the stack, or a temporary
                     66:           variable which must be passed by reference.
                     67: 
                     68:           Cleanups are handled in a language-specific way: they
                     69:           might be run by the called function (true in GNU C++
                     70:           for parameters with cleanups), or they might be
                     71:           run by the caller, after the call (true in GNU C++
                     72:           for other cleanup needs).  */
                     73: 
                     74:        tree func = TREE_OPERAND (exp, 0);
                     75:        tree args = TREE_OPERAND (exp, 1);
                     76:        tree type = TREE_TYPE (exp), slot;
                     77:        tree fn_type = TREE_TYPE (TREE_TYPE (func));
                     78:        tree return_type = TREE_TYPE (fn_type);
                     79:        tree call_exp;
                     80:        rtx call_target, return_target;
                     81:        int pcc_struct_return = 0;
                     82: 
                     83:        /* The expression `init' wants to initialize what
                     84:           `target' represents.  SLOT holds the slot for TARGET.  */
                     85:        slot = TREE_OPERAND (exp, 2);
                     86: 
                     87:        if (target == 0)
                     88:          {
                     89:            /* Should always be called with a target in BLKmode case.  */
                     90:            my_friendly_assert (mode != BLKmode, 205);
                     91:            my_friendly_assert (DECL_RTL (slot) != 0, 206);
                     92: 
                     93:            target = gen_reg_rtx (mode);
                     94:          }
                     95: 
                     96:        /* The target the initializer will initialize (CALL_TARGET)
                     97:           must now be directed to initialize the target we are
                     98:           supposed to initialize (TARGET).  The semantics for
                     99:           choosing what CALL_TARGET is is language-specific,
                    100:           as is building the call which will perform the
                    101:           initialization.  It is left here to show the choices that
                    102:           exist for C++.  */
                    103:           
                    104:        if (TREE_CODE (func) == ADDR_EXPR
                    105:            && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
                    106:            && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
                    107:          {
1.1.1.2 ! root      108:            type = build_pointer_type (type);
1.1       root      109:            /* Don't clobber a value that might be part of a default
                    110:               parameter value.  */
1.1.1.2 ! root      111:            mark_addressable (slot);
1.1       root      112:            if (TREE_PERMANENT (args))
                    113:              args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
                    114:                                TREE_CHAIN (args));
                    115:            else
                    116:              TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
                    117:            call_target = 0;
                    118:          }
                    119:        else if (TREE_CODE (return_type) == REFERENCE_TYPE)
                    120:          {
                    121:            type = return_type;
                    122:            call_target = 0;
                    123:          }
                    124:        else
                    125:          {
                    126: #ifdef PCC_STATIC_STRUCT_RETURN
                    127:            pcc_struct_return = 1;
                    128:            call_target = 0;
                    129: #else
                    130:            call_target = target;
                    131: #endif
                    132:          }
                    133:        if (call_target)
                    134:          {
                    135:            /* Make this a valid memory address now.  The code below assumes
                    136:               that it can compare rtx and make assumptions based on the
                    137:               result.  The assumptions are true only if the address was
                    138:               valid to begin with.  */
                    139:            call_target = validize_mem (call_target);
                    140:          }
                    141: 
                    142:        call_exp = build (CALL_EXPR, type, func, args, 0);
                    143:        TREE_SIDE_EFFECTS (call_exp) = 1;
1.1.1.2 ! root      144:        return_target = expand_call (call_exp, call_target, ignore);
1.1       root      145:        if (call_target == 0)
                    146:          {
                    147:            if (pcc_struct_return)
                    148:              {
                    149:                extern int flag_access_control;
                    150:                int old_ac = flag_access_control;
                    151: 
1.1.1.2 ! root      152:                tree init = build_decl (VAR_DECL, 0, type);
1.1       root      153:                TREE_ADDRESSABLE (init) = 1;
1.1.1.2 ! root      154:                DECL_RTL (init) = return_target;
1.1       root      155: 
                    156:                flag_access_control = 0;
1.1.1.2 ! root      157:                expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
1.1       root      158:                flag_access_control = old_ac;
                    159: 
                    160:                if (TYPE_NEEDS_DESTRUCTOR (type))
                    161:                  {
1.1.1.2 ! root      162:                    init = build_decl (VAR_DECL, 0,
        !           163:                                       build_reference_type (type));
        !           164:                    DECL_RTL (init) = XEXP (return_target, 0);
        !           165: 
1.1       root      166:                    init = maybe_build_cleanup (convert_from_reference (init));
                    167:                    if (init != NULL_TREE)
                    168:                      expand_expr (init, 0, 0, 0);
                    169:                  }
                    170:                call_target = return_target = DECL_RTL (slot);
                    171:              }
                    172:            else
                    173:              call_target = return_target;
                    174:          }
                    175: 
                    176:        if (call_target != return_target)
                    177:          {
1.1.1.2 ! root      178:            my_friendly_assert (TYPE_HAS_TRIVIAL_INIT_REF (type), 317);
1.1       root      179:            if (GET_MODE (return_target) == BLKmode)
                    180:              emit_block_move (call_target, return_target, expr_size (exp),
                    181:                               TYPE_ALIGN (type) / BITS_PER_UNIT);
                    182:            else
                    183:              emit_move_insn (call_target, return_target);
                    184:          }
                    185: 
                    186:        if (TREE_CODE (return_type) == REFERENCE_TYPE)
                    187:          {
                    188:            tree init;
                    189: 
                    190:            if (GET_CODE (call_target) == REG
                    191:                && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
                    192:              my_friendly_abort (39);
                    193: 
                    194:            type = TREE_TYPE (exp);
                    195: 
                    196:            init = build (RTL_EXPR, return_type, 0, call_target);
                    197:            /* We got back a reference to the type we want.  Now initialize
                    198:               target with that.  */
1.1.1.2 ! root      199:            expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
1.1       root      200:          }
                    201: 
                    202:        if (DECL_RTL (slot) != target)
                    203:          emit_move_insn (DECL_RTL (slot), target);
                    204:        return DECL_RTL (slot);
                    205:       }
                    206: 
                    207:     case OFFSET_REF:
                    208:       {
                    209: #if 1
                    210:        return expand_expr (default_conversion (resolve_offset_ref (exp)),
                    211:                            target, tmode, EXPAND_NORMAL);
                    212: #else
                    213:        /* This is old crusty code, and does not handle all that the
                    214:           resolve_offset_ref function does.  (mrs) */
                    215:        tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
                    216:        tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
                    217:        return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
                    218:                            target, tmode, EXPAND_NORMAL);
                    219: #endif
                    220:       }
                    221: 
                    222:     case THUNK_DECL:
                    223:       return DECL_RTL (exp);
                    224: 
                    225:     case THROW_EXPR:
                    226:       expand_throw (TREE_OPERAND (exp, 0));
                    227:       return NULL;
                    228: 
1.1.1.2 ! root      229:     case UNSAVE_EXPR:
        !           230:       {
        !           231:        rtx temp;
        !           232:        temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
        !           233:        TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
        !           234:        return temp;
        !           235:       }
        !           236: 
1.1       root      237:     default:
                    238:       break;
                    239:     }
                    240:   my_friendly_abort (40);
                    241:   /* NOTREACHED */
                    242:   return NULL;
                    243: }
                    244: 
                    245: void
                    246: init_cplus_expand ()
                    247: {
                    248:   lang_expand_expr = cplus_expand_expr;
                    249: }
                    250: 
                    251: /* If DECL had its rtl moved from where callers expect it
                    252:    to be, fix it up.  RESULT is the nominal rtl for the RESULT_DECL,
                    253:    which may be a pseudo instead of a hard register.  */
                    254: 
                    255: void
                    256: fixup_result_decl (decl, result)
                    257:      tree decl;
                    258:      rtx result;
                    259: {
                    260:   if (REG_P (result))
                    261:     {
                    262:       if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
                    263:        {
                    264:          rtx real_decl_result;
                    265: 
                    266: #ifdef FUNCTION_OUTGOING_VALUE
                    267:          real_decl_result
                    268:            = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
                    269: #else
                    270:          real_decl_result
                    271:            = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
                    272: #endif
                    273:          REG_FUNCTION_VALUE_P (real_decl_result) = 1;
                    274:          result = real_decl_result;
                    275:        }
1.1.1.2 ! root      276:       store_expr (decl, result, 0);
1.1       root      277:       emit_insn (gen_rtx (USE, VOIDmode, result));
                    278:     }
                    279: }
                    280: 
                    281: /* Return nonzero iff DECL is memory-based.  The DECL_RTL of
                    282:    certain const variables might be a CONST_INT, or a REG
                    283:    in some cases.  We cannot use `memory_operand' as a test
                    284:    here because on most RISC machines, a variable's address
                    285:    is not, by itself, a legitimate address.  */
1.1.1.2 ! root      286: 
1.1       root      287: int
                    288: decl_in_memory_p (decl)
                    289:      tree decl;
                    290: {
                    291:   return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
                    292: }
1.1.1.2 ! root      293: 
        !           294: /* Expand this initialization inline and see if it's simple enough that
        !           295:    it can be done at compile-time.  */
        !           296: 
        !           297: static tree
        !           298: extract_aggr_init (decl, init)
        !           299:      tree decl, init;
        !           300: {
        !           301:   return 0;
        !           302: }
        !           303: 
        !           304: static tree
        !           305: extract_scalar_init (decl, init)
        !           306:      tree decl, init;
        !           307: {
        !           308:   rtx value, insns, insn;
        !           309:   extern struct obstack temporary_obstack;
        !           310:   tree t = NULL_TREE;
        !           311: 
        !           312:   push_obstacks (&temporary_obstack, &temporary_obstack);
        !           313:   start_sequence ();
        !           314:   value = expand_expr (init, NULL_RTX, VOIDmode, 0);
        !           315:   insns = get_insns ();
        !           316:   end_sequence ();
        !           317:   reg_scan (insns, max_reg_num (), 0);
        !           318:   jump_optimize (insns, 0, 0, 1);
        !           319:   pop_obstacks ();
        !           320: 
        !           321:   for (insn = insns; insn; insn = NEXT_INSN (insn))
        !           322:     {
        !           323:       rtx r, to;
        !           324: 
        !           325:       if (GET_CODE (insn) == NOTE)
        !           326:        continue;
        !           327:       else if (GET_CODE (insn) != INSN)
        !           328:        return 0;
        !           329: 
        !           330:       r = PATTERN (insn);
        !           331:       if (GET_CODE (r) != SET)
        !           332:        return 0;
        !           333: 
        !           334:       to = XEXP (r, 0);
        !           335: 
        !           336:       if (! (to == value ||
        !           337:             (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
        !           338:        return 0;
        !           339: 
        !           340:       r = XEXP (r, 1);
        !           341: 
        !           342:       switch (GET_CODE (r))
        !           343:        {
        !           344:        case CONST_INT:
        !           345:          t = build_int_2 (XEXP (r, 0), 0);
        !           346:          break;
        !           347:        default:
        !           348:          return 0;
        !           349:        }
        !           350:     }
        !           351: 
        !           352:   return t; 
        !           353: }
        !           354: 
        !           355: int
        !           356: extract_init (decl, init)
        !           357:      tree decl, init;
        !           358: {
        !           359:   return 0;
        !           360: 
        !           361:   if (IS_AGGR_TYPE (TREE_TYPE (decl))
        !           362:       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
        !           363:     init = extract_aggr_init (decl, init);
        !           364:   else
        !           365:     init = extract_scalar_init (decl, init);
        !           366: 
        !           367:   if (init == NULL_TREE)
        !           368:     return 0;
        !           369: 
        !           370:   DECL_INITIAL (decl) = init;
        !           371:   return 1;
        !           372: }

unix.superglobalmegacorp.com

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