Annotation of GNUtools/cc/cp-expr.c, revision 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:                tree init = build (RTL_EXPR, type, 0, return_target);
        !           152:                TREE_ADDRESSABLE (init) = 1;
        !           153:                expand_aggr_init (slot, init, 0);
        !           154:                if (TYPE_NEEDS_DESTRUCTOR (type))
        !           155:                  {
        !           156:                    init = build (RTL_EXPR, build_reference_type (type), 0,
        !           157:                                  XEXP (return_target, 0));
        !           158:                    init = maybe_build_cleanup (convert_from_reference (init));
        !           159:                    if (init != NULL_TREE)
        !           160:                      expand_expr (init, 0, 0, 0);
        !           161:                  }
        !           162:                call_target = return_target = DECL_RTL (slot);
        !           163:              }
        !           164:            else
        !           165:              call_target = return_target;
        !           166:          }
        !           167: 
        !           168:        if (call_target != return_target)
        !           169:          {
        !           170:            my_friendly_assert (! TYPE_NEEDS_CONSTRUCTING (type), 317);
        !           171:            if (GET_MODE (return_target) == BLKmode)
        !           172:              emit_block_move (call_target, return_target, expr_size (exp),
        !           173:                               TYPE_ALIGN (type) / BITS_PER_UNIT);
        !           174:            else
        !           175:              emit_move_insn (call_target, return_target);
        !           176:          }
        !           177: 
        !           178:        if (TREE_CODE (return_type) == REFERENCE_TYPE)
        !           179:          {
        !           180:            tree init;
        !           181: 
        !           182:            if (GET_CODE (call_target) == REG
        !           183:                && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
        !           184:              my_friendly_abort (39);
        !           185: 
        !           186:            type = TREE_TYPE (exp);
        !           187: 
        !           188:            init = build (RTL_EXPR, return_type, 0, call_target);
        !           189:            /* We got back a reference to the type we want.  Now initialize
        !           190:               target with that.  */
        !           191:            expand_aggr_init (slot, init, 0);
        !           192:          }
        !           193: 
        !           194:        if (DECL_RTL (slot) != target)
        !           195:          emit_move_insn (DECL_RTL (slot), target);
        !           196:        return DECL_RTL (slot);
        !           197:       }
        !           198: 
        !           199:     case OFFSET_REF:
        !           200:       {
        !           201: #if 1
        !           202:        return expand_expr (default_conversion (resolve_offset_ref (exp)),
        !           203:                            target, tmode, EXPAND_NORMAL);
        !           204: #else
        !           205:        /* This is old crusty code, and does not handle all that the
        !           206:           resolve_offset_ref function does.  (mrs) */
        !           207:        tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
        !           208:        tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
        !           209:        return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
        !           210:                            target, tmode, EXPAND_NORMAL);
        !           211: #endif
        !           212:       }
        !           213: 
        !           214:     default:
        !           215:       break;
        !           216:     }
        !           217:   my_friendly_abort (40);
        !           218:   /* NOTREACHED */
        !           219:   return NULL;
        !           220: }
        !           221: 
        !           222: void
        !           223: init_cplus_expand ()
        !           224: {
        !           225:   lang_expand_expr = cplus_expand_expr;
        !           226: }
        !           227: 
        !           228: /* If DECL had its rtl moved from where callers expect it
        !           229:    to be, fix it up.  RESULT is the nominal rtl for the RESULT_DECL,
        !           230:    which may be a pseudo instead of a hard register.  */
        !           231: 
        !           232: void
        !           233: fixup_result_decl (decl, result)
        !           234:      tree decl;
        !           235:      rtx result;
        !           236: {
        !           237:   if (REG_P (result))
        !           238:     {
        !           239:       if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
        !           240:        {
        !           241:          rtx real_decl_result;
        !           242: 
        !           243: #ifdef FUNCTION_OUTGOING_VALUE
        !           244:          real_decl_result
        !           245:            = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
        !           246: #else
        !           247:          real_decl_result
        !           248:            = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
        !           249: #endif
        !           250:          REG_FUNCTION_VALUE_P (real_decl_result) = 1;
        !           251:          result = real_decl_result;
        !           252:        }
        !           253:       emit_move_insn (result, DECL_RTL (decl));
        !           254:       emit_insn (gen_rtx (USE, VOIDmode, result));
        !           255:     }
        !           256: }
        !           257: 
        !           258: /* Return nonzero iff DECL is memory-based.  The DECL_RTL of
        !           259:    certain const variables might be a CONST_INT, or a REG
        !           260:    in some cases.  We cannot use `memory_operand' as a test
        !           261:    here because on most RISC machines, a variable's address
        !           262:    is not, by itself, a legitimate address.  */
        !           263: int
        !           264: decl_in_memory_p (decl)
        !           265:      tree decl;
        !           266: {
        !           267:   return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
        !           268: }

unix.superglobalmegacorp.com

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