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

1.1       root        1: /* Convert language-specific tree expression to rtl instructions,
                      2:    for GNU compiler.
                      3:    Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
                      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 "rtl.h"
                     24: #include "tree.h"
                     25: #include "flags.h"
                     26: #include "expr.h"
                     27: #include "cp-tree.h"
                     28: 
                     29: #undef NULL
                     30: #define NULL 0
                     31: 
                     32: /* Hook used by expand_expr to expand language-specific tree codes.  */
                     33: 
                     34: rtx
                     35: cplus_expand_expr (exp, target, tmode, modifier)
                     36:      tree exp;
                     37:      rtx target;
                     38:      enum machine_mode tmode;
                     39:      enum expand_modifier modifier;
                     40: {
                     41:   tree type = TREE_TYPE (exp);
                     42:   register enum machine_mode mode = TYPE_MODE (type);
                     43:   register enum tree_code code = TREE_CODE (exp);
                     44:   rtx original_target = target;
                     45:   int ignore = target == const0_rtx;
                     46: 
                     47:   if (ignore)
                     48:     target = 0, original_target = 0;
                     49: 
                     50:   /* No sense saving up arithmetic to be done
                     51:      if it's all in the wrong mode to form part of an address.
                     52:      And force_operand won't know whether to sign-extend or zero-extend.  */
                     53: 
                     54:   if (mode != Pmode && modifier == EXPAND_SUM)
                     55:     modifier = EXPAND_NORMAL;
                     56: 
                     57:   switch (code)
                     58:     {
                     59:     case NEW_EXPR:
                     60:       {
                     61:        /* Something needs to be initialized, but we didn't know
                     62:           where that thing was when building the tree.  For example,
                     63:           it could be the return value of a function, or a parameter
                     64:           to a function which lays down in the stack, or a temporary
                     65:           variable which must be passed by reference.
                     66: 
                     67:           Cleanups are handled in a language-specific way: they
                     68:           might be run by the called function (true in GNU C++
                     69:           for parameters with cleanups), or they might be
                     70:           run by the caller, after the call (true in GNU C++
                     71:           for other cleanup needs).  */
                     72: 
                     73:        tree func = TREE_OPERAND (exp, 0);
                     74:        tree args = TREE_OPERAND (exp, 1);
                     75:        tree type = TREE_TYPE (exp), slot;
                     76:        tree fn_type = TREE_TYPE (TREE_TYPE (func));
                     77:        tree return_type = TREE_TYPE (fn_type);
                     78:        tree call_exp;
                     79:        rtx call_target, return_target;
                     80:        int pcc_struct_return = 0;
                     81: 
                     82:        /* The expression `init' wants to initialize what
                     83:           `target' represents.  SLOT holds the slot for TARGET.  */
                     84:        slot = TREE_OPERAND (exp, 2);
                     85: 
                     86:        if (target == 0)
                     87:          {
                     88:            /* Should always be called with a target in BLKmode case.  */
                     89:            my_friendly_assert (mode != BLKmode, 205);
                     90:            my_friendly_assert (DECL_RTL (slot) != 0, 206);
                     91: 
                     92:            target = gen_reg_rtx (mode);
                     93:          }
                     94: 
                     95:        /* The target the initializer will initialize (CALL_TARGET)
                     96:           must now be directed to initialize the target we are
                     97:           supposed to initialize (TARGET).  The semantics for
                     98:           choosing what CALL_TARGET is is language-specific,
                     99:           as is building the call which will perform the
                    100:           initialization.  It is left here to show the choices that
                    101:           exist for C++.  */
                    102:           
                    103:        if (TREE_CODE (func) == ADDR_EXPR
                    104:            && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
                    105:            && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
                    106:          {
                    107:            type = TYPE_POINTER_TO (type);
                    108:            /* Don't clobber a value that might be part of a default
                    109:               parameter value.  */
                    110:            if (TREE_PERMANENT (args))
                    111:              args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
                    112:                                TREE_CHAIN (args));
                    113:            else
                    114:              TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
                    115:            call_target = 0;
                    116:          }
                    117:        else if (TREE_CODE (return_type) == REFERENCE_TYPE)
                    118:          {
                    119:            type = return_type;
                    120:            call_target = 0;
                    121:          }
                    122:        else
                    123:          {
                    124: #ifdef PCC_STATIC_STRUCT_RETURN
                    125:            pcc_struct_return = 1;
                    126:            call_target = 0;
                    127: #else
                    128:            call_target = target;
                    129: #endif
                    130:          }
                    131:        if (call_target)
                    132:          {
                    133:            preserve_temp_slots (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:        preserve_temp_slots (DECL_RTL (slot));
                    143:        call_exp = build (CALL_EXPR, type, func, args, 0);
                    144:        TREE_SIDE_EFFECTS (call_exp) = 1;
                    145:        return_target = expand_expr (call_exp, call_target, mode, 0);
                    146:        free_temp_slots ();
                    147:        if (call_target == 0)
                    148:          {
                    149:            if (pcc_struct_return)
                    150:              {
                    151:                extern int flag_access_control;
                    152:                int old_ac = flag_access_control;
                    153: 
                    154:                tree init = build (RTL_EXPR, type, 0, return_target);
                    155:                TREE_ADDRESSABLE (init) = 1;
                    156: 
                    157:                flag_access_control = 0;
                    158:                expand_aggr_init (slot, init, 0);
                    159:                flag_access_control = old_ac;
                    160: 
                    161:                if (TYPE_NEEDS_DESTRUCTOR (type))
                    162:                  {
                    163:                    init = build (RTL_EXPR, build_reference_type (type), 0,
                    164:                                  XEXP (return_target, 0));
                    165:                    init = maybe_build_cleanup (convert_from_reference (init));
                    166:                    if (init != NULL_TREE)
                    167:                      expand_expr (init, 0, 0, 0);
                    168:                  }
                    169:                call_target = return_target = DECL_RTL (slot);
                    170:              }
                    171:            else
                    172:              call_target = return_target;
                    173:          }
                    174: 
                    175:        if (call_target != return_target)
                    176:          {
                    177:            my_friendly_assert (! TYPE_NEEDS_CONSTRUCTING (type), 317);
                    178:            if (GET_MODE (return_target) == BLKmode)
                    179:              emit_block_move (call_target, return_target, expr_size (exp),
                    180:                               TYPE_ALIGN (type) / BITS_PER_UNIT);
                    181:            else
                    182:              emit_move_insn (call_target, return_target);
                    183:          }
                    184: 
                    185:        if (TREE_CODE (return_type) == REFERENCE_TYPE)
                    186:          {
                    187:            tree init;
                    188: 
                    189:            if (GET_CODE (call_target) == REG
                    190:                && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
                    191:              my_friendly_abort (39);
                    192: 
                    193:            type = TREE_TYPE (exp);
                    194: 
                    195:            init = build (RTL_EXPR, return_type, 0, call_target);
                    196:            /* We got back a reference to the type we want.  Now initialize
                    197:               target with that.  */
                    198:            expand_aggr_init (slot, init, 0);
                    199:          }
                    200: 
                    201:        if (DECL_RTL (slot) != target)
                    202:          emit_move_insn (DECL_RTL (slot), target);
                    203:        return DECL_RTL (slot);
                    204:       }
                    205: 
                    206:     case OFFSET_REF:
                    207:       {
                    208: #if 1
                    209:        return expand_expr (default_conversion (resolve_offset_ref (exp)),
                    210:                            target, tmode, EXPAND_NORMAL);
                    211: #else
                    212:        /* This is old crusty code, and does not handle all that the
                    213:           resolve_offset_ref function does.  (mrs) */
                    214:        tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
                    215:        tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
                    216:        return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
                    217:                            target, tmode, EXPAND_NORMAL);
                    218: #endif
                    219:       }
                    220: 
                    221:     case THUNK_DECL:
                    222:       return DECL_RTL (exp);
                    223: 
                    224:     case THROW_EXPR:
                    225:       expand_throw (TREE_OPERAND (exp, 0));
                    226:       return NULL;
                    227: 
                    228:     default:
                    229:       break;
                    230:     }
                    231:   my_friendly_abort (40);
                    232:   /* NOTREACHED */
                    233:   return NULL;
                    234: }
                    235: 
                    236: void
                    237: init_cplus_expand ()
                    238: {
                    239:   lang_expand_expr = cplus_expand_expr;
                    240: }
                    241: 
                    242: /* If DECL had its rtl moved from where callers expect it
                    243:    to be, fix it up.  RESULT is the nominal rtl for the RESULT_DECL,
                    244:    which may be a pseudo instead of a hard register.  */
                    245: 
                    246: void
                    247: fixup_result_decl (decl, result)
                    248:      tree decl;
                    249:      rtx result;
                    250: {
                    251:   if (REG_P (result))
                    252:     {
                    253:       if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
                    254:        {
                    255:          rtx real_decl_result;
                    256: 
                    257: #ifdef FUNCTION_OUTGOING_VALUE
                    258:          real_decl_result
                    259:            = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
                    260: #else
                    261:          real_decl_result
                    262:            = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
                    263: #endif
                    264:          REG_FUNCTION_VALUE_P (real_decl_result) = 1;
                    265:          result = real_decl_result;
                    266:        }
                    267:       emit_move_insn (result, DECL_RTL (decl));
                    268:       emit_insn (gen_rtx (USE, VOIDmode, result));
                    269:     }
                    270: }
                    271: 
                    272: /* Return nonzero iff DECL is memory-based.  The DECL_RTL of
                    273:    certain const variables might be a CONST_INT, or a REG
                    274:    in some cases.  We cannot use `memory_operand' as a test
                    275:    here because on most RISC machines, a variable's address
                    276:    is not, by itself, a legitimate address.  */
                    277: int
                    278: decl_in_memory_p (decl)
                    279:      tree decl;
                    280: {
                    281:   return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
                    282: }

unix.superglobalmegacorp.com

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