Annotation of gcc/expr.c, revision 1.1.1.7

1.1       root        1: /* Convert tree expression to rtl instructions, for GNU compiler.
1.1.1.7 ! root        2:    Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: 
                     21: #include "config.h"
1.1.1.6   root       22: #include "machmode.h"
1.1       root       23: #include "rtl.h"
                     24: #include "tree.h"
1.1.1.6   root       25: #include "obstack.h"
1.1       root       26: #include "flags.h"
1.1.1.7 ! root       27: #include "regs.h"
1.1       root       28: #include "function.h"
                     29: #include "insn-flags.h"
                     30: #include "insn-codes.h"
                     31: #include "expr.h"
                     32: #include "insn-config.h"
                     33: #include "recog.h"
                     34: #include "output.h"
                     35: #include "typeclass.h"
                     36: 
1.1.1.6   root       37: #include "bytecode.h"
                     38: #include "bc-opcode.h"
                     39: #include "bc-typecd.h"
                     40: #include "bc-optab.h"
                     41: #include "bc-emit.h"
                     42: 
                     43: 
1.1       root       44: #define CEIL(x,y) (((x) + (y) - 1) / (y))
                     45: 
                     46: /* Decide whether a function's arguments should be processed
1.1.1.5   root       47:    from first to last or from last to first.
                     48: 
                     49:    They should if the stack and args grow in opposite directions, but
                     50:    only if we have push insns.  */
1.1       root       51: 
                     52: #ifdef PUSH_ROUNDING
1.1.1.5   root       53: 
1.1.1.6   root       54: #if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
1.1       root       55: #define PUSH_ARGS_REVERSED     /* If it's last to first */
                     56: #endif
1.1.1.5   root       57: 
1.1       root       58: #endif
                     59: 
                     60: #ifndef STACK_PUSH_CODE
                     61: #ifdef STACK_GROWS_DOWNWARD
                     62: #define STACK_PUSH_CODE PRE_DEC
                     63: #else
                     64: #define STACK_PUSH_CODE PRE_INC
                     65: #endif
                     66: #endif
                     67: 
                     68: /* Like STACK_BOUNDARY but in units of bytes, not bits.  */
                     69: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
                     70: 
                     71: /* If this is nonzero, we do not bother generating VOLATILE
                     72:    around volatile memory references, and we are willing to
                     73:    output indirect addresses.  If cse is to follow, we reject
                     74:    indirect addresses so a useful potential cse is generated;
                     75:    if it is used only once, instruction combination will produce
                     76:    the same indirect address eventually.  */
                     77: int cse_not_expected;
                     78: 
                     79: /* Nonzero to generate code for all the subroutines within an
                     80:    expression before generating the upper levels of the expression.
                     81:    Nowadays this is never zero.  */
                     82: int do_preexpand_calls = 1;
                     83: 
                     84: /* Number of units that we should eventually pop off the stack.
                     85:    These are the arguments to function calls that have already returned.  */
                     86: int pending_stack_adjust;
                     87: 
                     88: /* Nonzero means stack pops must not be deferred, and deferred stack
                     89:    pops must not be output.  It is nonzero inside a function call,
                     90:    inside a conditional expression, inside a statement expression,
                     91:    and in other cases as well.  */
                     92: int inhibit_defer_pop;
                     93: 
                     94: /* A list of all cleanups which belong to the arguments of
                     95:    function calls being expanded by expand_call.  */
                     96: tree cleanups_this_call;
                     97: 
1.1.1.7 ! root       98: /* When temporaries are created by TARGET_EXPRs, they are created at
        !            99:    this level of temp_slot_level, so that they can remain allocated
        !           100:    until no longer needed.  CLEANUP_POINT_EXPRs define the lifetime
        !           101:    of TARGET_EXPRs.  */
        !           102: int target_temp_slot_level;
        !           103: 
1.1       root      104: /* Nonzero means __builtin_saveregs has already been done in this function.
                    105:    The value is the pseudoreg containing the value __builtin_saveregs
                    106:    returned.  */
                    107: static rtx saveregs_value;
                    108: 
1.1.1.5   root      109: /* Similarly for __builtin_apply_args.  */
                    110: static rtx apply_args_value;
                    111: 
                    112: /* This structure is used by move_by_pieces to describe the move to
                    113:    be performed.  */
                    114: 
                    115: struct move_by_pieces
                    116: {
                    117:   rtx to;
                    118:   rtx to_addr;
                    119:   int autinc_to;
                    120:   int explicit_inc_to;
                    121:   rtx from;
                    122:   rtx from_addr;
                    123:   int autinc_from;
                    124:   int explicit_inc_from;
                    125:   int len;
                    126:   int offset;
                    127:   int reverse;
                    128: };
                    129: 
1.1.1.6   root      130: /* Used to generate bytecodes: keep track of size of local variables,
                    131:    as well as depth of arithmetic stack. (Notice that variables are
                    132:    stored on the machine's stack, not the arithmetic stack.) */
                    133: 
1.1.1.7 ! root      134: extern int local_vars_size;
1.1.1.6   root      135: extern int stack_depth;
                    136: extern int max_stack_depth;
                    137: extern struct obstack permanent_obstack;
                    138: 
                    139: 
1.1.1.5   root      140: static rtx enqueue_insn                PROTO((rtx, rtx));
                    141: static int queued_subexp_p     PROTO((rtx));
                    142: static void init_queue         PROTO((void));
                    143: static void move_by_pieces     PROTO((rtx, rtx, int, int));
                    144: static int move_by_pieces_ninsns PROTO((unsigned int, int));
                    145: static void move_by_pieces_1   PROTO((rtx (*) (), enum machine_mode,
                    146:                                       struct move_by_pieces *));
                    147: static void store_constructor  PROTO((tree, rtx));
                    148: static rtx store_field         PROTO((rtx, int, int, enum machine_mode, tree,
                    149:                                       enum machine_mode, int, int, int));
1.1.1.7 ! root      150: static int get_inner_unaligned_p PROTO((tree));
1.1.1.5   root      151: static tree save_noncopied_parts PROTO((tree, tree));
                    152: static tree init_noncopied_parts PROTO((tree, tree));
                    153: static int safe_from_p         PROTO((rtx, tree));
                    154: static int fixed_type_p                PROTO((tree));
                    155: static int get_pointer_alignment PROTO((tree, unsigned));
                    156: static tree string_constant    PROTO((tree, tree *));
                    157: static tree c_strlen           PROTO((tree));
1.1.1.7 ! root      158: static rtx expand_builtin      PROTO((tree, rtx, rtx,
        !           159:                                       enum machine_mode, int));
1.1.1.5   root      160: static int apply_args_size     PROTO((void));
                    161: static int apply_result_size   PROTO((void));
                    162: static rtx result_vector       PROTO((int, rtx));
                    163: static rtx expand_builtin_apply_args PROTO((void));
                    164: static rtx expand_builtin_apply        PROTO((rtx, rtx, rtx));
                    165: static void expand_builtin_return PROTO((rtx));
                    166: static rtx expand_increment    PROTO((tree, int));
1.1.1.6   root      167: rtx bc_expand_increment                PROTO((struct increment_operator *, tree));
                    168: tree bc_runtime_type_code      PROTO((tree));
                    169: rtx bc_allocate_local          PROTO((int, int));
                    170: void bc_store_memory           PROTO((tree, tree));
                    171: tree bc_expand_component_address PROTO((tree));
                    172: tree bc_expand_address                 PROTO((tree));
                    173: void bc_expand_constructor     PROTO((tree));
                    174: void bc_adjust_stack           PROTO((int));
                    175: tree bc_canonicalize_array_ref PROTO((tree));
                    176: void bc_load_memory            PROTO((tree, tree));
                    177: void bc_load_externaddr                PROTO((rtx));
                    178: void bc_load_externaddr_id     PROTO((tree, int));
                    179: void bc_load_localaddr         PROTO((rtx));
                    180: void bc_load_parmaddr          PROTO((rtx));
1.1.1.5   root      181: static void preexpand_calls    PROTO((tree));
                    182: static void do_jump_by_parts_greater PROTO((tree, int, rtx, rtx));
1.1.1.7 ! root      183: void do_jump_by_parts_greater_rtx PROTO((enum machine_mode, int, rtx, rtx, rtx, rtx));
1.1.1.5   root      184: static void do_jump_by_parts_equality PROTO((tree, rtx, rtx));
                    185: static void do_jump_by_parts_equality_rtx PROTO((rtx, rtx, rtx));
                    186: static void do_jump_for_compare        PROTO((rtx, rtx, rtx));
                    187: static rtx compare             PROTO((tree, enum rtx_code, enum rtx_code));
                    188: static rtx do_store_flag       PROTO((tree, rtx, enum machine_mode, int));
1.1.1.7 ! root      189: static tree defer_cleanups_to  PROTO((tree));
        !           190: extern void (*interim_eh_hook) PROTO((tree));
1.1       root      191: 
1.1.1.4   root      192: /* Record for each mode whether we can move a register directly to or
                    193:    from an object of that mode in memory.  If we can't, we won't try
                    194:    to use that mode directly when accessing a field of that mode.  */
                    195: 
                    196: static char direct_load[NUM_MACHINE_MODES];
                    197: static char direct_store[NUM_MACHINE_MODES];
                    198: 
1.1       root      199: /* MOVE_RATIO is the number of move instructions that is better than
                    200:    a block move.  */
                    201: 
                    202: #ifndef MOVE_RATIO
1.1.1.4   root      203: #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
1.1       root      204: #define MOVE_RATIO 2
                    205: #else
                    206: /* A value of around 6 would minimize code size; infinity would minimize
                    207:    execution time.  */
                    208: #define MOVE_RATIO 15
                    209: #endif
                    210: #endif
1.1.1.2   root      211: 
1.1.1.4   root      212: /* This array records the insn_code of insns to perform block moves.  */
1.1.1.5   root      213: enum insn_code movstr_optab[NUM_MACHINE_MODES];
1.1.1.4   root      214: 
1.1.1.2   root      215: /* SLOW_UNALIGNED_ACCESS is non-zero if unaligned accesses are very slow. */
                    216: 
                    217: #ifndef SLOW_UNALIGNED_ACCESS
                    218: #define SLOW_UNALIGNED_ACCESS 0
                    219: #endif
1.1.1.5   root      220: 
                    221: /* Register mappings for target machines without register windows.  */
                    222: #ifndef INCOMING_REGNO
                    223: #define INCOMING_REGNO(OUT) (OUT)
                    224: #endif
                    225: #ifndef OUTGOING_REGNO
                    226: #define OUTGOING_REGNO(IN) (IN)
                    227: #endif
1.1       root      228: 
1.1.1.6   root      229: /* Maps used to convert modes to const, load, and store bytecodes. */
                    230: enum bytecode_opcode mode_to_const_map[MAX_MACHINE_MODE];
                    231: enum bytecode_opcode mode_to_load_map[MAX_MACHINE_MODE];
                    232: enum bytecode_opcode mode_to_store_map[MAX_MACHINE_MODE];
                    233: 
                    234: /* Initialize maps used to convert modes to const, load, and store
                    235:    bytecodes. */
                    236: void
                    237: bc_init_mode_to_opcode_maps ()
                    238: {
                    239:   int mode;
                    240: 
                    241:   for (mode = 0; mode < (int) MAX_MACHINE_MODE; mode++)
                    242:     mode_to_const_map[mode] =
                    243:       mode_to_load_map[mode] =
                    244:        mode_to_store_map[mode] = neverneverland;
                    245:       
                    246: #define DEF_MODEMAP(SYM, CODE, UCODE, CONST, LOAD, STORE) \
                    247:   mode_to_const_map[(int) SYM] = CONST; \
                    248:   mode_to_load_map[(int) SYM] = LOAD; \
                    249:   mode_to_store_map[(int) SYM] = STORE;
                    250: 
                    251: #include "modemap.def"
                    252: #undef DEF_MODEMAP
                    253: }
                    254: 
1.1.1.4   root      255: /* This is run once per compilation to set up which modes can be used
                    256:    directly in memory and to initialize the block move optab.  */
                    257: 
                    258: void
                    259: init_expr_once ()
                    260: {
                    261:   rtx insn, pat;
                    262:   enum machine_mode mode;
                    263:   /* Try indexing by frame ptr and try by stack ptr.
                    264:      It is known that on the Convex the stack ptr isn't a valid index.
                    265:      With luck, one or the other is valid on any machine.  */
                    266:   rtx mem = gen_rtx (MEM, VOIDmode, stack_pointer_rtx);
                    267:   rtx mem1 = gen_rtx (MEM, VOIDmode, frame_pointer_rtx);
                    268: 
                    269:   start_sequence ();
                    270:   insn = emit_insn (gen_rtx (SET, 0, 0));
                    271:   pat = PATTERN (insn);
                    272: 
                    273:   for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
                    274:        mode = (enum machine_mode) ((int) mode + 1))
                    275:     {
                    276:       int regno;
                    277:       rtx reg;
                    278:       int num_clobbers;
                    279: 
                    280:       direct_load[(int) mode] = direct_store[(int) mode] = 0;
                    281:       PUT_MODE (mem, mode);
                    282:       PUT_MODE (mem1, mode);
                    283: 
                    284:       /* See if there is some register that can be used in this mode and
                    285:         directly loaded or stored from memory.  */
                    286: 
                    287:       if (mode != VOIDmode && mode != BLKmode)
                    288:        for (regno = 0; regno < FIRST_PSEUDO_REGISTER
                    289:             && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0);
                    290:             regno++)
                    291:          {
                    292:            if (! HARD_REGNO_MODE_OK (regno, mode))
                    293:              continue;
                    294: 
                    295:            reg = gen_rtx (REG, mode, regno);
                    296: 
                    297:            SET_SRC (pat) = mem;
                    298:            SET_DEST (pat) = reg;
                    299:            if (recog (pat, insn, &num_clobbers) >= 0)
                    300:              direct_load[(int) mode] = 1;
                    301: 
                    302:            SET_SRC (pat) = mem1;
                    303:            SET_DEST (pat) = reg;
                    304:            if (recog (pat, insn, &num_clobbers) >= 0)
                    305:              direct_load[(int) mode] = 1;
                    306: 
                    307:            SET_SRC (pat) = reg;
                    308:            SET_DEST (pat) = mem;
                    309:            if (recog (pat, insn, &num_clobbers) >= 0)
                    310:              direct_store[(int) mode] = 1;
                    311: 
                    312:            SET_SRC (pat) = reg;
                    313:            SET_DEST (pat) = mem1;
                    314:            if (recog (pat, insn, &num_clobbers) >= 0)
                    315:              direct_store[(int) mode] = 1;
                    316:          }
                    317:     }
                    318: 
                    319:   end_sequence ();
                    320: }
                    321:       
1.1       root      322: /* This is run at the start of compiling a function.  */
                    323: 
                    324: void
                    325: init_expr ()
                    326: {
                    327:   init_queue ();
                    328: 
                    329:   pending_stack_adjust = 0;
                    330:   inhibit_defer_pop = 0;
                    331:   cleanups_this_call = 0;
                    332:   saveregs_value = 0;
1.1.1.5   root      333:   apply_args_value = 0;
1.1.1.2   root      334:   forced_labels = 0;
1.1       root      335: }
                    336: 
                    337: /* Save all variables describing the current status into the structure *P.
                    338:    This is used before starting a nested function.  */
                    339: 
                    340: void
                    341: save_expr_status (p)
                    342:      struct function *p;
                    343: {
                    344:   /* Instead of saving the postincrement queue, empty it.  */
                    345:   emit_queue ();
                    346: 
                    347:   p->pending_stack_adjust = pending_stack_adjust;
                    348:   p->inhibit_defer_pop = inhibit_defer_pop;
                    349:   p->cleanups_this_call = cleanups_this_call;
                    350:   p->saveregs_value = saveregs_value;
1.1.1.5   root      351:   p->apply_args_value = apply_args_value;
1.1.1.2   root      352:   p->forced_labels = forced_labels;
1.1       root      353: 
                    354:   pending_stack_adjust = 0;
                    355:   inhibit_defer_pop = 0;
                    356:   cleanups_this_call = 0;
                    357:   saveregs_value = 0;
1.1.1.5   root      358:   apply_args_value = 0;
1.1.1.2   root      359:   forced_labels = 0;
1.1       root      360: }
                    361: 
                    362: /* Restore all variables describing the current status from the structure *P.
                    363:    This is used after a nested function.  */
                    364: 
                    365: void
                    366: restore_expr_status (p)
                    367:      struct function *p;
                    368: {
                    369:   pending_stack_adjust = p->pending_stack_adjust;
                    370:   inhibit_defer_pop = p->inhibit_defer_pop;
                    371:   cleanups_this_call = p->cleanups_this_call;
                    372:   saveregs_value = p->saveregs_value;
1.1.1.5   root      373:   apply_args_value = p->apply_args_value;
1.1.1.2   root      374:   forced_labels = p->forced_labels;
1.1       root      375: }
                    376: 
                    377: /* Manage the queue of increment instructions to be output
                    378:    for POSTINCREMENT_EXPR expressions, etc.  */
                    379: 
                    380: static rtx pending_chain;
                    381: 
                    382: /* Queue up to increment (or change) VAR later.  BODY says how:
                    383:    BODY should be the same thing you would pass to emit_insn
                    384:    to increment right away.  It will go to emit_insn later on.
                    385: 
                    386:    The value is a QUEUED expression to be used in place of VAR
                    387:    where you want to guarantee the pre-incrementation value of VAR.  */
                    388: 
                    389: static rtx
                    390: enqueue_insn (var, body)
                    391:      rtx var, body;
                    392: {
                    393:   pending_chain = gen_rtx (QUEUED, GET_MODE (var),
1.1.1.4   root      394:                           var, NULL_RTX, NULL_RTX, body, pending_chain);
1.1       root      395:   return pending_chain;
                    396: }
                    397: 
                    398: /* Use protect_from_queue to convert a QUEUED expression
                    399:    into something that you can put immediately into an instruction.
                    400:    If the queued incrementation has not happened yet,
                    401:    protect_from_queue returns the variable itself.
                    402:    If the incrementation has happened, protect_from_queue returns a temp
                    403:    that contains a copy of the old value of the variable.
                    404: 
                    405:    Any time an rtx which might possibly be a QUEUED is to be put
                    406:    into an instruction, it must be passed through protect_from_queue first.
                    407:    QUEUED expressions are not meaningful in instructions.
                    408: 
                    409:    Do not pass a value through protect_from_queue and then hold
                    410:    on to it for a while before putting it in an instruction!
                    411:    If the queue is flushed in between, incorrect code will result.  */
                    412: 
                    413: rtx
                    414: protect_from_queue (x, modify)
                    415:      register rtx x;
                    416:      int modify;
                    417: {
                    418:   register RTX_CODE code = GET_CODE (x);
                    419: 
                    420: #if 0  /* A QUEUED can hang around after the queue is forced out.  */
                    421:   /* Shortcut for most common case.  */
                    422:   if (pending_chain == 0)
                    423:     return x;
                    424: #endif
                    425: 
                    426:   if (code != QUEUED)
                    427:     {
1.1.1.6   root      428:       /* A special hack for read access to (MEM (QUEUED ...)) to facilitate
                    429:         use of autoincrement.  Make a copy of the contents of the memory
                    430:         location rather than a copy of the address, but not if the value is
                    431:         of mode BLKmode.  Don't modify X in place since it might be
                    432:         shared.  */
1.1       root      433:       if (code == MEM && GET_MODE (x) != BLKmode
                    434:          && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
                    435:        {
                    436:          register rtx y = XEXP (x, 0);
1.1.1.6   root      437:          register rtx new = gen_rtx (MEM, GET_MODE (x), QUEUED_VAR (y));
                    438: 
                    439:          MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
                    440:          RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
                    441:          MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
                    442: 
1.1       root      443:          if (QUEUED_INSN (y))
                    444:            {
1.1.1.6   root      445:              register rtx temp = gen_reg_rtx (GET_MODE (new));
                    446:              emit_insn_before (gen_move_insn (temp, new),
1.1       root      447:                                QUEUED_INSN (y));
                    448:              return temp;
                    449:            }
1.1.1.6   root      450:          return new;
1.1       root      451:        }
                    452:       /* Otherwise, recursively protect the subexpressions of all
                    453:         the kinds of rtx's that can contain a QUEUED.  */
                    454:       if (code == MEM)
1.1.1.6   root      455:        {
                    456:          rtx tem = protect_from_queue (XEXP (x, 0), 0);
                    457:          if (tem != XEXP (x, 0))
                    458:            {
                    459:              x = copy_rtx (x);
                    460:              XEXP (x, 0) = tem;
                    461:            }
                    462:        }
1.1       root      463:       else if (code == PLUS || code == MULT)
                    464:        {
1.1.1.6   root      465:          rtx new0 = protect_from_queue (XEXP (x, 0), 0);
                    466:          rtx new1 = protect_from_queue (XEXP (x, 1), 0);
                    467:          if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
                    468:            {
                    469:              x = copy_rtx (x);
                    470:              XEXP (x, 0) = new0;
                    471:              XEXP (x, 1) = new1;
                    472:            }
1.1       root      473:        }
                    474:       return x;
                    475:     }
                    476:   /* If the increment has not happened, use the variable itself.  */
                    477:   if (QUEUED_INSN (x) == 0)
                    478:     return QUEUED_VAR (x);
                    479:   /* If the increment has happened and a pre-increment copy exists,
                    480:      use that copy.  */
                    481:   if (QUEUED_COPY (x) != 0)
                    482:     return QUEUED_COPY (x);
                    483:   /* The increment has happened but we haven't set up a pre-increment copy.
                    484:      Set one up now, and use it.  */
                    485:   QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
                    486:   emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
                    487:                    QUEUED_INSN (x));
                    488:   return QUEUED_COPY (x);
                    489: }
                    490: 
                    491: /* Return nonzero if X contains a QUEUED expression:
                    492:    if it contains anything that will be altered by a queued increment.
                    493:    We handle only combinations of MEM, PLUS, MINUS and MULT operators
                    494:    since memory addresses generally contain only those.  */
                    495: 
                    496: static int
                    497: queued_subexp_p (x)
                    498:      rtx x;
                    499: {
                    500:   register enum rtx_code code = GET_CODE (x);
                    501:   switch (code)
                    502:     {
                    503:     case QUEUED:
                    504:       return 1;
                    505:     case MEM:
                    506:       return queued_subexp_p (XEXP (x, 0));
                    507:     case MULT:
                    508:     case PLUS:
                    509:     case MINUS:
                    510:       return queued_subexp_p (XEXP (x, 0))
                    511:        || queued_subexp_p (XEXP (x, 1));
                    512:     }
                    513:   return 0;
                    514: }
                    515: 
                    516: /* Perform all the pending incrementations.  */
                    517: 
                    518: void
                    519: emit_queue ()
                    520: {
                    521:   register rtx p;
                    522:   while (p = pending_chain)
                    523:     {
                    524:       QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p));
                    525:       pending_chain = QUEUED_NEXT (p);
                    526:     }
                    527: }
                    528: 
                    529: static void
                    530: init_queue ()
                    531: {
                    532:   if (pending_chain)
                    533:     abort ();
                    534: }
                    535: 
                    536: /* Copy data from FROM to TO, where the machine modes are not the same.
                    537:    Both modes may be integer, or both may be floating.
                    538:    UNSIGNEDP should be nonzero if FROM is an unsigned type.
                    539:    This causes zero-extension instead of sign-extension.  */
                    540: 
                    541: void
                    542: convert_move (to, from, unsignedp)
                    543:      register rtx to, from;
                    544:      int unsignedp;
                    545: {
                    546:   enum machine_mode to_mode = GET_MODE (to);
                    547:   enum machine_mode from_mode = GET_MODE (from);
                    548:   int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT;
                    549:   int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT;
                    550:   enum insn_code code;
                    551:   rtx libcall;
                    552: 
                    553:   /* rtx code for making an equivalent value.  */
                    554:   enum rtx_code equiv_code = (unsignedp ? ZERO_EXTEND : SIGN_EXTEND);
                    555: 
                    556:   to = protect_from_queue (to, 1);
                    557:   from = protect_from_queue (from, 0);
                    558: 
                    559:   if (to_real != from_real)
                    560:     abort ();
                    561: 
1.1.1.4   root      562:   /* If FROM is a SUBREG that indicates that we have already done at least
                    563:      the required extension, strip it.  We don't handle such SUBREGs as
                    564:      TO here.  */
                    565: 
                    566:   if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from)
                    567:       && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from)))
                    568:          >= GET_MODE_SIZE (to_mode))
                    569:       && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)
                    570:     from = gen_lowpart (to_mode, from), from_mode = to_mode;
                    571: 
                    572:   if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to))
                    573:     abort ();
                    574: 
1.1       root      575:   if (to_mode == from_mode
                    576:       || (from_mode == VOIDmode && CONSTANT_P (from)))
                    577:     {
                    578:       emit_move_insn (to, from);
                    579:       return;
                    580:     }
                    581: 
                    582:   if (to_real)
                    583:     {
1.1.1.6   root      584:       rtx value;
                    585: 
1.1.1.5   root      586: #ifdef HAVE_extendqfhf2
                    587:       if (HAVE_extendqfsf2 && from_mode == QFmode && to_mode == HFmode)
                    588:        {
                    589:          emit_unop_insn (CODE_FOR_extendqfsf2, to, from, UNKNOWN);
                    590:          return;
                    591:        }
                    592: #endif
                    593: #ifdef HAVE_extendqfsf2
                    594:       if (HAVE_extendqfsf2 && from_mode == QFmode && to_mode == SFmode)
                    595:        {
                    596:          emit_unop_insn (CODE_FOR_extendqfsf2, to, from, UNKNOWN);
                    597:          return;
                    598:        }
                    599: #endif
                    600: #ifdef HAVE_extendqfdf2
                    601:       if (HAVE_extendqfdf2 && from_mode == QFmode && to_mode == DFmode)
                    602:        {
                    603:          emit_unop_insn (CODE_FOR_extendqfdf2, to, from, UNKNOWN);
                    604:          return;
                    605:        }
                    606: #endif
                    607: #ifdef HAVE_extendqfxf2
                    608:       if (HAVE_extendqfxf2 && from_mode == QFmode && to_mode == XFmode)
                    609:        {
                    610:          emit_unop_insn (CODE_FOR_extendqfxf2, to, from, UNKNOWN);
                    611:          return;
                    612:        }
                    613: #endif
                    614: #ifdef HAVE_extendqftf2
                    615:       if (HAVE_extendqftf2 && from_mode == QFmode && to_mode == TFmode)
                    616:        {
                    617:          emit_unop_insn (CODE_FOR_extendqftf2, to, from, UNKNOWN);
                    618:          return;
                    619:        }
                    620: #endif
                    621: 
1.1.1.7 ! root      622: #ifdef HAVE_extendhftqf2
        !           623:       if (HAVE_extendhftqf2 && from_mode == HFmode && to_mode == TQFmode)
        !           624:        {
        !           625:          emit_unop_insn (CODE_FOR_extendhftqf2, to, from, UNKNOWN);
        !           626:          return;
        !           627:        }
        !           628: #endif
        !           629: 
1.1.1.5   root      630: #ifdef HAVE_extendhfsf2
                    631:       if (HAVE_extendhfsf2 && from_mode == HFmode && to_mode == SFmode)
                    632:        {
                    633:          emit_unop_insn (CODE_FOR_extendhfsf2, to, from, UNKNOWN);
                    634:          return;
                    635:        }
                    636: #endif
                    637: #ifdef HAVE_extendhfdf2
                    638:       if (HAVE_extendhfdf2 && from_mode == HFmode && to_mode == DFmode)
                    639:        {
                    640:          emit_unop_insn (CODE_FOR_extendhfdf2, to, from, UNKNOWN);
                    641:          return;
                    642:        }
                    643: #endif
                    644: #ifdef HAVE_extendhfxf2
                    645:       if (HAVE_extendhfxf2 && from_mode == HFmode && to_mode == XFmode)
                    646:        {
                    647:          emit_unop_insn (CODE_FOR_extendhfxf2, to, from, UNKNOWN);
                    648:          return;
                    649:        }
                    650: #endif
                    651: #ifdef HAVE_extendhftf2
                    652:       if (HAVE_extendhftf2 && from_mode == HFmode && to_mode == TFmode)
                    653:        {
                    654:          emit_unop_insn (CODE_FOR_extendhftf2, to, from, UNKNOWN);
                    655:          return;
                    656:        }
                    657: #endif
                    658: 
1.1       root      659: #ifdef HAVE_extendsfdf2
                    660:       if (HAVE_extendsfdf2 && from_mode == SFmode && to_mode == DFmode)
                    661:        {
                    662:          emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN);
                    663:          return;
                    664:        }
                    665: #endif
1.1.1.4   root      666: #ifdef HAVE_extendsfxf2
                    667:       if (HAVE_extendsfxf2 && from_mode == SFmode && to_mode == XFmode)
                    668:        {
                    669:          emit_unop_insn (CODE_FOR_extendsfxf2, to, from, UNKNOWN);
                    670:          return;
                    671:        }
                    672: #endif
1.1       root      673: #ifdef HAVE_extendsftf2
                    674:       if (HAVE_extendsftf2 && from_mode == SFmode && to_mode == TFmode)
                    675:        {
                    676:          emit_unop_insn (CODE_FOR_extendsftf2, to, from, UNKNOWN);
                    677:          return;
                    678:        }
                    679: #endif
1.1.1.4   root      680: #ifdef HAVE_extenddfxf2
                    681:       if (HAVE_extenddfxf2 && from_mode == DFmode && to_mode == XFmode)
                    682:        {
                    683:          emit_unop_insn (CODE_FOR_extenddfxf2, to, from, UNKNOWN);
                    684:          return;
                    685:        }
                    686: #endif
1.1       root      687: #ifdef HAVE_extenddftf2
                    688:       if (HAVE_extenddftf2 && from_mode == DFmode && to_mode == TFmode)
                    689:        {
                    690:          emit_unop_insn (CODE_FOR_extenddftf2, to, from, UNKNOWN);
                    691:          return;
                    692:        }
                    693: #endif
1.1.1.5   root      694: 
                    695: #ifdef HAVE_trunchfqf2
                    696:       if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode)
                    697:        {
                    698:          emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN);
                    699:          return;
                    700:        }
                    701: #endif
                    702: #ifdef HAVE_truncsfqf2
                    703:       if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode)
                    704:        {
                    705:          emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN);
                    706:          return;
                    707:        }
                    708: #endif
                    709: #ifdef HAVE_truncdfqf2
                    710:       if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode)
                    711:        {
                    712:          emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN);
                    713:          return;
                    714:        }
                    715: #endif
                    716: #ifdef HAVE_truncxfqf2
                    717:       if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode)
                    718:        {
                    719:          emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN);
                    720:          return;
                    721:        }
                    722: #endif
                    723: #ifdef HAVE_trunctfqf2
                    724:       if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode)
                    725:        {
                    726:          emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN);
                    727:          return;
                    728:        }
                    729: #endif
1.1.1.7 ! root      730: 
        !           731: #ifdef HAVE_trunctqfhf2
        !           732:       if (HAVE_trunctqfhf2 && from_mode == TQFmode && to_mode == HFmode)
        !           733:        {
        !           734:          emit_unop_insn (CODE_FOR_trunctqfhf2, to, from, UNKNOWN);
        !           735:          return;
        !           736:        }
        !           737: #endif
1.1.1.5   root      738: #ifdef HAVE_truncsfhf2
                    739:       if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode)
                    740:        {
                    741:          emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN);
                    742:          return;
                    743:        }
                    744: #endif
                    745: #ifdef HAVE_truncdfhf2
                    746:       if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode)
                    747:        {
                    748:          emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN);
                    749:          return;
                    750:        }
                    751: #endif
                    752: #ifdef HAVE_truncxfhf2
                    753:       if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode)
                    754:        {
                    755:          emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN);
                    756:          return;
                    757:        }
                    758: #endif
                    759: #ifdef HAVE_trunctfhf2
                    760:       if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode)
                    761:        {
                    762:          emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN);
                    763:          return;
                    764:        }
                    765: #endif
1.1       root      766: #ifdef HAVE_truncdfsf2
                    767:       if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode)
                    768:        {
                    769:          emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
                    770:          return;
                    771:        }
                    772: #endif
1.1.1.4   root      773: #ifdef HAVE_truncxfsf2
                    774:       if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode)
                    775:        {
                    776:          emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN);
                    777:          return;
                    778:        }
                    779: #endif
1.1       root      780: #ifdef HAVE_trunctfsf2
                    781:       if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode)
                    782:        {
                    783:          emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN);
                    784:          return;
                    785:        }
                    786: #endif
1.1.1.4   root      787: #ifdef HAVE_truncxfdf2
                    788:       if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode)
                    789:        {
                    790:          emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN);
                    791:          return;
                    792:        }
                    793: #endif
1.1       root      794: #ifdef HAVE_trunctfdf2
                    795:       if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode)
                    796:        {
                    797:          emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN);
                    798:          return;
                    799:        }
                    800: #endif
                    801: 
1.1.1.4   root      802:       libcall = (rtx) 0;
                    803:       switch (from_mode)
                    804:        {
                    805:        case SFmode:
                    806:          switch (to_mode)
                    807:            {
                    808:            case DFmode:
                    809:              libcall = extendsfdf2_libfunc;
                    810:              break;
                    811: 
                    812:            case XFmode:
                    813:              libcall = extendsfxf2_libfunc;
                    814:              break;
                    815: 
                    816:            case TFmode:
                    817:              libcall = extendsftf2_libfunc;
                    818:              break;
                    819:            }
                    820:          break;
                    821: 
                    822:        case DFmode:
                    823:          switch (to_mode)
                    824:            {
                    825:            case SFmode:
                    826:              libcall = truncdfsf2_libfunc;
                    827:              break;
                    828: 
                    829:            case XFmode:
                    830:              libcall = extenddfxf2_libfunc;
                    831:              break;
                    832: 
                    833:            case TFmode:
                    834:              libcall = extenddftf2_libfunc;
                    835:              break;
                    836:            }
                    837:          break;
                    838: 
                    839:        case XFmode:
                    840:          switch (to_mode)
                    841:            {
                    842:            case SFmode:
                    843:              libcall = truncxfsf2_libfunc;
                    844:              break;
                    845: 
                    846:            case DFmode:
                    847:              libcall = truncxfdf2_libfunc;
                    848:              break;
                    849:            }
                    850:          break;
                    851: 
                    852:        case TFmode:
                    853:          switch (to_mode)
                    854:            {
                    855:            case SFmode:
                    856:              libcall = trunctfsf2_libfunc;
                    857:              break;
                    858: 
                    859:            case DFmode:
                    860:              libcall = trunctfdf2_libfunc;
                    861:              break;
                    862:            }
                    863:          break;
                    864:        }
                    865: 
                    866:       if (libcall == (rtx) 0)
                    867:        /* This conversion is not implemented yet.  */
1.1       root      868:        abort ();
                    869: 
1.1.1.6   root      870:       value = emit_library_call_value (libcall, NULL_RTX, 1, to_mode,
                    871:                                       1, from, from_mode);
                    872:       emit_move_insn (to, value);
1.1       root      873:       return;
                    874:     }
                    875: 
                    876:   /* Now both modes are integers.  */
                    877: 
                    878:   /* Handle expanding beyond a word.  */
                    879:   if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)
                    880:       && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD)
                    881:     {
                    882:       rtx insns;
                    883:       rtx lowpart;
                    884:       rtx fill_value;
                    885:       rtx lowfrom;
                    886:       int i;
                    887:       enum machine_mode lowpart_mode;
                    888:       int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD);
                    889: 
                    890:       /* Try converting directly if the insn is supported.  */
                    891:       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
                    892:          != CODE_FOR_nothing)
                    893:        {
1.1.1.4   root      894:          /* If FROM is a SUBREG, put it into a register.  Do this
                    895:             so that we always generate the same set of insns for
                    896:             better cse'ing; if an intermediate assignment occurred,
                    897:             we won't be doing the operation directly on the SUBREG.  */
                    898:          if (optimize > 0 && GET_CODE (from) == SUBREG)
                    899:            from = force_reg (from_mode, from);
1.1       root      900:          emit_unop_insn (code, to, from, equiv_code);
                    901:          return;
                    902:        }
                    903:       /* Next, try converting via full word.  */
                    904:       else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD
                    905:               && ((code = can_extend_p (to_mode, word_mode, unsignedp))
                    906:                   != CODE_FOR_nothing))
                    907:        {
1.1.1.6   root      908:          if (GET_CODE (to) == REG)
                    909:            emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
1.1       root      910:          convert_move (gen_lowpart (word_mode, to), from, unsignedp);
                    911:          emit_unop_insn (code, to,
                    912:                          gen_lowpart (word_mode, to), equiv_code);
                    913:          return;
                    914:        }
                    915: 
                    916:       /* No special multiword conversion insn; do it by hand.  */
                    917:       start_sequence ();
                    918: 
1.1.1.7 ! root      919:       /* Since we will turn this into a no conflict block, we must ensure
        !           920:         that the source does not overlap the target.  */
        !           921: 
        !           922:       if (reg_overlap_mentioned_p (to, from))
        !           923:        from = force_reg (from_mode, from);
        !           924: 
1.1       root      925:       /* Get a copy of FROM widened to a word, if necessary.  */
                    926:       if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD)
                    927:        lowpart_mode = word_mode;
                    928:       else
                    929:        lowpart_mode = from_mode;
                    930: 
                    931:       lowfrom = convert_to_mode (lowpart_mode, from, unsignedp);
                    932: 
                    933:       lowpart = gen_lowpart (lowpart_mode, to);
                    934:       emit_move_insn (lowpart, lowfrom);
                    935: 
                    936:       /* Compute the value to put in each remaining word.  */
                    937:       if (unsignedp)
                    938:        fill_value = const0_rtx;
                    939:       else
                    940:        {
                    941: #ifdef HAVE_slt
                    942:          if (HAVE_slt
                    943:              && insn_operand_mode[(int) CODE_FOR_slt][0] == word_mode
                    944:              && STORE_FLAG_VALUE == -1)
                    945:            {
1.1.1.4   root      946:              emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
                    947:                             lowpart_mode, 0, 0);
1.1       root      948:              fill_value = gen_reg_rtx (word_mode);
                    949:              emit_insn (gen_slt (fill_value));
                    950:            }
                    951:          else
                    952: #endif
                    953:            {
                    954:              fill_value
                    955:                = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
                    956:                                size_int (GET_MODE_BITSIZE (lowpart_mode) - 1),
1.1.1.4   root      957:                                NULL_RTX, 0);
1.1       root      958:              fill_value = convert_to_mode (word_mode, fill_value, 1);
                    959:            }
                    960:        }
                    961: 
                    962:       /* Fill the remaining words.  */
                    963:       for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
                    964:        {
                    965:          int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
                    966:          rtx subword = operand_subword (to, index, 1, to_mode);
                    967: 
                    968:          if (subword == 0)
                    969:            abort ();
                    970: 
                    971:          if (fill_value != subword)
                    972:            emit_move_insn (subword, fill_value);
                    973:        }
                    974: 
                    975:       insns = get_insns ();
                    976:       end_sequence ();
                    977: 
1.1.1.4   root      978:       emit_no_conflict_block (insns, to, from, NULL_RTX,
1.1.1.5   root      979:                              gen_rtx (equiv_code, to_mode, copy_rtx (from)));
1.1       root      980:       return;
                    981:     }
                    982: 
1.1.1.5   root      983:   /* Truncating multi-word to a word or less.  */
                    984:   if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD
                    985:       && GET_MODE_BITSIZE (to_mode) <= BITS_PER_WORD)
1.1       root      986:     {
1.1.1.6   root      987:       if (!((GET_CODE (from) == MEM
                    988:             && ! MEM_VOLATILE_P (from)
                    989:             && direct_load[(int) to_mode]
                    990:             && ! mode_dependent_address_p (XEXP (from, 0)))
                    991:            || GET_CODE (from) == REG
                    992:            || GET_CODE (from) == SUBREG))
                    993:        from = force_reg (from_mode, from);
1.1       root      994:       convert_move (to, gen_lowpart (word_mode, from), 0);
                    995:       return;
                    996:     }
                    997: 
                    998:   /* Handle pointer conversion */                      /* SPEE 900220 */
                    999:   if (to_mode == PSImode)
                   1000:     {
                   1001:       if (from_mode != SImode)
                   1002:        from = convert_to_mode (SImode, from, unsignedp);
                   1003: 
1.1.1.7 ! root     1004: #ifdef HAVE_truncsipsi2
        !          1005:       if (HAVE_truncsipsi2)
1.1       root     1006:        {
1.1.1.7 ! root     1007:          emit_unop_insn (CODE_FOR_truncsipsi2, to, from, UNKNOWN);
1.1       root     1008:          return;
                   1009:        }
1.1.1.7 ! root     1010: #endif /* HAVE_truncsipsi2 */
1.1       root     1011:       abort ();
                   1012:     }
                   1013: 
                   1014:   if (from_mode == PSImode)
                   1015:     {
                   1016:       if (to_mode != SImode)
                   1017:        {
                   1018:          from = convert_to_mode (SImode, from, unsignedp);
                   1019:          from_mode = SImode;
                   1020:        }
                   1021:       else
                   1022:        {
1.1.1.7 ! root     1023: #ifdef HAVE_extendpsisi2
        !          1024:          if (HAVE_extendpsisi2)
1.1       root     1025:            {
1.1.1.7 ! root     1026:              emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN);
1.1       root     1027:              return;
                   1028:            }
1.1.1.7 ! root     1029: #endif /* HAVE_extendpsisi2 */
        !          1030:          abort ();
        !          1031:        }
        !          1032:     }
        !          1033: 
        !          1034:   if (to_mode == PDImode)
        !          1035:     {
        !          1036:       if (from_mode != DImode)
        !          1037:        from = convert_to_mode (DImode, from, unsignedp);
        !          1038: 
        !          1039: #ifdef HAVE_truncdipdi2
        !          1040:       if (HAVE_truncdipdi2)
        !          1041:        {
        !          1042:          emit_unop_insn (CODE_FOR_truncdipdi2, to, from, UNKNOWN);
        !          1043:          return;
        !          1044:        }
        !          1045: #endif /* HAVE_truncdipdi2 */
        !          1046:       abort ();
        !          1047:     }
        !          1048: 
        !          1049:   if (from_mode == PDImode)
        !          1050:     {
        !          1051:       if (to_mode != DImode)
        !          1052:        {
        !          1053:          from = convert_to_mode (DImode, from, unsignedp);
        !          1054:          from_mode = DImode;
        !          1055:        }
        !          1056:       else
        !          1057:        {
        !          1058: #ifdef HAVE_extendpdidi2
        !          1059:          if (HAVE_extendpdidi2)
        !          1060:            {
        !          1061:              emit_unop_insn (CODE_FOR_extendpdidi2, to, from, UNKNOWN);
        !          1062:              return;
        !          1063:            }
        !          1064: #endif /* HAVE_extendpdidi2 */
1.1       root     1065:          abort ();
                   1066:        }
                   1067:     }
                   1068: 
                   1069:   /* Now follow all the conversions between integers
                   1070:      no more than a word long.  */
                   1071: 
                   1072:   /* For truncation, usually we can just refer to FROM in a narrower mode.  */
                   1073:   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
                   1074:       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
1.1.1.5   root     1075:                                GET_MODE_BITSIZE (from_mode)))
1.1       root     1076:     {
1.1.1.5   root     1077:       if (!((GET_CODE (from) == MEM
                   1078:             && ! MEM_VOLATILE_P (from)
                   1079:             && direct_load[(int) to_mode]
                   1080:             && ! mode_dependent_address_p (XEXP (from, 0)))
                   1081:            || GET_CODE (from) == REG
                   1082:            || GET_CODE (from) == SUBREG))
                   1083:        from = force_reg (from_mode, from);
1.1       root     1084:       emit_move_insn (to, gen_lowpart (to_mode, from));
                   1085:       return;
                   1086:     }
                   1087: 
1.1.1.5   root     1088:   /* Handle extension.  */
1.1       root     1089:   if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode))
                   1090:     {
                   1091:       /* Convert directly if that works.  */
                   1092:       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
                   1093:          != CODE_FOR_nothing)
                   1094:        {
1.1.1.4   root     1095:          /* If FROM is a SUBREG, put it into a register.  Do this
                   1096:             so that we always generate the same set of insns for
                   1097:             better cse'ing; if an intermediate assignment occurred,
                   1098:             we won't be doing the operation directly on the SUBREG.  */
                   1099:          if (optimize > 0 && GET_CODE (from) == SUBREG)
                   1100:            from = force_reg (from_mode, from);
1.1       root     1101:          emit_unop_insn (code, to, from, equiv_code);
                   1102:          return;
                   1103:        }
                   1104:       else
                   1105:        {
                   1106:          enum machine_mode intermediate;
                   1107: 
                   1108:          /* Search for a mode to convert via.  */
                   1109:          for (intermediate = from_mode; intermediate != VOIDmode;
                   1110:               intermediate = GET_MODE_WIDER_MODE (intermediate))
1.1.1.7 ! root     1111:            if (((can_extend_p (to_mode, intermediate, unsignedp)
        !          1112:                  != CODE_FOR_nothing)
        !          1113:                 || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
        !          1114:                     && TRULY_NOOP_TRUNCATION (to_mode, intermediate)))
1.1       root     1115:                && (can_extend_p (intermediate, from_mode, unsignedp)
                   1116:                    != CODE_FOR_nothing))
                   1117:              {
                   1118:                convert_move (to, convert_to_mode (intermediate, from,
                   1119:                                                   unsignedp), unsignedp);
                   1120:                return;
                   1121:              }
                   1122: 
                   1123:          /* No suitable intermediate mode.  */
                   1124:          abort ();
                   1125:        }
                   1126:     }
                   1127: 
                   1128:   /* Support special truncate insns for certain modes.  */ 
                   1129: 
                   1130:   if (from_mode == DImode && to_mode == SImode)
                   1131:     {
                   1132: #ifdef HAVE_truncdisi2
                   1133:       if (HAVE_truncdisi2)
                   1134:        {
                   1135:          emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN);
                   1136:          return;
                   1137:        }
                   1138: #endif
                   1139:       convert_move (to, force_reg (from_mode, from), unsignedp);
                   1140:       return;
                   1141:     }
                   1142: 
                   1143:   if (from_mode == DImode && to_mode == HImode)
                   1144:     {
                   1145: #ifdef HAVE_truncdihi2
                   1146:       if (HAVE_truncdihi2)
                   1147:        {
                   1148:          emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN);
                   1149:          return;
                   1150:        }
                   1151: #endif
                   1152:       convert_move (to, force_reg (from_mode, from), unsignedp);
                   1153:       return;
                   1154:     }
                   1155: 
                   1156:   if (from_mode == DImode && to_mode == QImode)
                   1157:     {
                   1158: #ifdef HAVE_truncdiqi2
                   1159:       if (HAVE_truncdiqi2)
                   1160:        {
                   1161:          emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN);
                   1162:          return;
                   1163:        }
                   1164: #endif
                   1165:       convert_move (to, force_reg (from_mode, from), unsignedp);
                   1166:       return;
                   1167:     }
                   1168: 
                   1169:   if (from_mode == SImode && to_mode == HImode)
                   1170:     {
                   1171: #ifdef HAVE_truncsihi2
                   1172:       if (HAVE_truncsihi2)
                   1173:        {
                   1174:          emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
                   1175:          return;
                   1176:        }
                   1177: #endif
                   1178:       convert_move (to, force_reg (from_mode, from), unsignedp);
                   1179:       return;
                   1180:     }
                   1181: 
                   1182:   if (from_mode == SImode && to_mode == QImode)
                   1183:     {
                   1184: #ifdef HAVE_truncsiqi2
                   1185:       if (HAVE_truncsiqi2)
                   1186:        {
                   1187:          emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
                   1188:          return;
                   1189:        }
                   1190: #endif
                   1191:       convert_move (to, force_reg (from_mode, from), unsignedp);
                   1192:       return;
                   1193:     }
                   1194: 
                   1195:   if (from_mode == HImode && to_mode == QImode)
                   1196:     {
                   1197: #ifdef HAVE_trunchiqi2
                   1198:       if (HAVE_trunchiqi2)
                   1199:        {
                   1200:          emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
                   1201:          return;
                   1202:        }
                   1203: #endif
                   1204:       convert_move (to, force_reg (from_mode, from), unsignedp);
                   1205:       return;
                   1206:     }
                   1207: 
1.1.1.7 ! root     1208:   if (from_mode == TImode && to_mode == DImode)
        !          1209:     {
        !          1210: #ifdef HAVE_trunctidi2
        !          1211:       if (HAVE_trunctidi2)
        !          1212:        {
        !          1213:          emit_unop_insn (CODE_FOR_trunctidi2, to, from, UNKNOWN);
        !          1214:          return;
        !          1215:        }
        !          1216: #endif
        !          1217:       convert_move (to, force_reg (from_mode, from), unsignedp);
        !          1218:       return;
        !          1219:     }
        !          1220: 
        !          1221:   if (from_mode == TImode && to_mode == SImode)
        !          1222:     {
        !          1223: #ifdef HAVE_trunctisi2
        !          1224:       if (HAVE_trunctisi2)
        !          1225:        {
        !          1226:          emit_unop_insn (CODE_FOR_trunctisi2, to, from, UNKNOWN);
        !          1227:          return;
        !          1228:        }
        !          1229: #endif
        !          1230:       convert_move (to, force_reg (from_mode, from), unsignedp);
        !          1231:       return;
        !          1232:     }
        !          1233: 
        !          1234:   if (from_mode == TImode && to_mode == HImode)
        !          1235:     {
        !          1236: #ifdef HAVE_trunctihi2
        !          1237:       if (HAVE_trunctihi2)
        !          1238:        {
        !          1239:          emit_unop_insn (CODE_FOR_trunctihi2, to, from, UNKNOWN);
        !          1240:          return;
        !          1241:        }
        !          1242: #endif
        !          1243:       convert_move (to, force_reg (from_mode, from), unsignedp);
        !          1244:       return;
        !          1245:     }
        !          1246: 
        !          1247:   if (from_mode == TImode && to_mode == QImode)
        !          1248:     {
        !          1249: #ifdef HAVE_trunctiqi2
        !          1250:       if (HAVE_trunctiqi2)
        !          1251:        {
        !          1252:          emit_unop_insn (CODE_FOR_trunctiqi2, to, from, UNKNOWN);
        !          1253:          return;
        !          1254:        }
        !          1255: #endif
        !          1256:       convert_move (to, force_reg (from_mode, from), unsignedp);
        !          1257:       return;
        !          1258:     }
        !          1259: 
1.1       root     1260:   /* Handle truncation of volatile memrefs, and so on;
                   1261:      the things that couldn't be truncated directly,
                   1262:      and for which there was no special instruction.  */
                   1263:   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode))
                   1264:     {
                   1265:       rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from));
                   1266:       emit_move_insn (to, temp);
                   1267:       return;
                   1268:     }
                   1269: 
                   1270:   /* Mode combination is not recognized.  */
                   1271:   abort ();
                   1272: }
                   1273: 
                   1274: /* Return an rtx for a value that would result
                   1275:    from converting X to mode MODE.
                   1276:    Both X and MODE may be floating, or both integer.
                   1277:    UNSIGNEDP is nonzero if X is an unsigned value.
                   1278:    This can be done by referring to a part of X in place
1.1.1.4   root     1279:    or by copying to a new temporary with conversion.
                   1280: 
                   1281:    This function *must not* call protect_from_queue
                   1282:    except when putting X into an insn (in which case convert_move does it).  */
1.1       root     1283: 
                   1284: rtx
                   1285: convert_to_mode (mode, x, unsignedp)
                   1286:      enum machine_mode mode;
                   1287:      rtx x;
                   1288:      int unsignedp;
                   1289: {
1.1.1.6   root     1290:   return convert_modes (mode, VOIDmode, x, unsignedp);
                   1291: }
                   1292: 
                   1293: /* Return an rtx for a value that would result
                   1294:    from converting X from mode OLDMODE to mode MODE.
                   1295:    Both modes may be floating, or both integer.
                   1296:    UNSIGNEDP is nonzero if X is an unsigned value.
                   1297: 
                   1298:    This can be done by referring to a part of X in place
                   1299:    or by copying to a new temporary with conversion.
                   1300: 
                   1301:    You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid mode.
                   1302: 
                   1303:    This function *must not* call protect_from_queue
                   1304:    except when putting X into an insn (in which case convert_move does it).  */
                   1305: 
                   1306: rtx
                   1307: convert_modes (mode, oldmode, x, unsignedp)
                   1308:      enum machine_mode mode, oldmode;
                   1309:      rtx x;
                   1310:      int unsignedp;
                   1311: {
1.1       root     1312:   register rtx temp;
1.1.1.6   root     1313: 
1.1.1.4   root     1314:   /* If FROM is a SUBREG that indicates that we have already done at least
                   1315:      the required extension, strip it.  */
1.1       root     1316: 
1.1.1.4   root     1317:   if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
                   1318:       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)
                   1319:       && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp)
                   1320:     x = gen_lowpart (mode, x);
1.1       root     1321: 
1.1.1.6   root     1322:   if (GET_MODE (x) != VOIDmode)
                   1323:     oldmode = GET_MODE (x);
                   1324:  
                   1325:   if (mode == oldmode)
1.1       root     1326:     return x;
                   1327: 
                   1328:   /* There is one case that we must handle specially: If we are converting
1.1.1.4   root     1329:      a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and
1.1       root     1330:      we are to interpret the constant as unsigned, gen_lowpart will do
                   1331:      the wrong if the constant appears negative.  What we want to do is
                   1332:      make the high-order word of the constant zero, not all ones.  */
                   1333: 
                   1334:   if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
1.1.1.4   root     1335:       && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
1.1       root     1336:       && GET_CODE (x) == CONST_INT && INTVAL (x) < 0)
1.1.1.4   root     1337:     return immed_double_const (INTVAL (x), (HOST_WIDE_INT) 0, mode);
1.1       root     1338: 
                   1339:   /* We can do this with a gen_lowpart if both desired and current modes
                   1340:      are integer, and this is either a constant integer, a register, or a
1.1.1.6   root     1341:      non-volatile MEM.  Except for the constant case where MODE is no
                   1342:      wider than HOST_BITS_PER_WIDE_INT, we must be narrowing the operand.  */
1.1       root     1343: 
1.1.1.6   root     1344:   if ((GET_CODE (x) == CONST_INT
                   1345:        && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
1.1       root     1346:       || (GET_MODE_CLASS (mode) == MODE_INT
1.1.1.6   root     1347:          && GET_MODE_CLASS (oldmode) == MODE_INT
1.1       root     1348:          && (GET_CODE (x) == CONST_DOUBLE
1.1.1.6   root     1349:              || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (oldmode)
                   1350:                  && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x)
                   1351:                       && direct_load[(int) mode])
1.1.1.7 ! root     1352:                      || (GET_CODE (x) == REG
        !          1353:                          && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
        !          1354:                                                    GET_MODE_BITSIZE (GET_MODE (x)))))))))
1.1.1.6   root     1355:     {
                   1356:       /* ?? If we don't know OLDMODE, we have to assume here that
                   1357:         X does not need sign- or zero-extension.   This may not be
                   1358:         the case, but it's the best we can do.  */
                   1359:       if (GET_CODE (x) == CONST_INT && oldmode != VOIDmode
                   1360:          && GET_MODE_SIZE (mode) > GET_MODE_SIZE (oldmode))
                   1361:        {
                   1362:          HOST_WIDE_INT val = INTVAL (x);
                   1363:          int width = GET_MODE_BITSIZE (oldmode);
                   1364: 
                   1365:          /* We must sign or zero-extend in this case.  Start by
                   1366:             zero-extending, then sign extend if we need to.  */
                   1367:          val &= ((HOST_WIDE_INT) 1 << width) - 1;
                   1368:          if (! unsignedp
                   1369:              && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
                   1370:            val |= (HOST_WIDE_INT) (-1) << width;
                   1371: 
                   1372:          return GEN_INT (val);
                   1373:        }
                   1374: 
                   1375:       return gen_lowpart (mode, x);
                   1376:     }
1.1       root     1377: 
                   1378:   temp = gen_reg_rtx (mode);
                   1379:   convert_move (temp, x, unsignedp);
                   1380:   return temp;
                   1381: }
                   1382: 
                   1383: /* Generate several move instructions to copy LEN bytes
                   1384:    from block FROM to block TO.  (These are MEM rtx's with BLKmode).
                   1385:    The caller must pass FROM and TO
                   1386:     through protect_from_queue before calling.
                   1387:    ALIGN (in bytes) is maximum alignment we can assume.  */
                   1388: 
                   1389: static void
                   1390: move_by_pieces (to, from, len, align)
                   1391:      rtx to, from;
                   1392:      int len, align;
                   1393: {
                   1394:   struct move_by_pieces data;
                   1395:   rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
1.1.1.2   root     1396:   int max_size = MOVE_MAX + 1;
1.1       root     1397: 
                   1398:   data.offset = 0;
                   1399:   data.to_addr = to_addr;
                   1400:   data.from_addr = from_addr;
                   1401:   data.to = to;
                   1402:   data.from = from;
                   1403:   data.autinc_to
                   1404:     = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
                   1405:        || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
                   1406:   data.autinc_from
                   1407:     = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
                   1408:        || GET_CODE (from_addr) == POST_INC
                   1409:        || GET_CODE (from_addr) == POST_DEC);
                   1410: 
                   1411:   data.explicit_inc_from = 0;
                   1412:   data.explicit_inc_to = 0;
                   1413:   data.reverse
                   1414:     = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
                   1415:   if (data.reverse) data.offset = len;
                   1416:   data.len = len;
                   1417: 
                   1418:   /* If copying requires more than two move insns,
                   1419:      copy addresses to registers (to make displacements shorter)
                   1420:      and use post-increment if available.  */
                   1421:   if (!(data.autinc_from && data.autinc_to)
                   1422:       && move_by_pieces_ninsns (len, align) > 2)
                   1423:     {
                   1424: #ifdef HAVE_PRE_DECREMENT
                   1425:       if (data.reverse && ! data.autinc_from)
                   1426:        {
                   1427:          data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
                   1428:          data.autinc_from = 1;
                   1429:          data.explicit_inc_from = -1;
                   1430:        }
                   1431: #endif
                   1432: #ifdef HAVE_POST_INCREMENT
                   1433:       if (! data.autinc_from)
                   1434:        {
                   1435:          data.from_addr = copy_addr_to_reg (from_addr);
                   1436:          data.autinc_from = 1;
                   1437:          data.explicit_inc_from = 1;
                   1438:        }
                   1439: #endif
                   1440:       if (!data.autinc_from && CONSTANT_P (from_addr))
                   1441:        data.from_addr = copy_addr_to_reg (from_addr);
                   1442: #ifdef HAVE_PRE_DECREMENT
                   1443:       if (data.reverse && ! data.autinc_to)
                   1444:        {
                   1445:          data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
                   1446:          data.autinc_to = 1;
                   1447:          data.explicit_inc_to = -1;
                   1448:        }
                   1449: #endif
                   1450: #ifdef HAVE_POST_INCREMENT
                   1451:       if (! data.reverse && ! data.autinc_to)
                   1452:        {
                   1453:          data.to_addr = copy_addr_to_reg (to_addr);
                   1454:          data.autinc_to = 1;
                   1455:          data.explicit_inc_to = 1;
                   1456:        }
                   1457: #endif
                   1458:       if (!data.autinc_to && CONSTANT_P (to_addr))
                   1459:        data.to_addr = copy_addr_to_reg (to_addr);
                   1460:     }
                   1461: 
1.1.1.2   root     1462:   if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS)
                   1463:       || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1       root     1464:     align = MOVE_MAX;
                   1465: 
                   1466:   /* First move what we can in the largest integer mode, then go to
                   1467:      successively smaller modes.  */
                   1468: 
                   1469:   while (max_size > 1)
                   1470:     {
                   1471:       enum machine_mode mode = VOIDmode, tmode;
                   1472:       enum insn_code icode;
                   1473: 
1.1.1.3   root     1474:       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
                   1475:           tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
                   1476:        if (GET_MODE_SIZE (tmode) < max_size)
1.1       root     1477:          mode = tmode;
                   1478: 
                   1479:       if (mode == VOIDmode)
                   1480:        break;
                   1481: 
                   1482:       icode = mov_optab->handlers[(int) mode].insn_code;
                   1483:       if (icode != CODE_FOR_nothing
                   1484:          && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,
                   1485:                           GET_MODE_SIZE (mode)))
                   1486:        move_by_pieces_1 (GEN_FCN (icode), mode, &data);
                   1487: 
                   1488:       max_size = GET_MODE_SIZE (mode);
                   1489:     }
                   1490: 
                   1491:   /* The code above should have handled everything.  */
                   1492:   if (data.len != 0)
                   1493:     abort ();
                   1494: }
                   1495: 
                   1496: /* Return number of insns required to move L bytes by pieces.
                   1497:    ALIGN (in bytes) is maximum alignment we can assume.  */
                   1498: 
                   1499: static int
                   1500: move_by_pieces_ninsns (l, align)
                   1501:      unsigned int l;
                   1502:      int align;
                   1503: {
                   1504:   register int n_insns = 0;
1.1.1.2   root     1505:   int max_size = MOVE_MAX + 1;
1.1       root     1506: 
1.1.1.2   root     1507:   if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS)
                   1508:       || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1       root     1509:     align = MOVE_MAX;
                   1510: 
                   1511:   while (max_size > 1)
                   1512:     {
                   1513:       enum machine_mode mode = VOIDmode, tmode;
                   1514:       enum insn_code icode;
                   1515: 
1.1.1.3   root     1516:       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
                   1517:           tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
                   1518:        if (GET_MODE_SIZE (tmode) < max_size)
1.1       root     1519:          mode = tmode;
                   1520: 
                   1521:       if (mode == VOIDmode)
                   1522:        break;
                   1523: 
                   1524:       icode = mov_optab->handlers[(int) mode].insn_code;
                   1525:       if (icode != CODE_FOR_nothing
                   1526:          && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,
                   1527:                           GET_MODE_SIZE (mode)))
                   1528:        n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
                   1529: 
                   1530:       max_size = GET_MODE_SIZE (mode);
                   1531:     }
                   1532: 
                   1533:   return n_insns;
                   1534: }
                   1535: 
                   1536: /* Subroutine of move_by_pieces.  Move as many bytes as appropriate
                   1537:    with move instructions for mode MODE.  GENFUN is the gen_... function
                   1538:    to make a move insn for that mode.  DATA has all the other info.  */
                   1539: 
                   1540: static void
                   1541: move_by_pieces_1 (genfun, mode, data)
                   1542:      rtx (*genfun) ();
                   1543:      enum machine_mode mode;
                   1544:      struct move_by_pieces *data;
                   1545: {
                   1546:   register int size = GET_MODE_SIZE (mode);
                   1547:   register rtx to1, from1;
                   1548: 
                   1549:   while (data->len >= size)
                   1550:     {
                   1551:       if (data->reverse) data->offset -= size;
                   1552: 
                   1553:       to1 = (data->autinc_to
                   1554:             ? gen_rtx (MEM, mode, data->to_addr)
                   1555:             : change_address (data->to, mode,
                   1556:                               plus_constant (data->to_addr, data->offset)));
                   1557:       from1 =
                   1558:        (data->autinc_from
                   1559:         ? gen_rtx (MEM, mode, data->from_addr)
                   1560:         : change_address (data->from, mode,
                   1561:                           plus_constant (data->from_addr, data->offset)));
                   1562: 
                   1563: #ifdef HAVE_PRE_DECREMENT
                   1564:       if (data->explicit_inc_to < 0)
1.1.1.4   root     1565:        emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
1.1       root     1566:       if (data->explicit_inc_from < 0)
1.1.1.4   root     1567:        emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
1.1       root     1568: #endif
                   1569: 
                   1570:       emit_insn ((*genfun) (to1, from1));
                   1571: #ifdef HAVE_POST_INCREMENT
                   1572:       if (data->explicit_inc_to > 0)
1.1.1.4   root     1573:        emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
1.1       root     1574:       if (data->explicit_inc_from > 0)
1.1.1.4   root     1575:        emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
1.1       root     1576: #endif
                   1577: 
                   1578:       if (! data->reverse) data->offset += size;
                   1579: 
                   1580:       data->len -= size;
                   1581:     }
                   1582: }
                   1583: 
                   1584: /* Emit code to move a block Y to a block X.
                   1585:    This may be done with string-move instructions,
                   1586:    with multiple scalar move instructions, or with a library call.
                   1587: 
                   1588:    Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
                   1589:    with mode BLKmode.
                   1590:    SIZE is an rtx that says how long they are.
                   1591:    ALIGN is the maximum alignment we can assume they have,
                   1592:    measured in bytes.  */
                   1593: 
                   1594: void
                   1595: emit_block_move (x, y, size, align)
                   1596:      rtx x, y;
                   1597:      rtx size;
                   1598:      int align;
                   1599: {
                   1600:   if (GET_MODE (x) != BLKmode)
                   1601:     abort ();
                   1602: 
                   1603:   if (GET_MODE (y) != BLKmode)
                   1604:     abort ();
                   1605: 
                   1606:   x = protect_from_queue (x, 1);
                   1607:   y = protect_from_queue (y, 0);
1.1.1.4   root     1608:   size = protect_from_queue (size, 0);
1.1       root     1609: 
                   1610:   if (GET_CODE (x) != MEM)
                   1611:     abort ();
                   1612:   if (GET_CODE (y) != MEM)
                   1613:     abort ();
                   1614:   if (size == 0)
                   1615:     abort ();
                   1616: 
                   1617:   if (GET_CODE (size) == CONST_INT
1.1.1.4   root     1618:       && (move_by_pieces_ninsns (INTVAL (size), align) < MOVE_RATIO))
1.1       root     1619:     move_by_pieces (x, y, INTVAL (size), align);
                   1620:   else
                   1621:     {
                   1622:       /* Try the most limited insn first, because there's no point
                   1623:         including more than one in the machine description unless
                   1624:         the more limited one has some advantage.  */
1.1.1.4   root     1625: 
                   1626:       rtx opalign = GEN_INT (align);
                   1627:       enum machine_mode mode;
                   1628: 
                   1629:       for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
                   1630:           mode = GET_MODE_WIDER_MODE (mode))
1.1       root     1631:        {
1.1.1.4   root     1632:          enum insn_code code = movstr_optab[(int) mode];
                   1633: 
                   1634:          if (code != CODE_FOR_nothing
                   1635:              /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
                   1636:                 here because if SIZE is less than the mode mask, as it is
1.1.1.5   root     1637:                 returned by the macro, it will definitely be less than the
1.1.1.4   root     1638:                 actual mode mask.  */
1.1.1.7 ! root     1639:              && ((GET_CODE (size) == CONST_INT
        !          1640:                   && ((unsigned HOST_WIDE_INT) INTVAL (size)
        !          1641:                       <= GET_MODE_MASK (mode)))
        !          1642:                  || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
1.1.1.4   root     1643:              && (insn_operand_predicate[(int) code][0] == 0
                   1644:                  || (*insn_operand_predicate[(int) code][0]) (x, BLKmode))
                   1645:              && (insn_operand_predicate[(int) code][1] == 0
                   1646:                  || (*insn_operand_predicate[(int) code][1]) (y, BLKmode))
                   1647:              && (insn_operand_predicate[(int) code][3] == 0
                   1648:                  || (*insn_operand_predicate[(int) code][3]) (opalign,
                   1649:                                                               VOIDmode)))
1.1       root     1650:            {
1.1.1.4   root     1651:              rtx op2;
                   1652:              rtx last = get_last_insn ();
                   1653:              rtx pat;
                   1654: 
                   1655:              op2 = convert_to_mode (mode, size, 1);
                   1656:              if (insn_operand_predicate[(int) code][2] != 0
                   1657:                  && ! (*insn_operand_predicate[(int) code][2]) (op2, mode))
                   1658:                op2 = copy_to_mode_reg (mode, op2);
                   1659: 
                   1660:              pat = GEN_FCN ((int) code) (x, y, op2, opalign);
                   1661:              if (pat)
                   1662:                {
                   1663:                  emit_insn (pat);
                   1664:                  return;
                   1665:                }
                   1666:              else
                   1667:                delete_insns_since (last);
1.1       root     1668:            }
                   1669:        }
                   1670: 
                   1671: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4   root     1672:       emit_library_call (memcpy_libfunc, 0,
1.1       root     1673:                         VOIDmode, 3, XEXP (x, 0), Pmode,
                   1674:                         XEXP (y, 0), Pmode,
1.1.1.5   root     1675:                         convert_to_mode (TYPE_MODE (sizetype), size,
                   1676:                                          TREE_UNSIGNED (sizetype)),
                   1677:                         TYPE_MODE (sizetype));
1.1       root     1678: #else
1.1.1.4   root     1679:       emit_library_call (bcopy_libfunc, 0,
1.1       root     1680:                         VOIDmode, 3, XEXP (y, 0), Pmode,
                   1681:                         XEXP (x, 0), Pmode,
1.1.1.5   root     1682:                         convert_to_mode (TYPE_MODE (sizetype), size,
                   1683:                                          TREE_UNSIGNED (sizetype)),
                   1684:                         TYPE_MODE (sizetype));
1.1       root     1685: #endif
                   1686:     }
                   1687: }
                   1688: 
                   1689: /* Copy all or part of a value X into registers starting at REGNO.
                   1690:    The number of registers to be filled is NREGS.  */
                   1691: 
                   1692: void
                   1693: move_block_to_reg (regno, x, nregs, mode)
                   1694:      int regno;
                   1695:      rtx x;
                   1696:      int nregs;
                   1697:      enum machine_mode mode;
                   1698: {
                   1699:   int i;
                   1700:   rtx pat, last;
                   1701: 
1.1.1.7 ! root     1702:   if (nregs == 0)
        !          1703:     return;
        !          1704: 
1.1       root     1705:   if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
                   1706:     x = validize_mem (force_const_mem (mode, x));
                   1707: 
                   1708:   /* See if the machine can do this with a load multiple insn.  */
                   1709: #ifdef HAVE_load_multiple
1.1.1.6   root     1710:   if (HAVE_load_multiple)
1.1       root     1711:     {
1.1.1.6   root     1712:       last = get_last_insn ();
                   1713:       pat = gen_load_multiple (gen_rtx (REG, word_mode, regno), x,
                   1714:                               GEN_INT (nregs));
                   1715:       if (pat)
                   1716:        {
                   1717:          emit_insn (pat);
                   1718:          return;
                   1719:        }
                   1720:       else
                   1721:        delete_insns_since (last);
1.1       root     1722:     }
                   1723: #endif
                   1724: 
                   1725:   for (i = 0; i < nregs; i++)
                   1726:     emit_move_insn (gen_rtx (REG, word_mode, regno + i),
                   1727:                    operand_subword_force (x, i, mode));
                   1728: }
                   1729: 
                   1730: /* Copy all or part of a BLKmode value X out of registers starting at REGNO.
1.1.1.6   root     1731:    The number of registers to be filled is NREGS.  SIZE indicates the number
                   1732:    of bytes in the object X.  */
                   1733: 
1.1       root     1734: 
                   1735: void
1.1.1.6   root     1736: move_block_from_reg (regno, x, nregs, size)
1.1       root     1737:      int regno;
                   1738:      rtx x;
                   1739:      int nregs;
1.1.1.6   root     1740:      int size;
1.1       root     1741: {
                   1742:   int i;
                   1743:   rtx pat, last;
                   1744: 
1.1.1.6   root     1745:   /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
                   1746:      to the left before storing to memory.  */
                   1747:   if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)
                   1748:     {
                   1749:       rtx tem = operand_subword (x, 0, 1, BLKmode);
                   1750:       rtx shift;
                   1751: 
                   1752:       if (tem == 0)
                   1753:        abort ();
                   1754: 
                   1755:       shift = expand_shift (LSHIFT_EXPR, word_mode,
                   1756:                            gen_rtx (REG, word_mode, regno),
                   1757:                            build_int_2 ((UNITS_PER_WORD - size)
                   1758:                                         * BITS_PER_UNIT, 0), NULL_RTX, 0);
                   1759:       emit_move_insn (tem, shift);
                   1760:       return;
                   1761:     }
                   1762: 
1.1       root     1763:   /* See if the machine can do this with a store multiple insn.  */
                   1764: #ifdef HAVE_store_multiple
1.1.1.6   root     1765:   if (HAVE_store_multiple)
1.1       root     1766:     {
1.1.1.6   root     1767:       last = get_last_insn ();
                   1768:       pat = gen_store_multiple (x, gen_rtx (REG, word_mode, regno),
                   1769:                                GEN_INT (nregs));
                   1770:       if (pat)
                   1771:        {
                   1772:          emit_insn (pat);
                   1773:          return;
                   1774:        }
                   1775:       else
                   1776:        delete_insns_since (last);
1.1       root     1777:     }
                   1778: #endif
                   1779: 
                   1780:   for (i = 0; i < nregs; i++)
                   1781:     {
                   1782:       rtx tem = operand_subword (x, i, 1, BLKmode);
                   1783: 
                   1784:       if (tem == 0)
                   1785:        abort ();
                   1786: 
                   1787:       emit_move_insn (tem, gen_rtx (REG, word_mode, regno + i));
                   1788:     }
                   1789: }
                   1790: 
1.1.1.7 ! root     1791: /* Add a USE expression for REG to the (possibly empty) list pointed
        !          1792:    to by CALL_FUSAGE.  REG must denote a hard register.  */
1.1       root     1793: 
                   1794: void
1.1.1.7 ! root     1795: use_reg (call_fusage, reg)
        !          1796:      rtx *call_fusage, reg;
1.1       root     1797: {
1.1.1.7 ! root     1798:   if (GET_CODE (reg) != REG
        !          1799:       || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
        !          1800:     abort();
1.1       root     1801: 
1.1.1.7 ! root     1802:   *call_fusage
        !          1803:     = gen_rtx (EXPR_LIST, VOIDmode,
        !          1804:               gen_rtx (USE, VOIDmode, reg), *call_fusage);
1.1       root     1805: }
1.1.1.4   root     1806: 
1.1.1.7 ! root     1807: /* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs,
        !          1808:    starting at REGNO.  All of these registers must be hard registers.  */
1.1.1.4   root     1809: 
1.1.1.7 ! root     1810: void
        !          1811: use_regs (call_fusage, regno, nregs)
        !          1812:      rtx *call_fusage;
        !          1813:      int regno;
        !          1814:      int nregs;
1.1.1.4   root     1815: {
1.1.1.7 ! root     1816:   int i;
1.1.1.4   root     1817: 
1.1.1.7 ! root     1818:   if (regno + nregs > FIRST_PSEUDO_REGISTER)
        !          1819:     abort ();
1.1.1.4   root     1820: 
1.1.1.7 ! root     1821:   for (i = 0; i < nregs; i++)
        !          1822:     use_reg (call_fusage, gen_rtx (REG, reg_raw_mode[regno + i], regno + i));
1.1.1.4   root     1823: }
1.1       root     1824: 
                   1825: /* Write zeros through the storage of OBJECT.
                   1826:    If OBJECT has BLKmode, SIZE is its length in bytes.  */
                   1827: 
                   1828: void
                   1829: clear_storage (object, size)
                   1830:      rtx object;
                   1831:      int size;
                   1832: {
                   1833:   if (GET_MODE (object) == BLKmode)
                   1834:     {
                   1835: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4   root     1836:       emit_library_call (memset_libfunc, 0,
1.1       root     1837:                         VOIDmode, 3,
                   1838:                         XEXP (object, 0), Pmode, const0_rtx, Pmode,
1.1.1.4   root     1839:                         GEN_INT (size), Pmode);
1.1       root     1840: #else
1.1.1.4   root     1841:       emit_library_call (bzero_libfunc, 0,
1.1       root     1842:                         VOIDmode, 2,
                   1843:                         XEXP (object, 0), Pmode,
1.1.1.4   root     1844:                         GEN_INT (size), Pmode);
1.1       root     1845: #endif
                   1846:     }
                   1847:   else
                   1848:     emit_move_insn (object, const0_rtx);
                   1849: }
                   1850: 
                   1851: /* Generate code to copy Y into X.
                   1852:    Both Y and X must have the same mode, except that
                   1853:    Y can be a constant with VOIDmode.
                   1854:    This mode cannot be BLKmode; use emit_block_move for that.
                   1855: 
                   1856:    Return the last instruction emitted.  */
                   1857: 
                   1858: rtx
                   1859: emit_move_insn (x, y)
                   1860:      rtx x, y;
                   1861: {
                   1862:   enum machine_mode mode = GET_MODE (x);
                   1863: 
                   1864:   x = protect_from_queue (x, 1);
                   1865:   y = protect_from_queue (y, 0);
                   1866: 
                   1867:   if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))
                   1868:     abort ();
                   1869: 
                   1870:   if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
                   1871:     y = force_const_mem (mode, y);
                   1872: 
                   1873:   /* If X or Y are memory references, verify that their addresses are valid
                   1874:      for the machine.  */
                   1875:   if (GET_CODE (x) == MEM
                   1876:       && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))
                   1877:           && ! push_operand (x, GET_MODE (x)))
                   1878:          || (flag_force_addr
                   1879:              && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
                   1880:     x = change_address (x, VOIDmode, XEXP (x, 0));
                   1881: 
                   1882:   if (GET_CODE (y) == MEM
                   1883:       && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
                   1884:          || (flag_force_addr
                   1885:              && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
                   1886:     y = change_address (y, VOIDmode, XEXP (y, 0));
                   1887: 
                   1888:   if (mode == BLKmode)
                   1889:     abort ();
                   1890: 
1.1.1.5   root     1891:   return emit_move_insn_1 (x, y);
                   1892: }
                   1893: 
                   1894: /* Low level part of emit_move_insn.
                   1895:    Called just like emit_move_insn, but assumes X and Y
                   1896:    are basically valid.  */
                   1897: 
                   1898: rtx
                   1899: emit_move_insn_1 (x, y)
                   1900:      rtx x, y;
                   1901: {
                   1902:   enum machine_mode mode = GET_MODE (x);
                   1903:   enum machine_mode submode;
                   1904:   enum mode_class class = GET_MODE_CLASS (mode);
                   1905:   int i;
                   1906: 
1.1       root     1907:   if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   1908:     return
                   1909:       emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
                   1910: 
1.1.1.5   root     1911:   /* Expand complex moves by moving real part and imag part, if possible.  */
1.1.1.4   root     1912:   else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
1.1.1.7 ! root     1913:           && BLKmode != (submode = mode_for_size ((GET_MODE_UNIT_SIZE (mode)
        !          1914:                                                    * BITS_PER_UNIT),
        !          1915:                                                   (class == MODE_COMPLEX_INT
        !          1916:                                                    ? MODE_INT : MODE_FLOAT),
        !          1917:                                                   0))
1.1.1.4   root     1918:           && (mov_optab->handlers[(int) submode].insn_code
                   1919:               != CODE_FOR_nothing))
                   1920:     {
                   1921:       /* Don't split destination if it is a stack push.  */
                   1922:       int stack = push_operand (x, GET_MODE (x));
1.1.1.7 ! root     1923:       rtx insns;
1.1.1.4   root     1924: 
                   1925:       /* If this is a stack, push the highpart first, so it
                   1926:         will be in the argument order.
                   1927: 
                   1928:         In that case, change_address is used only to convert
                   1929:         the mode, not to change the address.  */
1.1.1.6   root     1930:       if (stack)
                   1931:        {
                   1932:          /* Note that the real part always precedes the imag part in memory
                   1933:             regardless of machine's endianness.  */
                   1934: #ifdef STACK_GROWS_DOWNWARD
                   1935:          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
                   1936:                     (gen_rtx (MEM, submode, (XEXP (x, 0))),
                   1937:                      gen_imagpart (submode, y)));
                   1938:          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
                   1939:                     (gen_rtx (MEM, submode, (XEXP (x, 0))),
                   1940:                      gen_realpart (submode, y)));
                   1941: #else
                   1942:          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
                   1943:                     (gen_rtx (MEM, submode, (XEXP (x, 0))),
                   1944:                      gen_realpart (submode, y)));
                   1945:          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
                   1946:                     (gen_rtx (MEM, submode, (XEXP (x, 0))),
                   1947:                      gen_imagpart (submode, y)));
                   1948: #endif
                   1949:        }
                   1950:       else
                   1951:        {
                   1952:          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
1.1.1.7 ! root     1953:                     (gen_realpart (submode, x), gen_realpart (submode, y)));
1.1.1.6   root     1954:          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
1.1.1.7 ! root     1955:                     (gen_imagpart (submode, x), gen_imagpart (submode, y)));
1.1.1.6   root     1956:        }
1.1.1.4   root     1957: 
                   1958:       return get_last_insn ();
                   1959:     }
                   1960: 
1.1       root     1961:   /* This will handle any multi-word mode that lacks a move_insn pattern.
                   1962:      However, you will get better code if you define such patterns,
                   1963:      even if they must turn into multiple assembler instructions.  */
1.1.1.4   root     1964:   else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
1.1       root     1965:     {
                   1966:       rtx last_insn = 0;
1.1.1.7 ! root     1967:       rtx insns;
        !          1968:       
        !          1969: #ifdef PUSH_ROUNDING
1.1       root     1970: 
1.1.1.7 ! root     1971:       /* If X is a push on the stack, do the push now and replace
        !          1972:         X with a reference to the stack pointer.  */
        !          1973:       if (push_operand (x, GET_MODE (x)))
        !          1974:        {
        !          1975:          anti_adjust_stack (GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
        !          1976:          x = change_address (x, VOIDmode, stack_pointer_rtx);
        !          1977:        }
        !          1978: #endif
        !          1979:                             
1.1       root     1980:       for (i = 0;
                   1981:           i < (GET_MODE_SIZE (mode)  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
                   1982:           i++)
                   1983:        {
                   1984:          rtx xpart = operand_subword (x, i, 1, mode);
                   1985:          rtx ypart = operand_subword (y, i, 1, mode);
                   1986: 
                   1987:          /* If we can't get a part of Y, put Y into memory if it is a
                   1988:             constant.  Otherwise, force it into a register.  If we still
                   1989:             can't get a part of Y, abort.  */
                   1990:          if (ypart == 0 && CONSTANT_P (y))
                   1991:            {
                   1992:              y = force_const_mem (mode, y);
                   1993:              ypart = operand_subword (y, i, 1, mode);
                   1994:            }
                   1995:          else if (ypart == 0)
                   1996:            ypart = operand_subword_force (y, i, mode);
                   1997: 
                   1998:          if (xpart == 0 || ypart == 0)
                   1999:            abort ();
                   2000: 
                   2001:          last_insn = emit_move_insn (xpart, ypart);
                   2002:        }
1.1.1.4   root     2003: 
1.1       root     2004:       return last_insn;
                   2005:     }
                   2006:   else
                   2007:     abort ();
                   2008: }
                   2009: 
                   2010: /* Pushing data onto the stack.  */
                   2011: 
                   2012: /* Push a block of length SIZE (perhaps variable)
                   2013:    and return an rtx to address the beginning of the block.
                   2014:    Note that it is not possible for the value returned to be a QUEUED.
                   2015:    The value may be virtual_outgoing_args_rtx.
                   2016: 
                   2017:    EXTRA is the number of bytes of padding to push in addition to SIZE.
                   2018:    BELOW nonzero means this padding comes at low addresses;
                   2019:    otherwise, the padding comes at high addresses.  */
                   2020: 
                   2021: rtx
                   2022: push_block (size, extra, below)
                   2023:      rtx size;
                   2024:      int extra, below;
                   2025: {
                   2026:   register rtx temp;
                   2027:   if (CONSTANT_P (size))
                   2028:     anti_adjust_stack (plus_constant (size, extra));
                   2029:   else if (GET_CODE (size) == REG && extra == 0)
                   2030:     anti_adjust_stack (size);
                   2031:   else
                   2032:     {
                   2033:       rtx temp = copy_to_mode_reg (Pmode, size);
                   2034:       if (extra != 0)
1.1.1.4   root     2035:        temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
1.1       root     2036:                             temp, 0, OPTAB_LIB_WIDEN);
                   2037:       anti_adjust_stack (temp);
                   2038:     }
                   2039: 
                   2040: #ifdef STACK_GROWS_DOWNWARD
                   2041:   temp = virtual_outgoing_args_rtx;
                   2042:   if (extra != 0 && below)
                   2043:     temp = plus_constant (temp, extra);
                   2044: #else
                   2045:   if (GET_CODE (size) == CONST_INT)
                   2046:     temp = plus_constant (virtual_outgoing_args_rtx,
                   2047:                          - INTVAL (size) - (below ? 0 : extra));
                   2048:   else if (extra != 0 && !below)
                   2049:     temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx,
                   2050:                    negate_rtx (Pmode, plus_constant (size, extra)));
                   2051:   else
                   2052:     temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx,
                   2053:                    negate_rtx (Pmode, size));
                   2054: #endif
                   2055: 
                   2056:   return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
                   2057: }
                   2058: 
1.1.1.4   root     2059: rtx
1.1       root     2060: gen_push_operand ()
                   2061: {
                   2062:   return gen_rtx (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
                   2063: }
                   2064: 
                   2065: /* Generate code to push X onto the stack, assuming it has mode MODE and
                   2066:    type TYPE.
                   2067:    MODE is redundant except when X is a CONST_INT (since they don't
                   2068:    carry mode info).
                   2069:    SIZE is an rtx for the size of data to be copied (in bytes),
                   2070:    needed only if X is BLKmode.
                   2071: 
                   2072:    ALIGN (in bytes) is maximum alignment we can assume.
                   2073: 
1.1.1.5   root     2074:    If PARTIAL and REG are both nonzero, then copy that many of the first
                   2075:    words of X into registers starting with REG, and push the rest of X.
1.1       root     2076:    The amount of space pushed is decreased by PARTIAL words,
                   2077:    rounded *down* to a multiple of PARM_BOUNDARY.
                   2078:    REG must be a hard register in this case.
1.1.1.5   root     2079:    If REG is zero but PARTIAL is not, take any all others actions for an
                   2080:    argument partially in registers, but do not actually load any
                   2081:    registers.
1.1       root     2082: 
                   2083:    EXTRA is the amount in bytes of extra space to leave next to this arg.
1.1.1.3   root     2084:    This is ignored if an argument block has already been allocated.
1.1       root     2085: 
                   2086:    On a machine that lacks real push insns, ARGS_ADDR is the address of
                   2087:    the bottom of the argument block for this call.  We use indexing off there
                   2088:    to store the arg.  On machines with push insns, ARGS_ADDR is 0 when a
                   2089:    argument block has not been preallocated.
                   2090: 
                   2091:    ARGS_SO_FAR is the size of args previously pushed for this call.  */
                   2092: 
                   2093: void
                   2094: emit_push_insn (x, mode, type, size, align, partial, reg, extra,
                   2095:                args_addr, args_so_far)
                   2096:      register rtx x;
                   2097:      enum machine_mode mode;
                   2098:      tree type;
                   2099:      rtx size;
                   2100:      int align;
                   2101:      int partial;
                   2102:      rtx reg;
                   2103:      int extra;
                   2104:      rtx args_addr;
                   2105:      rtx args_so_far;
                   2106: {
                   2107:   rtx xinner;
                   2108:   enum direction stack_direction
                   2109: #ifdef STACK_GROWS_DOWNWARD
                   2110:     = downward;
                   2111: #else
                   2112:     = upward;
                   2113: #endif
                   2114: 
                   2115:   /* Decide where to pad the argument: `downward' for below,
                   2116:      `upward' for above, or `none' for don't pad it.
                   2117:      Default is below for small data on big-endian machines; else above.  */
                   2118:   enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
                   2119: 
                   2120:   /* Invert direction if stack is post-update.  */
                   2121:   if (STACK_PUSH_CODE == POST_INC || STACK_PUSH_CODE == POST_DEC)
                   2122:     if (where_pad != none)
                   2123:       where_pad = (where_pad == downward ? upward : downward);
                   2124: 
                   2125:   xinner = x = protect_from_queue (x, 0);
                   2126: 
                   2127:   if (mode == BLKmode)
                   2128:     {
                   2129:       /* Copy a block into the stack, entirely or partially.  */
                   2130: 
                   2131:       register rtx temp;
                   2132:       int used = partial * UNITS_PER_WORD;
                   2133:       int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
                   2134:       int skip;
                   2135:       
                   2136:       if (size == 0)
                   2137:        abort ();
                   2138: 
                   2139:       used -= offset;
                   2140: 
                   2141:       /* USED is now the # of bytes we need not copy to the stack
                   2142:         because registers will take care of them.  */
                   2143: 
                   2144:       if (partial != 0)
                   2145:        xinner = change_address (xinner, BLKmode,
                   2146:                                 plus_constant (XEXP (xinner, 0), used));
                   2147: 
                   2148:       /* If the partial register-part of the arg counts in its stack size,
                   2149:         skip the part of stack space corresponding to the registers.
                   2150:         Otherwise, start copying to the beginning of the stack space,
                   2151:         by setting SKIP to 0.  */
                   2152: #ifndef REG_PARM_STACK_SPACE
                   2153:       skip = 0;
                   2154: #else
                   2155:       skip = used;
                   2156: #endif
                   2157: 
                   2158: #ifdef PUSH_ROUNDING
                   2159:       /* Do it with several push insns if that doesn't take lots of insns
                   2160:         and if there is no difficulty with push insns that skip bytes
                   2161:         on the stack for alignment purposes.  */
                   2162:       if (args_addr == 0
                   2163:          && GET_CODE (size) == CONST_INT
                   2164:          && skip == 0
                   2165:          && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align)
                   2166:              < MOVE_RATIO)
                   2167:          /* Here we avoid the case of a structure whose weak alignment
                   2168:             forces many pushes of a small amount of data,
                   2169:             and such small pushes do rounding that causes trouble.  */
1.1.1.2   root     2170:          && ((! STRICT_ALIGNMENT && ! SLOW_UNALIGNED_ACCESS)
                   2171:              || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT
1.1       root     2172:              || PUSH_ROUNDING (align) == align)
                   2173:          && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
                   2174:        {
                   2175:          /* Push padding now if padding above and stack grows down,
                   2176:             or if padding below and stack grows up.
                   2177:             But if space already allocated, this has already been done.  */
                   2178:          if (extra && args_addr == 0
                   2179:              && where_pad != none && where_pad != stack_direction)
1.1.1.4   root     2180:            anti_adjust_stack (GEN_INT (extra));
1.1       root     2181: 
                   2182:          move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner,
                   2183:                          INTVAL (size) - used, align);
                   2184:        }
                   2185:       else
                   2186: #endif /* PUSH_ROUNDING */
                   2187:        {
                   2188:          /* Otherwise make space on the stack and copy the data
                   2189:             to the address of that space.  */
                   2190: 
                   2191:          /* Deduct words put into registers from the size we must copy.  */
                   2192:          if (partial != 0)
                   2193:            {
                   2194:              if (GET_CODE (size) == CONST_INT)
1.1.1.4   root     2195:                size = GEN_INT (INTVAL (size) - used);
1.1       root     2196:              else
                   2197:                size = expand_binop (GET_MODE (size), sub_optab, size,
1.1.1.4   root     2198:                                     GEN_INT (used), NULL_RTX, 0,
                   2199:                                     OPTAB_LIB_WIDEN);
1.1       root     2200:            }
                   2201: 
                   2202:          /* Get the address of the stack space.
                   2203:             In this case, we do not deal with EXTRA separately.
                   2204:             A single stack adjust will do.  */
                   2205:          if (! args_addr)
                   2206:            {
                   2207:              temp = push_block (size, extra, where_pad == downward);
                   2208:              extra = 0;
                   2209:            }
                   2210:          else if (GET_CODE (args_so_far) == CONST_INT)
                   2211:            temp = memory_address (BLKmode,
                   2212:                                   plus_constant (args_addr,
                   2213:                                                  skip + INTVAL (args_so_far)));
                   2214:          else
                   2215:            temp = memory_address (BLKmode,
                   2216:                                   plus_constant (gen_rtx (PLUS, Pmode,
                   2217:                                                           args_addr, args_so_far),
                   2218:                                                  skip));
                   2219: 
                   2220:          /* TEMP is the address of the block.  Copy the data there.  */
                   2221:          if (GET_CODE (size) == CONST_INT
                   2222:              && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
                   2223:                  < MOVE_RATIO))
                   2224:            {
                   2225:              move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner,
                   2226:                              INTVAL (size), align);
                   2227:              goto ret;
                   2228:            }
                   2229:          /* Try the most limited insn first, because there's no point
                   2230:             including more than one in the machine description unless
                   2231:             the more limited one has some advantage.  */
                   2232: #ifdef HAVE_movstrqi
                   2233:          if (HAVE_movstrqi
                   2234:              && GET_CODE (size) == CONST_INT
                   2235:              && ((unsigned) INTVAL (size)
                   2236:                  < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
                   2237:            {
1.1.1.5   root     2238:              rtx pat = gen_movstrqi (gen_rtx (MEM, BLKmode, temp),
                   2239:                                      xinner, size, GEN_INT (align));
                   2240:              if (pat != 0)
                   2241:                {
                   2242:                  emit_insn (pat);
                   2243:                  goto ret;
                   2244:                }
1.1       root     2245:            }
                   2246: #endif
                   2247: #ifdef HAVE_movstrhi
                   2248:          if (HAVE_movstrhi
                   2249:              && GET_CODE (size) == CONST_INT
                   2250:              && ((unsigned) INTVAL (size)
                   2251:                  < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
                   2252:            {
1.1.1.5   root     2253:              rtx pat = gen_movstrhi (gen_rtx (MEM, BLKmode, temp),
                   2254:                                      xinner, size, GEN_INT (align));
                   2255:              if (pat != 0)
                   2256:                {
                   2257:                  emit_insn (pat);
                   2258:                  goto ret;
                   2259:                }
1.1       root     2260:            }
                   2261: #endif
                   2262: #ifdef HAVE_movstrsi
                   2263:          if (HAVE_movstrsi)
                   2264:            {
1.1.1.5   root     2265:              rtx pat = gen_movstrsi (gen_rtx (MEM, BLKmode, temp),
                   2266:                                      xinner, size, GEN_INT (align));
                   2267:              if (pat != 0)
                   2268:                {
                   2269:                  emit_insn (pat);
                   2270:                  goto ret;
                   2271:                }
1.1       root     2272:            }
                   2273: #endif
                   2274: #ifdef HAVE_movstrdi
                   2275:          if (HAVE_movstrdi)
                   2276:            {
1.1.1.5   root     2277:              rtx pat = gen_movstrdi (gen_rtx (MEM, BLKmode, temp),
                   2278:                                      xinner, size, GEN_INT (align));
                   2279:              if (pat != 0)
                   2280:                {
                   2281:                  emit_insn (pat);
                   2282:                  goto ret;
                   2283:                }
1.1       root     2284:            }
                   2285: #endif
                   2286: 
                   2287: #ifndef ACCUMULATE_OUTGOING_ARGS
                   2288:          /* If the source is referenced relative to the stack pointer,
                   2289:             copy it to another register to stabilize it.  We do not need
                   2290:             to do this if we know that we won't be changing sp.  */
                   2291: 
                   2292:          if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
                   2293:              || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
                   2294:            temp = copy_to_reg (temp);
                   2295: #endif
                   2296: 
                   2297:          /* Make inhibit_defer_pop nonzero around the library call
                   2298:             to force it to pop the bcopy-arguments right away.  */
                   2299:          NO_DEFER_POP;
                   2300: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4   root     2301:          emit_library_call (memcpy_libfunc, 0,
1.1       root     2302:                             VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
1.1.1.5   root     2303:                             convert_to_mode (TYPE_MODE (sizetype),
                   2304:                                              size, TREE_UNSIGNED (sizetype)),
                   2305:                             TYPE_MODE (sizetype));
1.1       root     2306: #else
1.1.1.4   root     2307:          emit_library_call (bcopy_libfunc, 0,
1.1       root     2308:                             VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
1.1.1.5   root     2309:                             convert_to_mode (TYPE_MODE (sizetype),
                   2310:                                              size, TREE_UNSIGNED (sizetype)),
                   2311:                             TYPE_MODE (sizetype));
1.1       root     2312: #endif
                   2313:          OK_DEFER_POP;
                   2314:        }
                   2315:     }
                   2316:   else if (partial > 0)
                   2317:     {
                   2318:       /* Scalar partly in registers.  */
                   2319: 
                   2320:       int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
                   2321:       int i;
                   2322:       int not_stack;
                   2323:       /* # words of start of argument
                   2324:         that we must make space for but need not store.  */
                   2325:       int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
                   2326:       int args_offset = INTVAL (args_so_far);
                   2327:       int skip;
                   2328: 
                   2329:       /* Push padding now if padding above and stack grows down,
                   2330:         or if padding below and stack grows up.
                   2331:         But if space already allocated, this has already been done.  */
                   2332:       if (extra && args_addr == 0
                   2333:          && where_pad != none && where_pad != stack_direction)
1.1.1.4   root     2334:        anti_adjust_stack (GEN_INT (extra));
1.1       root     2335: 
                   2336:       /* If we make space by pushing it, we might as well push
                   2337:         the real data.  Otherwise, we can leave OFFSET nonzero
                   2338:         and leave the space uninitialized.  */
                   2339:       if (args_addr == 0)
                   2340:        offset = 0;
                   2341: 
                   2342:       /* Now NOT_STACK gets the number of words that we don't need to
                   2343:         allocate on the stack.  */
                   2344:       not_stack = partial - offset;
                   2345: 
                   2346:       /* If the partial register-part of the arg counts in its stack size,
                   2347:         skip the part of stack space corresponding to the registers.
                   2348:         Otherwise, start copying to the beginning of the stack space,
                   2349:         by setting SKIP to 0.  */
                   2350: #ifndef REG_PARM_STACK_SPACE
                   2351:       skip = 0;
                   2352: #else
                   2353:       skip = not_stack;
                   2354: #endif
                   2355: 
                   2356:       if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
                   2357:        x = validize_mem (force_const_mem (mode, x));
                   2358: 
                   2359:       /* If X is a hard register in a non-integer mode, copy it into a pseudo;
                   2360:         SUBREGs of such registers are not allowed.  */
                   2361:       if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER
                   2362:           && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT))
                   2363:        x = copy_to_reg (x);
                   2364: 
                   2365:       /* Loop over all the words allocated on the stack for this arg.  */
                   2366:       /* We can do it by words, because any scalar bigger than a word
                   2367:         has a size a multiple of a word.  */
                   2368: #ifndef PUSH_ARGS_REVERSED
                   2369:       for (i = not_stack; i < size; i++)
                   2370: #else
                   2371:       for (i = size - 1; i >= not_stack; i--)
                   2372: #endif
                   2373:        if (i >= not_stack + offset)
                   2374:          emit_push_insn (operand_subword_force (x, i, mode),
1.1.1.4   root     2375:                          word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
                   2376:                          0, args_addr,
                   2377:                          GEN_INT (args_offset + ((i - not_stack + skip)
1.1       root     2378:                                                  * UNITS_PER_WORD)));
                   2379:     }
                   2380:   else
                   2381:     {
                   2382:       rtx addr;
                   2383: 
                   2384:       /* Push padding now if padding above and stack grows down,
                   2385:         or if padding below and stack grows up.
                   2386:         But if space already allocated, this has already been done.  */
                   2387:       if (extra && args_addr == 0
                   2388:          && where_pad != none && where_pad != stack_direction)
1.1.1.4   root     2389:        anti_adjust_stack (GEN_INT (extra));
1.1       root     2390: 
                   2391: #ifdef PUSH_ROUNDING
                   2392:       if (args_addr == 0)
                   2393:        addr = gen_push_operand ();
                   2394:       else
                   2395: #endif
                   2396:        if (GET_CODE (args_so_far) == CONST_INT)
                   2397:          addr
                   2398:            = memory_address (mode,
                   2399:                              plus_constant (args_addr, INTVAL (args_so_far)));
                   2400:       else
                   2401:        addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr,
                   2402:                                              args_so_far));
                   2403: 
                   2404:       emit_move_insn (gen_rtx (MEM, mode, addr), x);
                   2405:     }
                   2406: 
                   2407:  ret:
                   2408:   /* If part should go in registers, copy that part
                   2409:      into the appropriate registers.  Do this now, at the end,
                   2410:      since mem-to-mem copies above may do function calls.  */
1.1.1.5   root     2411:   if (partial > 0 && reg != 0)
1.1       root     2412:     move_block_to_reg (REGNO (reg), x, partial, mode);
                   2413: 
                   2414:   if (extra && args_addr == 0 && where_pad == stack_direction)
1.1.1.4   root     2415:     anti_adjust_stack (GEN_INT (extra));
1.1       root     2416: }
                   2417: 
                   2418: /* Expand an assignment that stores the value of FROM into TO.
                   2419:    If WANT_VALUE is nonzero, return an rtx for the value of TO.
1.1.1.6   root     2420:    (This may contain a QUEUED rtx;
                   2421:    if the value is constant, this rtx is a constant.)
                   2422:    Otherwise, the returned value is NULL_RTX.
1.1       root     2423: 
                   2424:    SUGGEST_REG is no longer actually used.
                   2425:    It used to mean, copy the value through a register
                   2426:    and return that register, if that is possible.
1.1.1.6   root     2427:    We now use WANT_VALUE to decide whether to do this.  */
1.1       root     2428: 
                   2429: rtx
                   2430: expand_assignment (to, from, want_value, suggest_reg)
                   2431:      tree to, from;
                   2432:      int want_value;
                   2433:      int suggest_reg;
                   2434: {
                   2435:   register rtx to_rtx = 0;
                   2436:   rtx result;
                   2437: 
                   2438:   /* Don't crash if the lhs of the assignment was erroneous.  */
                   2439: 
                   2440:   if (TREE_CODE (to) == ERROR_MARK)
1.1.1.6   root     2441:     {
                   2442:       result = expand_expr (from, NULL_RTX, VOIDmode, 0);
                   2443:       return want_value ? result : NULL_RTX;
                   2444:     }
                   2445: 
                   2446:   if (output_bytecode)
                   2447:     {
                   2448:       tree dest_innermost;
                   2449: 
                   2450:       bc_expand_expr (from);
                   2451:       bc_emit_instruction (duplicate);
                   2452: 
                   2453:       dest_innermost = bc_expand_address (to);
                   2454: 
                   2455:       /* Can't deduce from TYPE that we're dealing with a bitfield, so
                   2456:         take care of it here. */
                   2457: 
                   2458:       bc_store_memory (TREE_TYPE (to), dest_innermost);
                   2459:       return NULL;
                   2460:     }
1.1       root     2461: 
                   2462:   /* Assignment of a structure component needs special treatment
                   2463:      if the structure component's rtx is not simply a MEM.
1.1.1.7 ! root     2464:      Assignment of an array element at a constant index, and assignment of
        !          2465:      an array element in an unaligned packed structure field, has the same
        !          2466:      problem.  */
1.1       root     2467: 
                   2468:   if (TREE_CODE (to) == COMPONENT_REF
                   2469:       || TREE_CODE (to) == BIT_FIELD_REF
                   2470:       || (TREE_CODE (to) == ARRAY_REF
1.1.1.7 ! root     2471:          && ((TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST
        !          2472:               && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST)
        !          2473:              || (STRICT_ALIGNMENT && get_inner_unaligned_p (to)))))
1.1       root     2474:     {
                   2475:       enum machine_mode mode1;
                   2476:       int bitsize;
                   2477:       int bitpos;
1.1.1.3   root     2478:       tree offset;
1.1       root     2479:       int unsignedp;
                   2480:       int volatilep = 0;
1.1.1.6   root     2481:       tree tem;
                   2482:       int alignment;
                   2483: 
                   2484:       push_temp_slots ();
                   2485:       tem = get_inner_reference (to, &bitsize, &bitpos, &offset,
1.1       root     2486:                                      &mode1, &unsignedp, &volatilep);
                   2487: 
                   2488:       /* If we are going to use store_bit_field and extract_bit_field,
                   2489:         make sure to_rtx will be safe for multiple use.  */
                   2490: 
                   2491:       if (mode1 == VOIDmode && want_value)
                   2492:        tem = stabilize_reference (tem);
                   2493: 
1.1.1.6   root     2494:       alignment = TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT;
1.1.1.4   root     2495:       to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
1.1.1.3   root     2496:       if (offset != 0)
                   2497:        {
1.1.1.4   root     2498:          rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
1.1.1.3   root     2499: 
                   2500:          if (GET_CODE (to_rtx) != MEM)
                   2501:            abort ();
                   2502:          to_rtx = change_address (to_rtx, VOIDmode,
                   2503:                                   gen_rtx (PLUS, Pmode, XEXP (to_rtx, 0),
                   2504:                                            force_reg (Pmode, offset_rtx)));
1.1.1.6   root     2505:          /* If we have a variable offset, the known alignment
                   2506:             is only that of the innermost structure containing the field.
                   2507:             (Actually, we could sometimes do better by using the
                   2508:             align of an element of the innermost array, but no need.)  */
                   2509:          if (TREE_CODE (to) == COMPONENT_REF
                   2510:              || TREE_CODE (to) == BIT_FIELD_REF)
                   2511:            alignment
                   2512:              = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (to, 0))) / BITS_PER_UNIT;
1.1.1.3   root     2513:        }
1.1       root     2514:       if (volatilep)
                   2515:        {
                   2516:          if (GET_CODE (to_rtx) == MEM)
                   2517:            MEM_VOLATILE_P (to_rtx) = 1;
                   2518: #if 0  /* This was turned off because, when a field is volatile
                   2519:          in an object which is not volatile, the object may be in a register,
                   2520:          and then we would abort over here.  */
                   2521:          else
                   2522:            abort ();
                   2523: #endif
                   2524:        }
                   2525: 
                   2526:       result = store_field (to_rtx, bitsize, bitpos, mode1, from,
                   2527:                            (want_value
                   2528:                             /* Spurious cast makes HPUX compiler happy.  */
                   2529:                             ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to))
                   2530:                             : VOIDmode),
                   2531:                            unsignedp,
                   2532:                            /* Required alignment of containing datum.  */
1.1.1.6   root     2533:                            alignment,
1.1       root     2534:                            int_size_in_bytes (TREE_TYPE (tem)));
                   2535:       preserve_temp_slots (result);
                   2536:       free_temp_slots ();
1.1.1.6   root     2537:       pop_temp_slots ();
1.1       root     2538: 
1.1.1.6   root     2539:       /* If the value is meaningful, convert RESULT to the proper mode.
                   2540:         Otherwise, return nothing.  */
                   2541:       return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
                   2542:                                          TYPE_MODE (TREE_TYPE (from)),
                   2543:                                          result,
                   2544:                                          TREE_UNSIGNED (TREE_TYPE (to)))
                   2545:              : NULL_RTX);
                   2546:     }
                   2547: 
                   2548:   /* If the rhs is a function call and its value is not an aggregate,
                   2549:      call the function before we start to compute the lhs.
                   2550:      This is needed for correct code for cases such as
                   2551:      val = setjmp (buf) on machines where reference to val
                   2552:      requires loading up part of an address in a separate insn.
                   2553: 
                   2554:      Don't do this if TO is a VAR_DECL whose DECL_RTL is REG since it might be
                   2555:      a promoted variable where the zero- or sign- extension needs to be done.
                   2556:      Handling this in the normal way is safe because no computation is done
                   2557:      before the call.  */
                   2558:   if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from)
                   2559:       && ! (TREE_CODE (to) == VAR_DECL && GET_CODE (DECL_RTL (to)) == REG))
                   2560:     {
                   2561:       rtx value;
                   2562: 
                   2563:       push_temp_slots ();
                   2564:       value = expand_expr (from, NULL_RTX, VOIDmode, 0);
                   2565:       if (to_rtx == 0)
                   2566:        to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0);
                   2567:       emit_move_insn (to_rtx, value);
                   2568:       preserve_temp_slots (to_rtx);
                   2569:       free_temp_slots ();
                   2570:       pop_temp_slots ();
                   2571:       return want_value ? to_rtx : NULL_RTX;
1.1       root     2572:     }
                   2573: 
                   2574:   /* Ordinary treatment.  Expand TO to get a REG or MEM rtx.
                   2575:      Don't re-expand if it was expanded already (in COMPONENT_REF case).  */
                   2576: 
                   2577:   if (to_rtx == 0)
1.1.1.4   root     2578:     to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0);
1.1       root     2579: 
1.1.1.5   root     2580:   /* Don't move directly into a return register.  */
                   2581:   if (TREE_CODE (to) == RESULT_DECL && GET_CODE (to_rtx) == REG)
                   2582:     {
1.1.1.6   root     2583:       rtx temp;
                   2584: 
                   2585:       push_temp_slots ();
                   2586:       temp = expand_expr (from, 0, GET_MODE (to_rtx), 0);
1.1.1.5   root     2587:       emit_move_insn (to_rtx, temp);
                   2588:       preserve_temp_slots (to_rtx);
                   2589:       free_temp_slots ();
1.1.1.6   root     2590:       pop_temp_slots ();
                   2591:       return want_value ? to_rtx : NULL_RTX;
1.1.1.5   root     2592:     }
                   2593: 
1.1       root     2594:   /* In case we are returning the contents of an object which overlaps
                   2595:      the place the value is being stored, use a safe function when copying
                   2596:      a value through a pointer into a structure value return block.  */
                   2597:   if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
                   2598:       && current_function_returns_struct
                   2599:       && !current_function_returns_pcc_struct)
                   2600:     {
1.1.1.6   root     2601:       rtx from_rtx, size;
                   2602: 
                   2603:       push_temp_slots ();
                   2604:       size = expr_size (from);
                   2605:       from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
1.1       root     2606: 
                   2607: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4   root     2608:       emit_library_call (memcpy_libfunc, 0,
1.1       root     2609:                         VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
                   2610:                         XEXP (from_rtx, 0), Pmode,
1.1.1.5   root     2611:                         convert_to_mode (TYPE_MODE (sizetype),
                   2612:                                          size, TREE_UNSIGNED (sizetype)),
                   2613:                         TYPE_MODE (sizetype));
1.1       root     2614: #else
1.1.1.4   root     2615:       emit_library_call (bcopy_libfunc, 0,
1.1       root     2616:                         VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
                   2617:                         XEXP (to_rtx, 0), Pmode,
1.1.1.5   root     2618:                         convert_to_mode (TYPE_MODE (sizetype),
                   2619:                                          size, TREE_UNSIGNED (sizetype)),
                   2620:                         TYPE_MODE (sizetype));
1.1       root     2621: #endif
                   2622: 
                   2623:       preserve_temp_slots (to_rtx);
                   2624:       free_temp_slots ();
1.1.1.6   root     2625:       pop_temp_slots ();
                   2626:       return want_value ? to_rtx : NULL_RTX;
1.1       root     2627:     }
                   2628: 
                   2629:   /* Compute FROM and store the value in the rtx we got.  */
                   2630: 
1.1.1.6   root     2631:   push_temp_slots ();
1.1       root     2632:   result = store_expr (from, to_rtx, want_value);
                   2633:   preserve_temp_slots (result);
                   2634:   free_temp_slots ();
1.1.1.6   root     2635:   pop_temp_slots ();
                   2636:   return want_value ? result : NULL_RTX;
1.1       root     2637: }
                   2638: 
                   2639: /* Generate code for computing expression EXP,
                   2640:    and storing the value into TARGET.
                   2641:    TARGET may contain a QUEUED rtx.
                   2642: 
1.1.1.6   root     2643:    If WANT_VALUE is nonzero, return a copy of the value
                   2644:    not in TARGET, so that we can be sure to use the proper
                   2645:    value in a containing expression even if TARGET has something
                   2646:    else stored in it.  If possible, we copy the value through a pseudo
                   2647:    and return that pseudo.  Or, if the value is constant, we try to
                   2648:    return the constant.  In some cases, we return a pseudo
                   2649:    copied *from* TARGET.
                   2650: 
                   2651:    If the mode is BLKmode then we may return TARGET itself.
                   2652:    It turns out that in BLKmode it doesn't cause a problem.
                   2653:    because C has no operators that could combine two different
                   2654:    assignments into the same BLKmode object with different values
                   2655:    with no sequence point.  Will other languages need this to
                   2656:    be more thorough?
                   2657: 
                   2658:    If WANT_VALUE is 0, we return NULL, to make sure
                   2659:    to catch quickly any cases where the caller uses the value
                   2660:    and fails to set WANT_VALUE.  */
1.1       root     2661: 
                   2662: rtx
1.1.1.6   root     2663: store_expr (exp, target, want_value)
1.1       root     2664:      register tree exp;
                   2665:      register rtx target;
1.1.1.6   root     2666:      int want_value;
1.1       root     2667: {
                   2668:   register rtx temp;
                   2669:   int dont_return_target = 0;
                   2670: 
                   2671:   if (TREE_CODE (exp) == COMPOUND_EXPR)
                   2672:     {
                   2673:       /* Perform first part of compound expression, then assign from second
                   2674:         part.  */
                   2675:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
                   2676:       emit_queue ();
1.1.1.6   root     2677:       return store_expr (TREE_OPERAND (exp, 1), target, want_value);
1.1       root     2678:     }
                   2679:   else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
                   2680:     {
                   2681:       /* For conditional expression, get safe form of the target.  Then
                   2682:         test the condition, doing the appropriate assignment on either
                   2683:         side.  This avoids the creation of unnecessary temporaries.
                   2684:         For non-BLKmode, it is more efficient not to do this.  */
                   2685: 
                   2686:       rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
                   2687: 
                   2688:       emit_queue ();
                   2689:       target = protect_from_queue (target, 1);
                   2690: 
                   2691:       NO_DEFER_POP;
                   2692:       jumpifnot (TREE_OPERAND (exp, 0), lab1);
1.1.1.6   root     2693:       store_expr (TREE_OPERAND (exp, 1), target, 0);
1.1       root     2694:       emit_queue ();
                   2695:       emit_jump_insn (gen_jump (lab2));
                   2696:       emit_barrier ();
                   2697:       emit_label (lab1);
1.1.1.6   root     2698:       store_expr (TREE_OPERAND (exp, 2), target, 0);
1.1       root     2699:       emit_queue ();
                   2700:       emit_label (lab2);
                   2701:       OK_DEFER_POP;
1.1.1.6   root     2702:       return want_value ? target : NULL_RTX;
1.1       root     2703:     }
1.1.1.6   root     2704:   else if (want_value && GET_CODE (target) == MEM && ! MEM_VOLATILE_P (target)
1.1       root     2705:           && GET_MODE (target) != BLKmode)
                   2706:     /* If target is in memory and caller wants value in a register instead,
                   2707:        arrange that.  Pass TARGET as target for expand_expr so that,
1.1.1.6   root     2708:        if EXP is another assignment, WANT_VALUE will be nonzero for it.
                   2709:        We know expand_expr will not use the target in that case.
                   2710:        Don't do this if TARGET is volatile because we are supposed
                   2711:        to write it and then read it.  */
1.1       root     2712:     {
1.1.1.4   root     2713:       temp = expand_expr (exp, cse_not_expected ? NULL_RTX : target,
1.1       root     2714:                          GET_MODE (target), 0);
                   2715:       if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
                   2716:        temp = copy_to_reg (temp);
                   2717:       dont_return_target = 1;
                   2718:     }
                   2719:   else if (queued_subexp_p (target))
1.1.1.6   root     2720:     /* If target contains a postincrement, let's not risk
                   2721:        using it as the place to generate the rhs.  */
1.1       root     2722:     {
                   2723:       if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode)
                   2724:        {
                   2725:          /* Expand EXP into a new pseudo.  */
                   2726:          temp = gen_reg_rtx (GET_MODE (target));
                   2727:          temp = expand_expr (exp, temp, GET_MODE (target), 0);
                   2728:        }
                   2729:       else
1.1.1.4   root     2730:        temp = expand_expr (exp, NULL_RTX, GET_MODE (target), 0);
1.1.1.6   root     2731: 
                   2732:       /* If target is volatile, ANSI requires accessing the value
                   2733:         *from* the target, if it is accessed.  So make that happen.
                   2734:         In no case return the target itself.  */
                   2735:       if (! MEM_VOLATILE_P (target) && want_value)
                   2736:        dont_return_target = 1;
1.1       root     2737:     }
1.1.1.4   root     2738:   else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
                   2739:     /* If this is an scalar in a register that is stored in a wider mode
                   2740:        than the declared mode, compute the result into its declared mode
                   2741:        and then convert to the wider mode.  Our value is the computed
                   2742:        expression.  */
                   2743:     {
                   2744:       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
1.1.1.6   root     2745: 
1.1.1.7 ! root     2746:       /* If TEMP is a volatile MEM and we want a result value, make
        !          2747:         the access now so it gets done only once.  */
        !          2748:       if (GET_CODE (temp) == MEM && MEM_VOLATILE_P (temp))
        !          2749:        temp = copy_to_reg (temp);
        !          2750: 
1.1.1.6   root     2751:       /* If TEMP is a VOIDmode constant, use convert_modes to make
                   2752:         sure that we properly convert it.  */
                   2753:       if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)
                   2754:        temp = convert_modes (GET_MODE (SUBREG_REG (target)),
                   2755:                              TYPE_MODE (TREE_TYPE (exp)), temp,
                   2756:                              SUBREG_PROMOTED_UNSIGNED_P (target));
                   2757: 
1.1.1.4   root     2758:       convert_move (SUBREG_REG (target), temp,
                   2759:                    SUBREG_PROMOTED_UNSIGNED_P (target));
1.1.1.6   root     2760:       return want_value ? temp : NULL_RTX;
1.1.1.4   root     2761:     }
1.1       root     2762:   else
                   2763:     {
                   2764:       temp = expand_expr (exp, target, GET_MODE (target), 0);
1.1.1.7 ! root     2765:       /* Return TARGET if it's a specified hardware register.
1.1.1.6   root     2766:         If TARGET is a volatile mem ref, either return TARGET
                   2767:         or return a reg copied *from* TARGET; ANSI requires this.
                   2768: 
                   2769:         Otherwise, if TEMP is not TARGET, return TEMP
                   2770:         if it is constant (for efficiency),
                   2771:         or if we really want the correct value.  */
1.1       root     2772:       if (!(target && GET_CODE (target) == REG
                   2773:            && REGNO (target) < FIRST_PSEUDO_REGISTER)
1.1.1.6   root     2774:          && !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
                   2775:          && temp != target
                   2776:          && (CONSTANT_P (temp) || want_value))
1.1       root     2777:        dont_return_target = 1;
                   2778:     }
                   2779: 
1.1.1.6   root     2780:   /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
                   2781:      the same as that of TARGET, adjust the constant.  This is needed, for
                   2782:      example, in case it is a CONST_DOUBLE and we want only a word-sized
                   2783:      value.  */
                   2784:   if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode
1.1.1.7 ! root     2785:       && TREE_CODE (exp) != ERROR_MARK
1.1.1.6   root     2786:       && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
                   2787:     temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
                   2788:                          temp, TREE_UNSIGNED (TREE_TYPE (exp)));
                   2789: 
1.1       root     2790:   /* If value was not generated in the target, store it there.
                   2791:      Convert the value to TARGET's type first if nec.  */
                   2792: 
                   2793:   if (temp != target && TREE_CODE (exp) != ERROR_MARK)
                   2794:     {
                   2795:       target = protect_from_queue (target, 1);
                   2796:       if (GET_MODE (temp) != GET_MODE (target)
                   2797:          && GET_MODE (temp) != VOIDmode)
                   2798:        {
                   2799:          int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
                   2800:          if (dont_return_target)
                   2801:            {
                   2802:              /* In this case, we will return TEMP,
                   2803:                 so make sure it has the proper mode.
                   2804:                 But don't forget to store the value into TARGET.  */
                   2805:              temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
                   2806:              emit_move_insn (target, temp);
                   2807:            }
                   2808:          else
                   2809:            convert_move (target, temp, unsignedp);
                   2810:        }
                   2811: 
                   2812:       else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
                   2813:        {
                   2814:          /* Handle copying a string constant into an array.
                   2815:             The string constant may be shorter than the array.
                   2816:             So copy just the string's actual length, and clear the rest.  */
                   2817:          rtx size;
1.1.1.7 ! root     2818:          rtx addr;
1.1       root     2819: 
1.1.1.2   root     2820:          /* Get the size of the data type of the string,
                   2821:             which is actually the size of the target.  */
                   2822:          size = expr_size (exp);
                   2823:          if (GET_CODE (size) == CONST_INT
                   2824:              && INTVAL (size) < TREE_STRING_LENGTH (exp))
                   2825:            emit_block_move (target, temp, size,
                   2826:                             TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   2827:          else
1.1       root     2828:            {
1.1.1.2   root     2829:              /* Compute the size of the data to copy from the string.  */
                   2830:              tree copy_size
1.1.1.5   root     2831:                = size_binop (MIN_EXPR,
1.1.1.6   root     2832:                              make_tree (sizetype, size),
1.1.1.5   root     2833:                              convert (sizetype,
                   2834:                                       build_int_2 (TREE_STRING_LENGTH (exp), 0)));
1.1.1.4   root     2835:              rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX,
                   2836:                                               VOIDmode, 0);
1.1.1.2   root     2837:              rtx label = 0;
                   2838: 
                   2839:              /* Copy that much.  */
                   2840:              emit_block_move (target, temp, copy_size_rtx,
                   2841:                               TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   2842: 
                   2843:              /* Figure out how much is left in TARGET
                   2844:                 that we have to clear.  */
                   2845:              if (GET_CODE (copy_size_rtx) == CONST_INT)
                   2846:                {
1.1.1.7 ! root     2847:                  addr = plus_constant (XEXP (target, 0),
1.1.1.2   root     2848:                                        TREE_STRING_LENGTH (exp));
1.1.1.7 ! root     2849:                  size = plus_constant (size, - TREE_STRING_LENGTH (exp));
1.1.1.2   root     2850:                }
                   2851:              else
                   2852:                {
                   2853:                  enum machine_mode size_mode = Pmode;
                   2854: 
1.1.1.7 ! root     2855:                  addr = force_reg (Pmode, XEXP (target, 0));
        !          2856:                  addr = expand_binop (size_mode, add_optab, addr,
1.1.1.4   root     2857:                                       copy_size_rtx, NULL_RTX, 0,
                   2858:                                       OPTAB_LIB_WIDEN);
1.1.1.2   root     2859: 
                   2860:                  size = expand_binop (size_mode, sub_optab, size,
1.1.1.4   root     2861:                                       copy_size_rtx, NULL_RTX, 0,
                   2862:                                       OPTAB_LIB_WIDEN);
1.1.1.2   root     2863: 
1.1.1.4   root     2864:                  emit_cmp_insn (size, const0_rtx, LT, NULL_RTX,
1.1.1.2   root     2865:                                 GET_MODE (size), 0, 0);
                   2866:                  label = gen_label_rtx ();
                   2867:                  emit_jump_insn (gen_blt (label));
                   2868:                }
                   2869: 
                   2870:              if (size != const0_rtx)
                   2871:                {
1.1       root     2872: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.7 ! root     2873:                  emit_library_call (memset_libfunc, 0, VOIDmode, 3, addr,
        !          2874:                                     Pmode, const0_rtx, Pmode, size, Pmode);
1.1       root     2875: #else
1.1.1.4   root     2876:                  emit_library_call (bzero_libfunc, 0, VOIDmode, 2,
1.1.1.7 ! root     2877:                                     addr, Pmode, size, Pmode);
1.1       root     2878: #endif
1.1.1.2   root     2879:                }
1.1.1.7 ! root     2880: 
1.1.1.2   root     2881:              if (label)
                   2882:                emit_label (label);
1.1       root     2883:            }
                   2884:        }
                   2885:       else if (GET_MODE (temp) == BLKmode)
                   2886:        emit_block_move (target, temp, expr_size (exp),
                   2887:                         TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   2888:       else
                   2889:        emit_move_insn (target, temp);
                   2890:     }
1.1.1.6   root     2891: 
1.1.1.7 ! root     2892:   /* If we don't want a value, return NULL_RTX.  */
        !          2893:   if (! want_value)
        !          2894:     return NULL_RTX;
        !          2895: 
        !          2896:   /* If we are supposed to return TEMP, do so as long as it isn't a MEM.
        !          2897:      ??? The latter test doesn't seem to make sense.  */
        !          2898:   else if (dont_return_target && GET_CODE (temp) != MEM)
1.1       root     2899:     return temp;
1.1.1.7 ! root     2900: 
        !          2901:   /* Return TARGET itself if it is a hard register.  */
        !          2902:   else if (want_value && GET_MODE (target) != BLKmode
        !          2903:           && ! (GET_CODE (target) == REG
        !          2904:                 && REGNO (target) < FIRST_PSEUDO_REGISTER))
1.1.1.6   root     2905:     return copy_to_reg (target);
1.1.1.7 ! root     2906:   
        !          2907:   else
1.1.1.6   root     2908:     return target;
1.1       root     2909: }
                   2910: 
                   2911: /* Store the value of constructor EXP into the rtx TARGET.
                   2912:    TARGET is either a REG or a MEM.  */
                   2913: 
                   2914: static void
                   2915: store_constructor (exp, target)
                   2916:      tree exp;
                   2917:      rtx target;
                   2918: {
1.1.1.3   root     2919:   tree type = TREE_TYPE (exp);
                   2920: 
1.1       root     2921:   /* We know our target cannot conflict, since safe_from_p has been called.  */
                   2922: #if 0
                   2923:   /* Don't try copying piece by piece into a hard register
                   2924:      since that is vulnerable to being clobbered by EXP.
                   2925:      Instead, construct in a pseudo register and then copy it all.  */
                   2926:   if (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
                   2927:     {
                   2928:       rtx temp = gen_reg_rtx (GET_MODE (target));
                   2929:       store_constructor (exp, temp);
                   2930:       emit_move_insn (target, temp);
                   2931:       return;
                   2932:     }
                   2933: #endif
                   2934: 
1.1.1.6   root     2935:   if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
                   2936:       || TREE_CODE (type) == QUAL_UNION_TYPE)
1.1       root     2937:     {
                   2938:       register tree elt;
                   2939: 
1.1.1.3   root     2940:       /* Inform later passes that the whole union value is dead.  */
1.1.1.6   root     2941:       if (TREE_CODE (type) == UNION_TYPE
                   2942:          || TREE_CODE (type) == QUAL_UNION_TYPE)
1.1       root     2943:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1.1.1.3   root     2944: 
                   2945:       /* If we are building a static constructor into a register,
                   2946:         set the initial value as zero so we can fold the value into
                   2947:         a constant.  */
                   2948:       else if (GET_CODE (target) == REG && TREE_STATIC (exp))
                   2949:        emit_move_insn (target, const0_rtx);
                   2950: 
1.1       root     2951:       /* If the constructor has fewer fields than the structure,
                   2952:         clear the whole structure first.  */
                   2953:       else if (list_length (CONSTRUCTOR_ELTS (exp))
1.1.1.3   root     2954:               != list_length (TYPE_FIELDS (type)))
                   2955:        clear_storage (target, int_size_in_bytes (type));
1.1       root     2956:       else
                   2957:        /* Inform later passes that the old value is dead.  */
                   2958:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                   2959: 
                   2960:       /* Store each element of the constructor into
                   2961:         the corresponding field of TARGET.  */
                   2962: 
                   2963:       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
                   2964:        {
                   2965:          register tree field = TREE_PURPOSE (elt);
                   2966:          register enum machine_mode mode;
                   2967:          int bitsize;
1.1.1.6   root     2968:          int bitpos = 0;
1.1       root     2969:          int unsignedp;
1.1.1.6   root     2970:          tree pos, constant = 0, offset = 0;
                   2971:          rtx to_rtx = target;
1.1       root     2972: 
1.1.1.4   root     2973:          /* Just ignore missing fields.
                   2974:             We cleared the whole structure, above,
                   2975:             if any fields are missing.  */
                   2976:          if (field == 0)
                   2977:            continue;
                   2978: 
1.1       root     2979:          bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
                   2980:          unsignedp = TREE_UNSIGNED (field);
                   2981:          mode = DECL_MODE (field);
                   2982:          if (DECL_BIT_FIELD (field))
                   2983:            mode = VOIDmode;
                   2984: 
1.1.1.6   root     2985:          pos = DECL_FIELD_BITPOS (field);
                   2986:          if (TREE_CODE (pos) == INTEGER_CST)
                   2987:            constant = pos;
                   2988:          else if (TREE_CODE (pos) == PLUS_EXPR
                   2989:                   && TREE_CODE (TREE_OPERAND (pos, 1)) == INTEGER_CST)
                   2990:            constant = TREE_OPERAND (pos, 1), offset = TREE_OPERAND (pos, 0);
                   2991:          else
                   2992:            offset = pos;
1.1       root     2993: 
1.1.1.6   root     2994:          if (constant)
                   2995:            bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
                   2996: 
                   2997:          if (offset)
                   2998:            {
                   2999:              rtx offset_rtx;
1.1       root     3000: 
1.1.1.6   root     3001:              if (contains_placeholder_p (offset))
                   3002:                offset = build (WITH_RECORD_EXPR, sizetype,
                   3003:                                offset, exp);
                   3004: 
                   3005:              offset = size_binop (FLOOR_DIV_EXPR, offset,
                   3006:                                   size_int (BITS_PER_UNIT));
                   3007: 
                   3008:              offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
                   3009:              if (GET_CODE (to_rtx) != MEM)
                   3010:                abort ();
                   3011: 
                   3012:              to_rtx
                   3013:                = change_address (to_rtx, VOIDmode,
                   3014:                                  gen_rtx (PLUS, Pmode, XEXP (to_rtx, 0),
                   3015:                                           force_reg (Pmode, offset_rtx)));
                   3016:            }
                   3017: 
                   3018:          store_field (to_rtx, bitsize, bitpos, mode, TREE_VALUE (elt),
1.1       root     3019:                       /* The alignment of TARGET is
                   3020:                          at least what its type requires.  */
                   3021:                       VOIDmode, 0,
1.1.1.3   root     3022:                       TYPE_ALIGN (type) / BITS_PER_UNIT,
                   3023:                       int_size_in_bytes (type));
1.1       root     3024:        }
                   3025:     }
1.1.1.3   root     3026:   else if (TREE_CODE (type) == ARRAY_TYPE)
1.1       root     3027:     {
                   3028:       register tree elt;
                   3029:       register int i;
1.1.1.3   root     3030:       tree domain = TYPE_DOMAIN (type);
1.1.1.4   root     3031:       HOST_WIDE_INT minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
                   3032:       HOST_WIDE_INT maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
1.1.1.3   root     3033:       tree elttype = TREE_TYPE (type);
1.1       root     3034: 
                   3035:       /* If the constructor has fewer fields than the structure,
1.1.1.3   root     3036:         clear the whole structure first.  Similarly if this this is
                   3037:         static constructor of a non-BLKmode object.  */
1.1       root     3038: 
1.1.1.3   root     3039:       if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1
                   3040:          || (GET_CODE (target) == REG && TREE_STATIC (exp)))
1.1.1.5   root     3041:        clear_storage (target, int_size_in_bytes (type));
1.1       root     3042:       else
                   3043:        /* Inform later passes that the old value is dead.  */
                   3044:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                   3045: 
                   3046:       /* Store each element of the constructor into
                   3047:         the corresponding element of TARGET, determined
                   3048:         by counting the elements.  */
                   3049:       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
                   3050:           elt;
                   3051:           elt = TREE_CHAIN (elt), i++)
                   3052:        {
                   3053:          register enum machine_mode mode;
                   3054:          int bitsize;
                   3055:          int bitpos;
                   3056:          int unsignedp;
1.1.1.6   root     3057:          tree index = TREE_PURPOSE (elt);
                   3058:          rtx xtarget = target;
1.1       root     3059: 
                   3060:          mode = TYPE_MODE (elttype);
                   3061:          bitsize = GET_MODE_BITSIZE (mode);
                   3062:          unsignedp = TREE_UNSIGNED (elttype);
                   3063: 
1.1.1.6   root     3064:          if (index != 0 && TREE_CODE (index) != INTEGER_CST)
                   3065:            {
                   3066:              /* We don't currently allow variable indices in a
                   3067:                 C initializer, but let's try here to support them.  */
                   3068:              rtx pos_rtx, addr, xtarget;
                   3069:              tree position;
                   3070: 
                   3071:              position = size_binop (MULT_EXPR, index, TYPE_SIZE (elttype));
                   3072:              pos_rtx = expand_expr (position, 0, VOIDmode, 0);
                   3073:              addr = gen_rtx (PLUS, Pmode, XEXP (target, 0), pos_rtx);
                   3074:              xtarget = change_address (target, mode, addr);
                   3075:              store_expr (TREE_VALUE (elt), xtarget, 0);
                   3076:            }
                   3077:          else
                   3078:            {
                   3079:              if (index != 0)
                   3080:                bitpos = ((TREE_INT_CST_LOW (index) - minelt)
                   3081:                          * TREE_INT_CST_LOW (TYPE_SIZE (elttype)));
                   3082:              else
                   3083:                bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype)));
1.1       root     3084: 
1.1.1.6   root     3085:              store_field (xtarget, bitsize, bitpos, mode, TREE_VALUE (elt),
                   3086:                           /* The alignment of TARGET is
                   3087:                              at least what its type requires.  */
                   3088:                           VOIDmode, 0,
                   3089:                           TYPE_ALIGN (type) / BITS_PER_UNIT,
                   3090:                           int_size_in_bytes (type));
                   3091:            }
1.1       root     3092:        }
                   3093:     }
                   3094: 
                   3095:   else
                   3096:     abort ();
                   3097: }
                   3098: 
                   3099: /* Store the value of EXP (an expression tree)
                   3100:    into a subfield of TARGET which has mode MODE and occupies
                   3101:    BITSIZE bits, starting BITPOS bits from the start of TARGET.
                   3102:    If MODE is VOIDmode, it means that we are storing into a bit-field.
                   3103: 
                   3104:    If VALUE_MODE is VOIDmode, return nothing in particular.
                   3105:    UNSIGNEDP is not used in this case.
                   3106: 
                   3107:    Otherwise, return an rtx for the value stored.  This rtx
                   3108:    has mode VALUE_MODE if that is convenient to do.
                   3109:    In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
                   3110: 
                   3111:    ALIGN is the alignment that TARGET is known to have, measured in bytes.
                   3112:    TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.  */
                   3113: 
                   3114: static rtx
                   3115: store_field (target, bitsize, bitpos, mode, exp, value_mode,
                   3116:             unsignedp, align, total_size)
                   3117:      rtx target;
                   3118:      int bitsize, bitpos;
                   3119:      enum machine_mode mode;
                   3120:      tree exp;
                   3121:      enum machine_mode value_mode;
                   3122:      int unsignedp;
                   3123:      int align;
                   3124:      int total_size;
                   3125: {
1.1.1.4   root     3126:   HOST_WIDE_INT width_mask = 0;
1.1       root     3127: 
1.1.1.4   root     3128:   if (bitsize < HOST_BITS_PER_WIDE_INT)
                   3129:     width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
1.1       root     3130: 
                   3131:   /* If we are storing into an unaligned field of an aligned union that is
                   3132:      in a register, we may have the mode of TARGET being an integer mode but
                   3133:      MODE == BLKmode.  In that case, get an aligned object whose size and
                   3134:      alignment are the same as TARGET and store TARGET into it (we can avoid
                   3135:      the store if the field being stored is the entire width of TARGET).  Then
                   3136:      call ourselves recursively to store the field into a BLKmode version of
                   3137:      that object.  Finally, load from the object into TARGET.  This is not
                   3138:      very efficient in general, but should only be slightly more expensive
                   3139:      than the otherwise-required unaligned accesses.  Perhaps this can be
                   3140:      cleaned up later.  */
                   3141: 
                   3142:   if (mode == BLKmode
                   3143:       && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG))
                   3144:     {
                   3145:       rtx object = assign_stack_temp (GET_MODE (target),
                   3146:                                      GET_MODE_SIZE (GET_MODE (target)), 0);
                   3147:       rtx blk_object = copy_rtx (object);
                   3148: 
1.1.1.7 ! root     3149:       MEM_IN_STRUCT_P (object) = 1;
        !          3150:       MEM_IN_STRUCT_P (blk_object) = 1;
1.1       root     3151:       PUT_MODE (blk_object, BLKmode);
                   3152: 
                   3153:       if (bitsize != GET_MODE_BITSIZE (GET_MODE (target)))
                   3154:        emit_move_insn (object, target);
                   3155: 
                   3156:       store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0,
                   3157:                   align, total_size);
                   3158: 
1.1.1.6   root     3159:       /* Even though we aren't returning target, we need to
                   3160:         give it the updated value.  */
1.1       root     3161:       emit_move_insn (target, object);
                   3162: 
1.1.1.6   root     3163:       return blk_object;
1.1       root     3164:     }
                   3165: 
                   3166:   /* If the structure is in a register or if the component
                   3167:      is a bit field, we cannot use addressing to access it.
                   3168:      Use bit-field techniques or SUBREG to store in it.  */
                   3169: 
1.1.1.4   root     3170:   if (mode == VOIDmode
                   3171:       || (mode != BLKmode && ! direct_store[(int) mode])
                   3172:       || GET_CODE (target) == REG
1.1.1.6   root     3173:       || GET_CODE (target) == SUBREG
                   3174:       /* If the field isn't aligned enough to store as an ordinary memref,
                   3175:         store it as a bit field.  */
                   3176:       || (STRICT_ALIGNMENT
                   3177:          && align * BITS_PER_UNIT < GET_MODE_ALIGNMENT (mode))
                   3178:       || (STRICT_ALIGNMENT && bitpos % GET_MODE_ALIGNMENT (mode) != 0))
1.1       root     3179:     {
1.1.1.4   root     3180:       rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
1.1.1.6   root     3181: 
                   3182:       /* Unless MODE is VOIDmode or BLKmode, convert TEMP to
                   3183:         MODE.  */
                   3184:       if (mode != VOIDmode && mode != BLKmode
                   3185:          && mode != TYPE_MODE (TREE_TYPE (exp)))
                   3186:        temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
                   3187: 
1.1       root     3188:       /* Store the value in the bitfield.  */
                   3189:       store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size);
                   3190:       if (value_mode != VOIDmode)
                   3191:        {
                   3192:          /* The caller wants an rtx for the value.  */
                   3193:          /* If possible, avoid refetching from the bitfield itself.  */
                   3194:          if (width_mask != 0
                   3195:              && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)))
1.1.1.4   root     3196:            {
                   3197:              tree count;
                   3198:              enum machine_mode tmode;
                   3199: 
                   3200:              if (unsignedp)
                   3201:                return expand_and (temp, GEN_INT (width_mask), NULL_RTX);
                   3202:              tmode = GET_MODE (temp);
                   3203:              if (tmode == VOIDmode)
                   3204:                tmode = value_mode;
                   3205:              count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
                   3206:              temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
                   3207:              return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
                   3208:            }
1.1       root     3209:          return extract_bit_field (target, bitsize, bitpos, unsignedp,
1.1.1.4   root     3210:                                    NULL_RTX, value_mode, 0, align,
                   3211:                                    total_size);
1.1       root     3212:        }
                   3213:       return const0_rtx;
                   3214:     }
                   3215:   else
                   3216:     {
                   3217:       rtx addr = XEXP (target, 0);
                   3218:       rtx to_rtx;
                   3219: 
                   3220:       /* If a value is wanted, it must be the lhs;
                   3221:         so make the address stable for multiple use.  */
                   3222: 
                   3223:       if (value_mode != VOIDmode && GET_CODE (addr) != REG
                   3224:          && ! CONSTANT_ADDRESS_P (addr)
                   3225:          /* A frame-pointer reference is already stable.  */
                   3226:          && ! (GET_CODE (addr) == PLUS
                   3227:                && GET_CODE (XEXP (addr, 1)) == CONST_INT
                   3228:                && (XEXP (addr, 0) == virtual_incoming_args_rtx
                   3229:                    || XEXP (addr, 0) == virtual_stack_vars_rtx)))
                   3230:        addr = copy_to_reg (addr);
                   3231: 
                   3232:       /* Now build a reference to just the desired component.  */
                   3233: 
                   3234:       to_rtx = change_address (target, mode,
                   3235:                               plus_constant (addr, (bitpos / BITS_PER_UNIT)));
                   3236:       MEM_IN_STRUCT_P (to_rtx) = 1;
                   3237: 
                   3238:       return store_expr (exp, to_rtx, value_mode != VOIDmode);
                   3239:     }
                   3240: }
                   3241: 
1.1.1.7 ! root     3242: /* Return true if any object containing the innermost array is an unaligned
        !          3243:    packed structure field.  */
        !          3244: 
        !          3245: static int
        !          3246: get_inner_unaligned_p (exp)
        !          3247:      tree exp;
        !          3248: {
        !          3249:   int needed_alignment = TYPE_ALIGN (TREE_TYPE (exp));
        !          3250: 
        !          3251:   while (1)
        !          3252:     {
        !          3253:       if (TREE_CODE (exp) == COMPONENT_REF || TREE_CODE (exp) == BIT_FIELD_REF)
        !          3254:        {
        !          3255:          if (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
        !          3256:              < needed_alignment)
        !          3257:            return 1;
        !          3258:        }
        !          3259:       else if (TREE_CODE (exp) != ARRAY_REF
        !          3260:               && TREE_CODE (exp) != NON_LVALUE_EXPR
        !          3261:               && ! ((TREE_CODE (exp) == NOP_EXPR
        !          3262:                      || TREE_CODE (exp) == CONVERT_EXPR)
        !          3263:                     && (TYPE_MODE (TREE_TYPE (exp))
        !          3264:                         == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
        !          3265:        break;
        !          3266: 
        !          3267:       exp = TREE_OPERAND (exp, 0);
        !          3268:     }
        !          3269: 
        !          3270:   return 0;
        !          3271: }
        !          3272: 
1.1       root     3273: /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF,
                   3274:    or an ARRAY_REF, look for nested COMPONENT_REFs, BIT_FIELD_REFs, or
1.1.1.5   root     3275:    ARRAY_REFs and find the ultimate containing object, which we return.
1.1       root     3276: 
                   3277:    We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
                   3278:    bit position, and *PUNSIGNEDP to the signedness of the field.
1.1.1.3   root     3279:    If the position of the field is variable, we store a tree
                   3280:    giving the variable offset (in units) in *POFFSET.
                   3281:    This offset is in addition to the bit position.
                   3282:    If the position is not variable, we store 0 in *POFFSET.
1.1       root     3283: 
                   3284:    If any of the extraction expressions is volatile,
                   3285:    we store 1 in *PVOLATILEP.  Otherwise we don't change that.
                   3286: 
                   3287:    If the field is a bit-field, *PMODE is set to VOIDmode.  Otherwise, it
                   3288:    is a mode that can be used to access the field.  In that case, *PBITSIZE
1.1.1.3   root     3289:    is redundant.
                   3290: 
                   3291:    If the field describes a variable-sized object, *PMODE is set to
                   3292:    VOIDmode and *PBITSIZE is set to -1.  An access cannot be made in
                   3293:    this case, but the address of the object can be found.  */
1.1       root     3294: 
                   3295: tree
1.1.1.5   root     3296: get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
                   3297:                     punsignedp, pvolatilep)
1.1       root     3298:      tree exp;
                   3299:      int *pbitsize;
                   3300:      int *pbitpos;
1.1.1.3   root     3301:      tree *poffset;
1.1       root     3302:      enum machine_mode *pmode;
                   3303:      int *punsignedp;
                   3304:      int *pvolatilep;
                   3305: {
1.1.1.6   root     3306:   tree orig_exp = exp;
1.1       root     3307:   tree size_tree = 0;
                   3308:   enum machine_mode mode = VOIDmode;
1.1.1.5   root     3309:   tree offset = integer_zero_node;
1.1       root     3310: 
                   3311:   if (TREE_CODE (exp) == COMPONENT_REF)
                   3312:     {
                   3313:       size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
                   3314:       if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
                   3315:        mode = DECL_MODE (TREE_OPERAND (exp, 1));
                   3316:       *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1));
                   3317:     }
                   3318:   else if (TREE_CODE (exp) == BIT_FIELD_REF)
                   3319:     {
                   3320:       size_tree = TREE_OPERAND (exp, 1);
                   3321:       *punsignedp = TREE_UNSIGNED (exp);
                   3322:     }
                   3323:   else
                   3324:     {
                   3325:       mode = TYPE_MODE (TREE_TYPE (exp));
                   3326:       *pbitsize = GET_MODE_BITSIZE (mode);
                   3327:       *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
                   3328:     }
                   3329:       
                   3330:   if (size_tree)
                   3331:     {
                   3332:       if (TREE_CODE (size_tree) != INTEGER_CST)
1.1.1.3   root     3333:        mode = BLKmode, *pbitsize = -1;
                   3334:       else
                   3335:        *pbitsize = TREE_INT_CST_LOW (size_tree);
1.1       root     3336:     }
                   3337: 
                   3338:   /* Compute cumulative bit-offset for nested component-refs and array-refs,
                   3339:      and find the ultimate containing object.  */
                   3340: 
                   3341:   *pbitpos = 0;
                   3342: 
                   3343:   while (1)
                   3344:     {
1.1.1.3   root     3345:       if (TREE_CODE (exp) == COMPONENT_REF || TREE_CODE (exp) == BIT_FIELD_REF)
1.1       root     3346:        {
1.1.1.3   root     3347:          tree pos = (TREE_CODE (exp) == COMPONENT_REF
                   3348:                      ? DECL_FIELD_BITPOS (TREE_OPERAND (exp, 1))
                   3349:                      : TREE_OPERAND (exp, 2));
1.1       root     3350: 
1.1.1.5   root     3351:          /* If this field hasn't been filled in yet, don't go
                   3352:             past it.  This should only happen when folding expressions
                   3353:             made during type construction.  */
                   3354:          if (pos == 0)
                   3355:            break;
                   3356: 
1.1.1.3   root     3357:          if (TREE_CODE (pos) == PLUS_EXPR)
                   3358:            {
                   3359:              tree constant, var;
                   3360:              if (TREE_CODE (TREE_OPERAND (pos, 0)) == INTEGER_CST)
                   3361:                {
                   3362:                  constant = TREE_OPERAND (pos, 0);
                   3363:                  var = TREE_OPERAND (pos, 1);
                   3364:                }
                   3365:              else if (TREE_CODE (TREE_OPERAND (pos, 1)) == INTEGER_CST)
                   3366:                {
                   3367:                  constant = TREE_OPERAND (pos, 1);
                   3368:                  var = TREE_OPERAND (pos, 0);
                   3369:                }
                   3370:              else
                   3371:                abort ();
1.1.1.5   root     3372: 
1.1.1.3   root     3373:              *pbitpos += TREE_INT_CST_LOW (constant);
1.1.1.5   root     3374:              offset = size_binop (PLUS_EXPR, offset,
                   3375:                                   size_binop (FLOOR_DIV_EXPR, var,
                   3376:                                               size_int (BITS_PER_UNIT)));
1.1.1.3   root     3377:            }
                   3378:          else if (TREE_CODE (pos) == INTEGER_CST)
                   3379:            *pbitpos += TREE_INT_CST_LOW (pos);
                   3380:          else
                   3381:            {
                   3382:              /* Assume here that the offset is a multiple of a unit.
                   3383:                 If not, there should be an explicitly added constant.  */
1.1.1.5   root     3384:              offset = size_binop (PLUS_EXPR, offset,
                   3385:                                   size_binop (FLOOR_DIV_EXPR, pos,
                   3386:                                               size_int (BITS_PER_UNIT)));
1.1.1.3   root     3387:            }
1.1       root     3388:        }
                   3389: 
1.1.1.5   root     3390:       else if (TREE_CODE (exp) == ARRAY_REF)
1.1       root     3391:        {
1.1.1.5   root     3392:          /* This code is based on the code in case ARRAY_REF in expand_expr
                   3393:             below.  We assume here that the size of an array element is
                   3394:             always an integral multiple of BITS_PER_UNIT.  */
                   3395: 
                   3396:          tree index = TREE_OPERAND (exp, 1);
                   3397:          tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   3398:          tree low_bound
                   3399:            = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
                   3400:          tree index_type = TREE_TYPE (index);
                   3401: 
                   3402:          if (! integer_zerop (low_bound))
                   3403:            index = fold (build (MINUS_EXPR, index_type, index, low_bound));
                   3404: 
                   3405:          if (TYPE_PRECISION (index_type) != POINTER_SIZE)
                   3406:            {
                   3407:              index = convert (type_for_size (POINTER_SIZE, 0), index);
                   3408:              index_type = TREE_TYPE (index);
                   3409:            }
                   3410: 
                   3411:          index = fold (build (MULT_EXPR, index_type, index,
                   3412:                               TYPE_SIZE (TREE_TYPE (exp))));
                   3413: 
                   3414:          if (TREE_CODE (index) == INTEGER_CST
                   3415:              && TREE_INT_CST_HIGH (index) == 0)
                   3416:            *pbitpos += TREE_INT_CST_LOW (index);
                   3417:          else
                   3418:            offset = size_binop (PLUS_EXPR, offset,
                   3419:                                 size_binop (FLOOR_DIV_EXPR, index,
                   3420:                                             size_int (BITS_PER_UNIT)));
1.1       root     3421:        }
                   3422:       else if (TREE_CODE (exp) != NON_LVALUE_EXPR
                   3423:               && ! ((TREE_CODE (exp) == NOP_EXPR
                   3424:                      || TREE_CODE (exp) == CONVERT_EXPR)
                   3425:                     && (TYPE_MODE (TREE_TYPE (exp))
                   3426:                         == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
                   3427:        break;
1.1.1.3   root     3428: 
                   3429:       /* If any reference in the chain is volatile, the effect is volatile.  */
                   3430:       if (TREE_THIS_VOLATILE (exp))
                   3431:        *pvolatilep = 1;
1.1       root     3432:       exp = TREE_OPERAND (exp, 0);
                   3433:     }
                   3434: 
                   3435:   /* If this was a bit-field, see if there is a mode that allows direct
                   3436:      access in case EXP is in memory.  */
1.1.1.5   root     3437:   if (mode == VOIDmode && *pbitsize != 0 && *pbitpos % *pbitsize == 0)
1.1       root     3438:     {
                   3439:       mode = mode_for_size (*pbitsize, MODE_INT, 0);
                   3440:       if (mode == BLKmode)
                   3441:        mode = VOIDmode;
                   3442:     }
                   3443: 
1.1.1.5   root     3444:   if (integer_zerop (offset))
                   3445:     offset = 0;
                   3446: 
1.1.1.6   root     3447:   if (offset != 0 && contains_placeholder_p (offset))
                   3448:     offset = build (WITH_RECORD_EXPR, sizetype, offset, orig_exp);
                   3449: 
1.1       root     3450:   *pmode = mode;
1.1.1.3   root     3451:   *poffset = offset;
1.1       root     3452:   return exp;
                   3453: }
                   3454: 
                   3455: /* Given an rtx VALUE that may contain additions and multiplications,
                   3456:    return an equivalent value that just refers to a register or memory.
                   3457:    This is done by generating instructions to perform the arithmetic
1.1.1.4   root     3458:    and returning a pseudo-register containing the value.
                   3459: 
                   3460:    The returned value may be a REG, SUBREG, MEM or constant.  */
1.1       root     3461: 
                   3462: rtx
                   3463: force_operand (value, target)
                   3464:      rtx value, target;
                   3465: {
                   3466:   register optab binoptab = 0;
                   3467:   /* Use a temporary to force order of execution of calls to
                   3468:      `force_operand'.  */
                   3469:   rtx tmp;
                   3470:   register rtx op2;
                   3471:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   3472:   register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
                   3473: 
                   3474:   if (GET_CODE (value) == PLUS)
                   3475:     binoptab = add_optab;
                   3476:   else if (GET_CODE (value) == MINUS)
                   3477:     binoptab = sub_optab;
                   3478:   else if (GET_CODE (value) == MULT)
                   3479:     {
                   3480:       op2 = XEXP (value, 1);
                   3481:       if (!CONSTANT_P (op2)
                   3482:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   3483:        subtarget = 0;
                   3484:       tmp = force_operand (XEXP (value, 0), subtarget);
                   3485:       return expand_mult (GET_MODE (value), tmp,
1.1.1.4   root     3486:                          force_operand (op2, NULL_RTX),
1.1       root     3487:                          target, 0);
                   3488:     }
                   3489: 
                   3490:   if (binoptab)
                   3491:     {
                   3492:       op2 = XEXP (value, 1);
                   3493:       if (!CONSTANT_P (op2)
                   3494:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   3495:        subtarget = 0;
                   3496:       if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT)
                   3497:        {
                   3498:          binoptab = add_optab;
                   3499:          op2 = negate_rtx (GET_MODE (value), op2);
                   3500:        }
                   3501: 
                   3502:       /* Check for an addition with OP2 a constant integer and our first
                   3503:         operand a PLUS of a virtual register and something else.  In that
                   3504:         case, we want to emit the sum of the virtual register and the
                   3505:         constant first and then add the other value.  This allows virtual
                   3506:         register instantiation to simply modify the constant rather than
                   3507:         creating another one around this addition.  */
                   3508:       if (binoptab == add_optab && GET_CODE (op2) == CONST_INT
                   3509:          && GET_CODE (XEXP (value, 0)) == PLUS
                   3510:          && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
                   3511:          && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
                   3512:          && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
                   3513:        {
                   3514:          rtx temp = expand_binop (GET_MODE (value), binoptab,
                   3515:                                   XEXP (XEXP (value, 0), 0), op2,
                   3516:                                   subtarget, 0, OPTAB_LIB_WIDEN);
                   3517:          return expand_binop (GET_MODE (value), binoptab, temp,
                   3518:                               force_operand (XEXP (XEXP (value, 0), 1), 0),
                   3519:                               target, 0, OPTAB_LIB_WIDEN);
                   3520:        }
                   3521:                                   
                   3522:       tmp = force_operand (XEXP (value, 0), subtarget);
                   3523:       return expand_binop (GET_MODE (value), binoptab, tmp,
1.1.1.4   root     3524:                           force_operand (op2, NULL_RTX),
1.1       root     3525:                           target, 0, OPTAB_LIB_WIDEN);
1.1.1.5   root     3526:       /* We give UNSIGNEDP = 0 to expand_binop
1.1       root     3527:         because the only operations we are expanding here are signed ones.  */
                   3528:     }
                   3529:   return value;
                   3530: }
                   3531: 
                   3532: /* Subroutine of expand_expr:
                   3533:    save the non-copied parts (LIST) of an expr (LHS), and return a list
                   3534:    which can restore these values to their previous values,
                   3535:    should something modify their storage.  */
                   3536: 
                   3537: static tree
                   3538: save_noncopied_parts (lhs, list)
                   3539:      tree lhs;
                   3540:      tree list;
                   3541: {
                   3542:   tree tail;
                   3543:   tree parts = 0;
                   3544: 
                   3545:   for (tail = list; tail; tail = TREE_CHAIN (tail))
                   3546:     if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
                   3547:       parts = chainon (parts, save_noncopied_parts (lhs, TREE_VALUE (tail)));
                   3548:     else
                   3549:       {
                   3550:        tree part = TREE_VALUE (tail);
                   3551:        tree part_type = TREE_TYPE (part);
1.1.1.4   root     3552:        tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part);
1.1       root     3553:        rtx target = assign_stack_temp (TYPE_MODE (part_type),
                   3554:                                        int_size_in_bytes (part_type), 0);
                   3555:        if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0)))
1.1.1.4   root     3556:          target = change_address (target, TYPE_MODE (part_type), NULL_RTX);
1.1       root     3557:        parts = tree_cons (to_be_saved,
1.1.1.4   root     3558:                           build (RTL_EXPR, part_type, NULL_TREE,
                   3559:                                  (tree) target),
1.1       root     3560:                           parts);
                   3561:        store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0);
                   3562:       }
                   3563:   return parts;
                   3564: }
                   3565: 
                   3566: /* Subroutine of expand_expr:
                   3567:    record the non-copied parts (LIST) of an expr (LHS), and return a list
                   3568:    which specifies the initial values of these parts.  */
                   3569: 
                   3570: static tree
                   3571: init_noncopied_parts (lhs, list)
                   3572:      tree lhs;
                   3573:      tree list;
                   3574: {
                   3575:   tree tail;
                   3576:   tree parts = 0;
                   3577: 
                   3578:   for (tail = list; tail; tail = TREE_CHAIN (tail))
                   3579:     if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
                   3580:       parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
                   3581:     else
                   3582:       {
                   3583:        tree part = TREE_VALUE (tail);
                   3584:        tree part_type = TREE_TYPE (part);
1.1.1.4   root     3585:        tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part);
1.1       root     3586:        parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts);
                   3587:       }
                   3588:   return parts;
                   3589: }
                   3590: 
                   3591: /* Subroutine of expand_expr: return nonzero iff there is no way that
                   3592:    EXP can reference X, which is being modified.  */
                   3593: 
                   3594: static int
                   3595: safe_from_p (x, exp)
                   3596:      rtx x;
                   3597:      tree exp;
                   3598: {
                   3599:   rtx exp_rtl = 0;
                   3600:   int i, nops;
                   3601: 
1.1.1.7 ! root     3602:   if (x == 0
        !          3603:       /* If EXP has varying size, we MUST use a target since we currently
        !          3604:         have no way of allocating temporaries of variable size.  So we
        !          3605:         assume here that something at a higher level has prevented a
        !          3606:         clash.  This is somewhat bogus, but the best we can do.  */
        !          3607:       || (TREE_TYPE (exp) != 0 && TYPE_SIZE (TREE_TYPE (exp)) != 0
        !          3608:          && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST))
1.1       root     3609:     return 1;
                   3610: 
                   3611:   /* If this is a subreg of a hard register, declare it unsafe, otherwise,
                   3612:      find the underlying pseudo.  */
                   3613:   if (GET_CODE (x) == SUBREG)
                   3614:     {
                   3615:       x = SUBREG_REG (x);
                   3616:       if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
                   3617:        return 0;
                   3618:     }
                   3619: 
                   3620:   /* If X is a location in the outgoing argument area, it is always safe.  */
                   3621:   if (GET_CODE (x) == MEM
                   3622:       && (XEXP (x, 0) == virtual_outgoing_args_rtx
                   3623:          || (GET_CODE (XEXP (x, 0)) == PLUS
                   3624:              && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx)))
                   3625:     return 1;
                   3626: 
                   3627:   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
                   3628:     {
                   3629:     case 'd':
                   3630:       exp_rtl = DECL_RTL (exp);
                   3631:       break;
                   3632: 
                   3633:     case 'c':
                   3634:       return 1;
                   3635: 
                   3636:     case 'x':
                   3637:       if (TREE_CODE (exp) == TREE_LIST)
1.1.1.4   root     3638:        return ((TREE_VALUE (exp) == 0
                   3639:                 || safe_from_p (x, TREE_VALUE (exp)))
1.1       root     3640:                && (TREE_CHAIN (exp) == 0
                   3641:                    || safe_from_p (x, TREE_CHAIN (exp))));
                   3642:       else
                   3643:        return 0;
                   3644: 
                   3645:     case '1':
                   3646:       return safe_from_p (x, TREE_OPERAND (exp, 0));
                   3647: 
                   3648:     case '2':
                   3649:     case '<':
                   3650:       return (safe_from_p (x, TREE_OPERAND (exp, 0))
                   3651:              && safe_from_p (x, TREE_OPERAND (exp, 1)));
                   3652: 
                   3653:     case 'e':
                   3654:     case 'r':
                   3655:       /* Now do code-specific tests.  EXP_RTL is set to any rtx we find in
                   3656:         the expression.  If it is set, we conflict iff we are that rtx or
                   3657:         both are in memory.  Otherwise, we check all operands of the
                   3658:         expression recursively.  */
                   3659: 
                   3660:       switch (TREE_CODE (exp))
                   3661:        {
                   3662:        case ADDR_EXPR:
1.1.1.6   root     3663:          return (staticp (TREE_OPERAND (exp, 0))
                   3664:                  || safe_from_p (x, TREE_OPERAND (exp, 0)));
1.1       root     3665: 
                   3666:        case INDIRECT_REF:
                   3667:          if (GET_CODE (x) == MEM)
                   3668:            return 0;
                   3669:          break;
                   3670: 
                   3671:        case CALL_EXPR:
                   3672:          exp_rtl = CALL_EXPR_RTL (exp);
                   3673:          if (exp_rtl == 0)
                   3674:            {
                   3675:              /* Assume that the call will clobber all hard registers and
                   3676:                 all of memory.  */
                   3677:              if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
                   3678:                  || GET_CODE (x) == MEM)
                   3679:                return 0;
                   3680:            }
                   3681: 
                   3682:          break;
                   3683: 
                   3684:        case RTL_EXPR:
                   3685:          exp_rtl = RTL_EXPR_RTL (exp);
                   3686:          if (exp_rtl == 0)
                   3687:            /* We don't know what this can modify.  */
                   3688:            return 0;
                   3689: 
                   3690:          break;
                   3691: 
                   3692:        case WITH_CLEANUP_EXPR:
                   3693:          exp_rtl = RTL_EXPR_RTL (exp);
                   3694:          break;
                   3695: 
1.1.1.7 ! root     3696:        case CLEANUP_POINT_EXPR:
        !          3697:          return safe_from_p (x, TREE_OPERAND (exp, 0));
        !          3698: 
1.1       root     3699:        case SAVE_EXPR:
                   3700:          exp_rtl = SAVE_EXPR_RTL (exp);
                   3701:          break;
                   3702: 
1.1.1.3   root     3703:        case BIND_EXPR:
                   3704:          /* The only operand we look at is operand 1.  The rest aren't
                   3705:             part of the expression.  */
                   3706:          return safe_from_p (x, TREE_OPERAND (exp, 1));
                   3707: 
1.1       root     3708:        case METHOD_CALL_EXPR:
                   3709:          /* This takes a rtx argument, but shouldn't appear here. */
                   3710:          abort ();
                   3711:        }
                   3712: 
                   3713:       /* If we have an rtx, we do not need to scan our operands.  */
                   3714:       if (exp_rtl)
                   3715:        break;
                   3716: 
                   3717:       nops = tree_code_length[(int) TREE_CODE (exp)];
                   3718:       for (i = 0; i < nops; i++)
                   3719:        if (TREE_OPERAND (exp, i) != 0
                   3720:            && ! safe_from_p (x, TREE_OPERAND (exp, i)))
                   3721:          return 0;
                   3722:     }
                   3723: 
                   3724:   /* If we have an rtl, find any enclosed object.  Then see if we conflict
                   3725:      with it.  */
                   3726:   if (exp_rtl)
                   3727:     {
                   3728:       if (GET_CODE (exp_rtl) == SUBREG)
                   3729:        {
                   3730:          exp_rtl = SUBREG_REG (exp_rtl);
                   3731:          if (GET_CODE (exp_rtl) == REG
                   3732:              && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER)
                   3733:            return 0;
                   3734:        }
                   3735: 
                   3736:       /* If the rtl is X, then it is not safe.  Otherwise, it is unless both
                   3737:         are memory and EXP is not readonly.  */
                   3738:       return ! (rtx_equal_p (x, exp_rtl)
                   3739:                || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
                   3740:                    && ! TREE_READONLY (exp)));
                   3741:     }
                   3742: 
                   3743:   /* If we reach here, it is safe.  */
                   3744:   return 1;
                   3745: }
                   3746: 
                   3747: /* Subroutine of expand_expr: return nonzero iff EXP is an
                   3748:    expression whose type is statically determinable.  */
                   3749: 
                   3750: static int
                   3751: fixed_type_p (exp)
                   3752:      tree exp;
                   3753: {
                   3754:   if (TREE_CODE (exp) == PARM_DECL
                   3755:       || TREE_CODE (exp) == VAR_DECL
                   3756:       || TREE_CODE (exp) == CALL_EXPR || TREE_CODE (exp) == TARGET_EXPR
                   3757:       || TREE_CODE (exp) == COMPONENT_REF
                   3758:       || TREE_CODE (exp) == ARRAY_REF)
                   3759:     return 1;
                   3760:   return 0;
                   3761: }
                   3762: 
                   3763: /* expand_expr: generate code for computing expression EXP.
                   3764:    An rtx for the computed value is returned.  The value is never null.
                   3765:    In the case of a void EXP, const0_rtx is returned.
                   3766: 
                   3767:    The value may be stored in TARGET if TARGET is nonzero.
                   3768:    TARGET is just a suggestion; callers must assume that
                   3769:    the rtx returned may not be the same as TARGET.
                   3770: 
                   3771:    If TARGET is CONST0_RTX, it means that the value will be ignored.
                   3772: 
                   3773:    If TMODE is not VOIDmode, it suggests generating the
                   3774:    result in mode TMODE.  But this is done only when convenient.
                   3775:    Otherwise, TMODE is ignored and the value generated in its natural mode.
                   3776:    TMODE is just a suggestion; callers must assume that
                   3777:    the rtx returned may not have mode TMODE.
                   3778: 
1.1.1.7 ! root     3779:    Note that TARGET may have neither TMODE nor MODE.  In that case, it
        !          3780:    probably will not be used.
1.1       root     3781: 
                   3782:    If MODIFIER is EXPAND_SUM then when EXP is an addition
                   3783:    we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
                   3784:    or a nest of (PLUS ...) and (MINUS ...) where the terms are
                   3785:    products as above, or REG or MEM, or constant.
                   3786:    Ordinarily in such cases we would output mul or add instructions
                   3787:    and then return a pseudo reg containing the sum.
                   3788: 
                   3789:    EXPAND_INITIALIZER is much like EXPAND_SUM except that
                   3790:    it also marks a label as absolutely required (it can't be dead).
1.1.1.4   root     3791:    It also makes a ZERO_EXTEND or SIGN_EXTEND instead of emitting extend insns.
1.1.1.7 ! root     3792:    This is used for outputting expressions used in initializers.
        !          3793: 
        !          3794:    EXPAND_CONST_ADDRESS says that it is okay to return a MEM
        !          3795:    with a constant address even if that address is not normally legitimate.
        !          3796:    EXPAND_INITIALIZER and EXPAND_SUM also have this effect.  */
1.1       root     3797: 
                   3798: rtx
                   3799: expand_expr (exp, target, tmode, modifier)
                   3800:      register tree exp;
                   3801:      rtx target;
                   3802:      enum machine_mode tmode;
                   3803:      enum expand_modifier modifier;
                   3804: {
1.1.1.6   root     3805:   /* Chain of pending expressions for PLACEHOLDER_EXPR to replace.
                   3806:      This is static so it will be accessible to our recursive callees.  */
                   3807:   static tree placeholder_list = 0;
1.1       root     3808:   register rtx op0, op1, temp;
                   3809:   tree type = TREE_TYPE (exp);
                   3810:   int unsignedp = TREE_UNSIGNED (type);
                   3811:   register enum machine_mode mode = TYPE_MODE (type);
                   3812:   register enum tree_code code = TREE_CODE (exp);
                   3813:   optab this_optab;
                   3814:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   3815:   rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
                   3816:   rtx original_target = target;
1.1.1.6   root     3817:   /* Maybe defer this until sure not doing bytecode?  */
                   3818:   int ignore = (target == const0_rtx
                   3819:                || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
                   3820:                     || code == CONVERT_EXPR || code == REFERENCE_EXPR
                   3821:                     || code == COND_EXPR)
                   3822:                    && TREE_CODE (type) == VOID_TYPE));
1.1       root     3823:   tree context;
                   3824: 
1.1.1.6   root     3825: 
1.1.1.7 ! root     3826:   if (output_bytecode && modifier != EXPAND_INITIALIZER)
1.1.1.6   root     3827:     {
                   3828:       bc_expand_expr (exp);
                   3829:       return NULL;
                   3830:     }
                   3831: 
1.1       root     3832:   /* Don't use hard regs as subtargets, because the combiner
                   3833:      can only handle pseudo regs.  */
                   3834:   if (subtarget && REGNO (subtarget) < FIRST_PSEUDO_REGISTER)
                   3835:     subtarget = 0;
                   3836:   /* Avoid subtargets inside loops,
                   3837:      since they hide some invariant expressions.  */
                   3838:   if (preserve_subexpressions_p ())
                   3839:     subtarget = 0;
                   3840: 
1.1.1.6   root     3841:   /* If we are going to ignore this result, we need only do something
                   3842:      if there is a side-effect somewhere in the expression.  If there
                   3843:      is, short-circuit the most common cases here.  Note that we must
                   3844:      not call expand_expr with anything but const0_rtx in case this
                   3845:      is an initial expansion of a size that contains a PLACEHOLDER_EXPR.  */
                   3846: 
                   3847:   if (ignore)
                   3848:     {
                   3849:       if (! TREE_SIDE_EFFECTS (exp))
                   3850:        return const0_rtx;
                   3851: 
                   3852:       /* Ensure we reference a volatile object even if value is ignored.  */
                   3853:       if (TREE_THIS_VOLATILE (exp)
                   3854:          && TREE_CODE (exp) != FUNCTION_DECL
                   3855:          && mode != VOIDmode && mode != BLKmode)
                   3856:        {
                   3857:          temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier);
                   3858:          if (GET_CODE (temp) == MEM)
                   3859:            temp = copy_to_reg (temp);
                   3860:          return const0_rtx;
                   3861:        }
                   3862: 
                   3863:       if (TREE_CODE_CLASS (code) == '1')
                   3864:        return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
                   3865:                            VOIDmode, modifier);
                   3866:       else if (TREE_CODE_CLASS (code) == '2'
                   3867:               || TREE_CODE_CLASS (code) == '<')
                   3868:        {
                   3869:          expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
                   3870:          expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
                   3871:          return const0_rtx;
                   3872:        }
                   3873:       else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
                   3874:               && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
                   3875:        /* If the second operand has no side effects, just evaluate
                   3876:           the first. */
                   3877:        return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
                   3878:                            VOIDmode, modifier);
                   3879: 
                   3880:       target = 0;
                   3881:     }
1.1       root     3882: 
                   3883:   /* If will do cse, generate all results into pseudo registers
                   3884:      since 1) that allows cse to find more things
                   3885:      and 2) otherwise cse could produce an insn the machine
                   3886:      cannot support.  */
                   3887: 
                   3888:   if (! cse_not_expected && mode != BLKmode && target
                   3889:       && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER))
                   3890:     target = subtarget;
                   3891: 
                   3892:   switch (code)
                   3893:     {
                   3894:     case LABEL_DECL:
1.1.1.3   root     3895:       {
                   3896:        tree function = decl_function_context (exp);
                   3897:        /* Handle using a label in a containing function.  */
                   3898:        if (function != current_function_decl && function != 0)
                   3899:          {
                   3900:            struct function *p = find_function_data (function);
                   3901:            /* Allocate in the memory associated with the function
                   3902:               that the label is in.  */
                   3903:            push_obstacks (p->function_obstack,
                   3904:                           p->function_maybepermanent_obstack);
                   3905: 
                   3906:            p->forced_labels = gen_rtx (EXPR_LIST, VOIDmode,
                   3907:                                        label_rtx (exp), p->forced_labels);
                   3908:            pop_obstacks ();
                   3909:          }
                   3910:        else if (modifier == EXPAND_INITIALIZER)
                   3911:          forced_labels = gen_rtx (EXPR_LIST, VOIDmode,
                   3912:                                   label_rtx (exp), forced_labels);
1.1.1.4   root     3913:        temp = gen_rtx (MEM, FUNCTION_MODE,
1.1.1.3   root     3914:                        gen_rtx (LABEL_REF, Pmode, label_rtx (exp)));
1.1.1.4   root     3915:        if (function != current_function_decl && function != 0)
                   3916:          LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1;
                   3917:        return temp;
1.1.1.3   root     3918:       }
1.1       root     3919: 
                   3920:     case PARM_DECL:
                   3921:       if (DECL_RTL (exp) == 0)
                   3922:        {
                   3923:          error_with_decl (exp, "prior parameter's size depends on `%s'");
1.1.1.3   root     3924:          return CONST0_RTX (mode);
1.1       root     3925:        }
                   3926: 
1.1.1.7 ! root     3927:       /* ... fall through ... */
        !          3928: 
1.1       root     3929:     case VAR_DECL:
1.1.1.6   root     3930:       /* If a static var's type was incomplete when the decl was written,
                   3931:         but the type is complete now, lay out the decl now.  */
                   3932:       if (DECL_SIZE (exp) == 0 && TYPE_SIZE (TREE_TYPE (exp)) != 0
                   3933:          && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
                   3934:        {
                   3935:          push_obstacks_nochange ();
                   3936:          end_temporary_allocation ();
                   3937:          layout_decl (exp, 0);
                   3938:          PUT_MODE (DECL_RTL (exp), DECL_MODE (exp));
                   3939:          pop_obstacks ();
                   3940:        }
1.1.1.7 ! root     3941: 
        !          3942:       /* ... fall through ... */
        !          3943: 
1.1.1.6   root     3944:     case FUNCTION_DECL:
1.1       root     3945:     case RESULT_DECL:
                   3946:       if (DECL_RTL (exp) == 0)
                   3947:        abort ();
1.1.1.7 ! root     3948: 
1.1.1.6   root     3949:       /* Ensure variable marked as used even if it doesn't go through
                   3950:         a parser.  If it hasn't be used yet, write out an external
                   3951:         definition.  */
                   3952:       if (! TREE_USED (exp))
                   3953:        {
                   3954:          assemble_external (exp);
                   3955:          TREE_USED (exp) = 1;
                   3956:        }
                   3957: 
1.1       root     3958:       /* Handle variables inherited from containing functions.  */
                   3959:       context = decl_function_context (exp);
                   3960: 
                   3961:       /* We treat inline_function_decl as an alias for the current function
                   3962:         because that is the inline function whose vars, types, etc.
                   3963:         are being merged into the current function.
                   3964:         See expand_inline_function.  */
1.1.1.7 ! root     3965: 
1.1       root     3966:       if (context != 0 && context != current_function_decl
                   3967:          && context != inline_function_decl
                   3968:          /* If var is static, we don't need a static chain to access it.  */
                   3969:          && ! (GET_CODE (DECL_RTL (exp)) == MEM
                   3970:                && CONSTANT_P (XEXP (DECL_RTL (exp), 0))))
                   3971:        {
                   3972:          rtx addr;
                   3973: 
                   3974:          /* Mark as non-local and addressable.  */
1.1.1.4   root     3975:          DECL_NONLOCAL (exp) = 1;
1.1       root     3976:          mark_addressable (exp);
                   3977:          if (GET_CODE (DECL_RTL (exp)) != MEM)
                   3978:            abort ();
                   3979:          addr = XEXP (DECL_RTL (exp), 0);
                   3980:          if (GET_CODE (addr) == MEM)
1.1.1.7 ! root     3981:            addr = gen_rtx (MEM, Pmode,
        !          3982:                            fix_lexical_addr (XEXP (addr, 0), exp));
1.1       root     3983:          else
                   3984:            addr = fix_lexical_addr (addr, exp);
                   3985:          return change_address (DECL_RTL (exp), mode, addr);
                   3986:        }
1.1.1.3   root     3987: 
1.1       root     3988:       /* This is the case of an array whose size is to be determined
                   3989:         from its initializer, while the initializer is still being parsed.
                   3990:         See expand_decl.  */
1.1.1.7 ! root     3991: 
1.1       root     3992:       if (GET_CODE (DECL_RTL (exp)) == MEM
                   3993:          && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG)
                   3994:        return change_address (DECL_RTL (exp), GET_MODE (DECL_RTL (exp)),
                   3995:                               XEXP (DECL_RTL (exp), 0));
1.1.1.7 ! root     3996: 
        !          3997:       /* If DECL_RTL is memory, we are in the normal case and either
        !          3998:         the address is not valid or it is not a register and -fforce-addr
        !          3999:         is specified, get the address into a register.  */
        !          4000: 
1.1       root     4001:       if (GET_CODE (DECL_RTL (exp)) == MEM
                   4002:          && modifier != EXPAND_CONST_ADDRESS
                   4003:          && modifier != EXPAND_SUM
1.1.1.7 ! root     4004:          && modifier != EXPAND_INITIALIZER
        !          4005:          && (! memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0))
1.1       root     4006:              || (flag_force_addr
1.1.1.7 ! root     4007:                  && GET_CODE (XEXP (DECL_RTL (exp), 0)) != REG)))
        !          4008:        return change_address (DECL_RTL (exp), VOIDmode,
        !          4009:                               copy_rtx (XEXP (DECL_RTL (exp), 0)));
1.1.1.4   root     4010: 
                   4011:       /* If the mode of DECL_RTL does not match that of the decl, it
                   4012:         must be a promoted value.  We return a SUBREG of the wanted mode,
                   4013:         but mark it so that we know that it was already extended.  */
                   4014: 
                   4015:       if (GET_CODE (DECL_RTL (exp)) == REG
                   4016:          && GET_MODE (DECL_RTL (exp)) != mode)
                   4017:        {
                   4018:          /* Get the signedness used for this variable.  Ensure we get the
                   4019:             same mode we got when the variable was declared.  */
1.1.1.7 ! root     4020:          if (GET_MODE (DECL_RTL (exp))
        !          4021:              != promote_mode (type, DECL_MODE (exp), &unsignedp, 0))
1.1.1.4   root     4022:            abort ();
                   4023: 
                   4024:          temp = gen_rtx (SUBREG, mode, DECL_RTL (exp), 0);
                   4025:          SUBREG_PROMOTED_VAR_P (temp) = 1;
                   4026:          SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
                   4027:          return temp;
                   4028:        }
                   4029: 
1.1       root     4030:       return DECL_RTL (exp);
                   4031: 
                   4032:     case INTEGER_CST:
                   4033:       return immed_double_const (TREE_INT_CST_LOW (exp),
                   4034:                                 TREE_INT_CST_HIGH (exp),
                   4035:                                 mode);
                   4036: 
                   4037:     case CONST_DECL:
                   4038:       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
                   4039: 
                   4040:     case REAL_CST:
                   4041:       /* If optimized, generate immediate CONST_DOUBLE
                   4042:         which will be turned into memory by reload if necessary. 
                   4043:      
                   4044:         We used to force a register so that loop.c could see it.  But
                   4045:         this does not allow gen_* patterns to perform optimizations with
                   4046:         the constants.  It also produces two insns in cases like "x = 1.0;".
                   4047:         On most machines, floating-point constants are not permitted in
                   4048:         many insns, so we'd end up copying it to a register in any case.
                   4049: 
                   4050:         Now, we do the copying in expand_binop, if appropriate.  */
                   4051:       return immed_real_const (exp);
                   4052: 
                   4053:     case COMPLEX_CST:
                   4054:     case STRING_CST:
                   4055:       if (! TREE_CST_RTL (exp))
                   4056:        output_constant_def (exp);
                   4057: 
                   4058:       /* TREE_CST_RTL probably contains a constant address.
                   4059:         On RISC machines where a constant address isn't valid,
                   4060:         make some insns to get that address into a register.  */
                   4061:       if (GET_CODE (TREE_CST_RTL (exp)) == MEM
                   4062:          && modifier != EXPAND_CONST_ADDRESS
                   4063:          && modifier != EXPAND_INITIALIZER
                   4064:          && modifier != EXPAND_SUM
1.1.1.7 ! root     4065:          && (! memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0))
        !          4066:              || (flag_force_addr
        !          4067:                  && GET_CODE (XEXP (TREE_CST_RTL (exp), 0)) != REG)))
1.1       root     4068:        return change_address (TREE_CST_RTL (exp), VOIDmode,
                   4069:                               copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
                   4070:       return TREE_CST_RTL (exp);
                   4071: 
                   4072:     case SAVE_EXPR:
                   4073:       context = decl_function_context (exp);
1.1.1.7 ! root     4074: 
1.1       root     4075:       /* We treat inline_function_decl as an alias for the current function
                   4076:         because that is the inline function whose vars, types, etc.
                   4077:         are being merged into the current function.
                   4078:         See expand_inline_function.  */
                   4079:       if (context == current_function_decl || context == inline_function_decl)
                   4080:        context = 0;
                   4081: 
                   4082:       /* If this is non-local, handle it.  */
                   4083:       if (context)
                   4084:        {
                   4085:          temp = SAVE_EXPR_RTL (exp);
                   4086:          if (temp && GET_CODE (temp) == REG)
                   4087:            {
                   4088:              put_var_into_stack (exp);
                   4089:              temp = SAVE_EXPR_RTL (exp);
                   4090:            }
                   4091:          if (temp == 0 || GET_CODE (temp) != MEM)
                   4092:            abort ();
                   4093:          return change_address (temp, mode,
                   4094:                                 fix_lexical_addr (XEXP (temp, 0), exp));
                   4095:        }
                   4096:       if (SAVE_EXPR_RTL (exp) == 0)
                   4097:        {
                   4098:          if (mode == BLKmode)
1.1.1.6   root     4099:            {
                   4100:              temp
                   4101:                = assign_stack_temp (mode, int_size_in_bytes (type), 0);
1.1.1.7 ! root     4102:              MEM_IN_STRUCT_P (temp) = AGGREGATE_TYPE_P (type);
1.1.1.6   root     4103:            }
1.1       root     4104:          else
1.1.1.7 ! root     4105:            temp = gen_reg_rtx (promote_mode (type, mode, &unsignedp, 0));
1.1.1.4   root     4106: 
1.1       root     4107:          SAVE_EXPR_RTL (exp) = temp;
                   4108:          if (!optimize && GET_CODE (temp) == REG)
                   4109:            save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, temp,
                   4110:                                      save_expr_regs);
1.1.1.5   root     4111: 
                   4112:          /* If the mode of TEMP does not match that of the expression, it
                   4113:             must be a promoted value.  We pass store_expr a SUBREG of the
                   4114:             wanted mode but mark it so that we know that it was already
                   4115:             extended.  Note that `unsignedp' was modified above in
                   4116:             this case.  */
                   4117: 
                   4118:          if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
                   4119:            {
                   4120:              temp = gen_rtx (SUBREG, mode, SAVE_EXPR_RTL (exp), 0);
                   4121:              SUBREG_PROMOTED_VAR_P (temp) = 1;
                   4122:              SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
                   4123:            }
                   4124: 
                   4125:          store_expr (TREE_OPERAND (exp, 0), temp, 0);
1.1       root     4126:        }
1.1.1.4   root     4127: 
                   4128:       /* If the mode of SAVE_EXPR_RTL does not match that of the expression, it
                   4129:         must be a promoted value.  We return a SUBREG of the wanted mode,
1.1.1.6   root     4130:         but mark it so that we know that it was already extended. */
1.1.1.4   root     4131: 
                   4132:       if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG
                   4133:          && GET_MODE (SAVE_EXPR_RTL (exp)) != mode)
                   4134:        {
1.1.1.7 ! root     4135:          /* Compute the signedness and make the proper SUBREG.  */
        !          4136:          promote_mode (type, mode, &unsignedp, 0);
1.1.1.4   root     4137:          temp = gen_rtx (SUBREG, mode, SAVE_EXPR_RTL (exp), 0);
                   4138:          SUBREG_PROMOTED_VAR_P (temp) = 1;
                   4139:          SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
                   4140:          return temp;
                   4141:        }
                   4142: 
1.1       root     4143:       return SAVE_EXPR_RTL (exp);
                   4144: 
1.1.1.6   root     4145:     case PLACEHOLDER_EXPR:
                   4146:       /* If there is an object on the head of the placeholder list,
                   4147:         see if some object in it's references is of type TYPE.  For
                   4148:         further information, see tree.def.  */
                   4149:       if (placeholder_list)
                   4150:        {
                   4151:          tree object;
                   4152:          tree old_list = placeholder_list;
                   4153: 
                   4154:          for (object = TREE_PURPOSE (placeholder_list);
                   4155:               TREE_TYPE (object) != type
                   4156:               && (TREE_CODE_CLASS (TREE_CODE (object)) == 'r'
                   4157:                   || TREE_CODE_CLASS (TREE_CODE (object)) == '1'
                   4158:                   || TREE_CODE_CLASS (TREE_CODE (object)) == '2'
                   4159:                   || TREE_CODE_CLASS (TREE_CODE (object)) == 'e');
                   4160:               object = TREE_OPERAND (object, 0))
                   4161:            ;
                   4162: 
                   4163:          if (object && TREE_TYPE (object) == type)
                   4164:            {
                   4165:              /* Expand this object skipping the list entries before
                   4166:                 it was found in case it is also a PLACEHOLDER_EXPR.
                   4167:                 In that case, we want to translate it using subsequent
                   4168:                 entries.  */
                   4169:              placeholder_list = TREE_CHAIN (placeholder_list);
                   4170:              temp = expand_expr (object, original_target, tmode, modifier);
                   4171:              placeholder_list = old_list;
                   4172:              return temp;
                   4173:            }
                   4174:        }
                   4175: 
                   4176:       /* We can't find the object or there was a missing WITH_RECORD_EXPR.  */
                   4177:       abort ();
                   4178: 
                   4179:     case WITH_RECORD_EXPR:
                   4180:       /* Put the object on the placeholder list, expand our first operand,
                   4181:         and pop the list.  */
                   4182:       placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
                   4183:                                    placeholder_list);
                   4184:       target = expand_expr (TREE_OPERAND (exp, 0), original_target,
                   4185:                            tmode, modifier);
                   4186:       placeholder_list = TREE_CHAIN (placeholder_list);
                   4187:       return target;
                   4188: 
1.1       root     4189:     case EXIT_EXPR:
1.1.1.6   root     4190:       expand_exit_loop_if_false (NULL_PTR,
                   4191:                                 invert_truthvalue (TREE_OPERAND (exp, 0)));
1.1       root     4192:       return const0_rtx;
                   4193: 
                   4194:     case LOOP_EXPR:
1.1.1.6   root     4195:       push_temp_slots ();
1.1       root     4196:       expand_start_loop (1);
                   4197:       expand_expr_stmt (TREE_OPERAND (exp, 0));
                   4198:       expand_end_loop ();
1.1.1.6   root     4199:       pop_temp_slots ();
1.1       root     4200: 
                   4201:       return const0_rtx;
                   4202: 
                   4203:     case BIND_EXPR:
                   4204:       {
                   4205:        tree vars = TREE_OPERAND (exp, 0);
                   4206:        int vars_need_expansion = 0;
                   4207: 
                   4208:        /* Need to open a binding contour here because
                   4209:           if there are any cleanups they most be contained here.  */
                   4210:        expand_start_bindings (0);
                   4211: 
1.1.1.4   root     4212:        /* Mark the corresponding BLOCK for output in its proper place.  */
                   4213:        if (TREE_OPERAND (exp, 2) != 0
                   4214:            && ! TREE_USED (TREE_OPERAND (exp, 2)))
                   4215:          insert_block (TREE_OPERAND (exp, 2));
1.1       root     4216: 
                   4217:        /* If VARS have not yet been expanded, expand them now.  */
                   4218:        while (vars)
                   4219:          {
                   4220:            if (DECL_RTL (vars) == 0)
                   4221:              {
                   4222:                vars_need_expansion = 1;
                   4223:                expand_decl (vars);
                   4224:              }
                   4225:            expand_decl_init (vars);
                   4226:            vars = TREE_CHAIN (vars);
                   4227:          }
                   4228: 
                   4229:        temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier);
                   4230: 
                   4231:        expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
                   4232: 
                   4233:        return temp;
                   4234:       }
                   4235: 
                   4236:     case RTL_EXPR:
                   4237:       if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
                   4238:        abort ();
                   4239:       emit_insns (RTL_EXPR_SEQUENCE (exp));
                   4240:       RTL_EXPR_SEQUENCE (exp) = const0_rtx;
1.1.1.6   root     4241:       preserve_rtl_expr_result (RTL_EXPR_RTL (exp));
                   4242:       free_temps_for_rtl_expr (exp);
1.1       root     4243:       return RTL_EXPR_RTL (exp);
                   4244: 
                   4245:     case CONSTRUCTOR:
1.1.1.6   root     4246:       /* If we don't need the result, just ensure we evaluate any
                   4247:         subexpressions.  */
                   4248:       if (ignore)
                   4249:        {
                   4250:          tree elt;
                   4251:          for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
                   4252:            expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
                   4253:          return const0_rtx;
                   4254:        }
1.1.1.7 ! root     4255: 
1.1.1.3   root     4256:       /* All elts simple constants => refer to a constant in memory.  But
                   4257:         if this is a non-BLKmode mode, let it store a field at a time
                   4258:         since that should make a CONST_INT or CONST_DOUBLE when we
1.1.1.7 ! root     4259:         fold.  Likewise, if we have a target we can use, it is best to
        !          4260:         store directly into the target unless the type is large enough
        !          4261:         that memcpy will be used.  If we are making an initializer and
        !          4262:         all operands are constant, put it in memory as well.  */
1.1.1.6   root     4263:       else if ((TREE_STATIC (exp)
1.1.1.7 ! root     4264:                && ((mode == BLKmode
        !          4265:                     && ! (target != 0 && safe_from_p (target, exp)))
        !          4266:                    || TREE_ADDRESSABLE (exp)
        !          4267:                    || (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
        !          4268:                        && (move_by_pieces_ninsns
        !          4269:                            (TREE_INT_CST_LOW (TYPE_SIZE (type)),
        !          4270:                             TYPE_ALIGN (type))
        !          4271:                            > MOVE_RATIO))))
1.1.1.6   root     4272:               || (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
1.1       root     4273:        {
                   4274:          rtx constructor = output_constant_def (exp);
1.1.1.3   root     4275:          if (modifier != EXPAND_CONST_ADDRESS
                   4276:              && modifier != EXPAND_INITIALIZER
                   4277:              && modifier != EXPAND_SUM
1.1.1.7 ! root     4278:              && (! memory_address_p (GET_MODE (constructor),
        !          4279:                                      XEXP (constructor, 0))
        !          4280:                  || (flag_force_addr
        !          4281:                      && GET_CODE (XEXP (constructor, 0)) != REG)))
1.1       root     4282:            constructor = change_address (constructor, VOIDmode,
                   4283:                                          XEXP (constructor, 0));
                   4284:          return constructor;
                   4285:        }
                   4286: 
                   4287:       else
                   4288:        {
                   4289:          if (target == 0 || ! safe_from_p (target, exp))
                   4290:            {
                   4291:              if (mode != BLKmode && ! TREE_ADDRESSABLE (exp))
1.1.1.7 ! root     4292:                target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
1.1       root     4293:              else
                   4294:                {
1.1.1.5   root     4295:                  target
                   4296:                    = assign_stack_temp (mode, int_size_in_bytes (type), 0);
1.1.1.7 ! root     4297:                  if (AGGREGATE_TYPE_P (type))
1.1.1.5   root     4298:                    MEM_IN_STRUCT_P (target) = 1;
1.1       root     4299:                }
                   4300:            }
                   4301:          store_constructor (exp, target);
                   4302:          return target;
                   4303:        }
                   4304: 
                   4305:     case INDIRECT_REF:
                   4306:       {
                   4307:        tree exp1 = TREE_OPERAND (exp, 0);
                   4308:        tree exp2;
                   4309: 
                   4310:        /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated
                   4311:           for  *PTR += ANYTHING  where PTR is put inside the SAVE_EXPR.
                   4312:           This code has the same general effect as simply doing
                   4313:           expand_expr on the save expr, except that the expression PTR
                   4314:           is computed for use as a memory address.  This means different
                   4315:           code, suitable for indexing, may be generated.  */
                   4316:        if (TREE_CODE (exp1) == SAVE_EXPR
                   4317:            && SAVE_EXPR_RTL (exp1) == 0
                   4318:            && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK
                   4319:            && TYPE_MODE (TREE_TYPE (exp1)) == Pmode
                   4320:            && TYPE_MODE (TREE_TYPE (exp2)) == Pmode)
                   4321:          {
1.1.1.4   root     4322:            temp = expand_expr (TREE_OPERAND (exp1, 0), NULL_RTX,
                   4323:                                VOIDmode, EXPAND_SUM);
1.1       root     4324:            op0 = memory_address (mode, temp);
                   4325:            op0 = copy_all_regs (op0);
                   4326:            SAVE_EXPR_RTL (exp1) = op0;
                   4327:          }
                   4328:        else
                   4329:          {
1.1.1.4   root     4330:            op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
1.1       root     4331:            op0 = memory_address (mode, op0);
                   4332:          }
1.1.1.3   root     4333: 
                   4334:        temp = gen_rtx (MEM, mode, op0);
                   4335:        /* If address was computed by addition,
                   4336:           mark this as an element of an aggregate.  */
                   4337:        if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
                   4338:            || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR
                   4339:                && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR)
1.1.1.7 ! root     4340:            || AGGREGATE_TYPE_P (TREE_TYPE (exp))
1.1.1.3   root     4341:            || (TREE_CODE (exp1) == ADDR_EXPR
                   4342:                && (exp2 = TREE_OPERAND (exp1, 0))
1.1.1.7 ! root     4343:                && AGGREGATE_TYPE_P (TREE_TYPE (exp2))))
1.1.1.3   root     4344:          MEM_IN_STRUCT_P (temp) = 1;
1.1.1.6   root     4345:        MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile;
1.1.1.5   root     4346: #if 0 /* It is incorrect to set RTX_UNCHANGING_P here, because the fact that
1.1       root     4347:         a location is accessed through a pointer to const does not mean
                   4348:         that the value there can never change.  */
1.1.1.3   root     4349:        RTX_UNCHANGING_P (temp) = TREE_READONLY (exp);
1.1       root     4350: #endif
1.1.1.3   root     4351:        return temp;
                   4352:       }
1.1       root     4353: 
                   4354:     case ARRAY_REF:
1.1.1.5   root     4355:       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE)
                   4356:        abort ();
1.1       root     4357: 
                   4358:       {
1.1.1.5   root     4359:        tree array = TREE_OPERAND (exp, 0);
                   4360:        tree domain = TYPE_DOMAIN (TREE_TYPE (array));
                   4361:        tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
                   4362:        tree index = TREE_OPERAND (exp, 1);
                   4363:        tree index_type = TREE_TYPE (index);
1.1       root     4364:        int i;
                   4365: 
1.1.1.6   root     4366:        if (TREE_CODE (low_bound) != INTEGER_CST
                   4367:            && contains_placeholder_p (low_bound))
                   4368:          low_bound = build (WITH_RECORD_EXPR, sizetype, low_bound, exp);
                   4369: 
                   4370:        /* Optimize the special-case of a zero lower bound.
                   4371: 
                   4372:           We convert the low_bound to sizetype to avoid some problems
                   4373:           with constant folding.  (E.g. suppose the lower bound is 1,
                   4374:           and its mode is QI.  Without the conversion,  (ARRAY
                   4375:           +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
                   4376:           +INDEX), which becomes (ARRAY+255+INDEX).  Oops!)
                   4377: 
                   4378:           But sizetype isn't quite right either (especially if
                   4379:           the lowbound is negative).  FIXME */
                   4380: 
1.1.1.5   root     4381:        if (! integer_zerop (low_bound))
1.1.1.6   root     4382:          index = fold (build (MINUS_EXPR, index_type, index,
                   4383:                               convert (sizetype, low_bound)));
1.1.1.5   root     4384: 
1.1.1.7 ! root     4385:        if ((TREE_CODE (index) != INTEGER_CST
        !          4386:             || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
        !          4387:            && (! STRICT_ALIGNMENT || ! get_inner_unaligned_p (exp)))
1.1.1.5   root     4388:          {
1.1.1.7 ! root     4389:            /* Nonconstant array index or nonconstant element size, and
        !          4390:               not an array in an unaligned (packed) structure field.
1.1.1.5   root     4391:               Generate the tree for *(&array+index) and expand that,
                   4392:               except do it in a language-independent way
                   4393:               and don't complain about non-lvalue arrays.
                   4394:               `mark_addressable' should already have been called
                   4395:               for any array for which this case will be reached.  */
                   4396: 
                   4397:            /* Don't forget the const or volatile flag from the array
                   4398:               element. */
                   4399:            tree variant_type = build_type_variant (type,
                   4400:                                                    TREE_READONLY (exp),
                   4401:                                                    TREE_THIS_VOLATILE (exp));
                   4402:            tree array_adr = build1 (ADDR_EXPR,
                   4403:                                     build_pointer_type (variant_type), array);
                   4404:            tree elt;
1.1.1.6   root     4405:            tree size = size_in_bytes (type);
1.1.1.5   root     4406: 
                   4407:            /* Convert the integer argument to a type the same size as a
                   4408:               pointer so the multiply won't overflow spuriously.  */
                   4409:            if (TYPE_PRECISION (index_type) != POINTER_SIZE)
                   4410:              index = convert (type_for_size (POINTER_SIZE, 0), index);
                   4411: 
1.1.1.6   root     4412:            if (TREE_CODE (size) != INTEGER_CST
                   4413:                && contains_placeholder_p (size))
                   4414:              size = build (WITH_RECORD_EXPR, sizetype, size, exp);
                   4415: 
1.1.1.5   root     4416:            /* Don't think the address has side effects
                   4417:               just because the array does.
                   4418:               (In some cases the address might have side effects,
                   4419:               and we fail to record that fact here.  However, it should not
                   4420:               matter, since expand_expr should not care.)  */
                   4421:            TREE_SIDE_EFFECTS (array_adr) = 0;
                   4422: 
                   4423:            elt = build1 (INDIRECT_REF, type,
                   4424:                          fold (build (PLUS_EXPR,
                   4425:                                       TYPE_POINTER_TO (variant_type),
                   4426:                                       array_adr,
                   4427:                                       fold (build (MULT_EXPR,
                   4428:                                                    TYPE_POINTER_TO (variant_type),
1.1.1.6   root     4429:                                                    index, size)))));
1.1.1.5   root     4430: 
                   4431:            /* Volatility, etc., of new expression is same as old
                   4432:               expression.  */
                   4433:            TREE_SIDE_EFFECTS (elt) = TREE_SIDE_EFFECTS (exp);
                   4434:            TREE_THIS_VOLATILE (elt) = TREE_THIS_VOLATILE (exp);
                   4435:            TREE_READONLY (elt) = TREE_READONLY (exp);
                   4436: 
                   4437:            return expand_expr (elt, target, tmode, modifier);
                   4438:          }
                   4439: 
                   4440:        /* Fold an expression like: "foo"[2].
1.1.1.7 ! root     4441:           This is not done in fold so it won't happen inside &.
        !          4442:           Don't fold if this is for wide characters since it's too
        !          4443:           difficult to do correctly and this is a very rare case.  */
1.1.1.5   root     4444: 
                   4445:        if (TREE_CODE (array) == STRING_CST
                   4446:            && TREE_CODE (index) == INTEGER_CST
                   4447:            && !TREE_INT_CST_HIGH (index)
1.1.1.7 ! root     4448:            && (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (array)
        !          4449:            && GET_MODE_CLASS (mode) == MODE_INT
        !          4450:            && GET_MODE_SIZE (mode) == 1)
        !          4451:          return GEN_INT (TREE_STRING_POINTER (array)[i]);
1.1       root     4452: 
1.1.1.5   root     4453:        /* If this is a constant index into a constant array,
                   4454:           just get the value from the array.  Handle both the cases when
                   4455:           we have an explicit constructor and when our operand is a variable
                   4456:           that was declared const.  */
1.1.1.3   root     4457: 
1.1.1.5   root     4458:        if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array))
                   4459:          {
                   4460:            if (TREE_CODE (index) == INTEGER_CST
                   4461:                && TREE_INT_CST_HIGH (index) == 0)
                   4462:              {
                   4463:                tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
1.1       root     4464: 
1.1.1.5   root     4465:                i = TREE_INT_CST_LOW (index);
                   4466:                while (elem && i--)
                   4467:                  elem = TREE_CHAIN (elem);
                   4468:                if (elem)
                   4469:                  return expand_expr (fold (TREE_VALUE (elem)), target,
                   4470:                                      tmode, modifier);
                   4471:              }
                   4472:          }
1.1.1.3   root     4473:          
1.1.1.5   root     4474:        else if (optimize >= 1
                   4475:                 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
                   4476:                 && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
                   4477:                 && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
                   4478:          {
                   4479:            if (TREE_CODE (index) == INTEGER_CST
                   4480:                && TREE_INT_CST_HIGH (index) == 0)
                   4481:              {
                   4482:                tree init = DECL_INITIAL (array);
1.1.1.3   root     4483: 
1.1.1.5   root     4484:                i = TREE_INT_CST_LOW (index);
                   4485:                if (TREE_CODE (init) == CONSTRUCTOR)
                   4486:                  {
                   4487:                    tree elem = CONSTRUCTOR_ELTS (init);
                   4488: 
1.1.1.6   root     4489:                    while (elem
                   4490:                           && !tree_int_cst_equal (TREE_PURPOSE (elem), index))
1.1.1.5   root     4491:                      elem = TREE_CHAIN (elem);
                   4492:                    if (elem)
                   4493:                      return expand_expr (fold (TREE_VALUE (elem)), target,
                   4494:                                          tmode, modifier);
                   4495:                  }
                   4496:                else if (TREE_CODE (init) == STRING_CST
                   4497:                         && i < TREE_STRING_LENGTH (init))
1.1.1.7 ! root     4498:                  return GEN_INT (TREE_STRING_POINTER (init)[i]);
1.1.1.5   root     4499:              }
                   4500:          }
                   4501:       }
1.1.1.3   root     4502: 
1.1       root     4503:       /* Treat array-ref with constant index as a component-ref.  */
                   4504: 
                   4505:     case COMPONENT_REF:
                   4506:     case BIT_FIELD_REF:
1.1.1.3   root     4507:       /* If the operand is a CONSTRUCTOR, we can just extract the
1.1.1.7 ! root     4508:         appropriate field if it is present.  Don't do this if we have
        !          4509:         already written the data since we want to refer to that copy
        !          4510:         and varasm.c assumes that's what we'll do.  */
1.1.1.3   root     4511:       if (code != ARRAY_REF
1.1.1.7 ! root     4512:          && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
        !          4513:          && TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
1.1.1.3   root     4514:        {
                   4515:          tree elt;
                   4516: 
                   4517:          for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
                   4518:               elt = TREE_CHAIN (elt))
                   4519:            if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1))
                   4520:              return expand_expr (TREE_VALUE (elt), target, tmode, modifier);
                   4521:        }
                   4522: 
1.1       root     4523:       {
                   4524:        enum machine_mode mode1;
                   4525:        int bitsize;
                   4526:        int bitpos;
1.1.1.3   root     4527:        tree offset;
1.1       root     4528:        int volatilep = 0;
1.1.1.3   root     4529:        tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
1.1       root     4530:                                        &mode1, &unsignedp, &volatilep);
1.1.1.6   root     4531:        int alignment;
1.1       root     4532: 
1.1.1.5   root     4533:        /* If we got back the original object, something is wrong.  Perhaps
                   4534:           we are evaluating an expression too early.  In any event, don't
                   4535:           infinitely recurse.  */
                   4536:        if (tem == exp)
                   4537:          abort ();
                   4538: 
1.1       root     4539:        /* In some cases, we will be offsetting OP0's address by a constant.
                   4540:           So get it as a sum, if possible.  If we will be using it
                   4541:           directly in an insn, we validate it.  */
1.1.1.4   root     4542:        op0 = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_SUM);
1.1       root     4543: 
1.1.1.3   root     4544:        /* If this is a constant, put it into a register if it is a
1.1.1.5   root     4545:           legitimate constant and memory if it isn't.  */
1.1.1.3   root     4546:        if (CONSTANT_P (op0))
                   4547:          {
                   4548:            enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
1.1.1.5   root     4549:            if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0))
1.1.1.3   root     4550:              op0 = force_reg (mode, op0);
                   4551:            else
                   4552:              op0 = validize_mem (force_const_mem (mode, op0));
                   4553:          }
                   4554: 
1.1.1.6   root     4555:        alignment = TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT;
1.1.1.3   root     4556:        if (offset != 0)
                   4557:          {
1.1.1.4   root     4558:            rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
1.1.1.3   root     4559: 
                   4560:            if (GET_CODE (op0) != MEM)
                   4561:              abort ();
                   4562:            op0 = change_address (op0, VOIDmode,
                   4563:                                  gen_rtx (PLUS, Pmode, XEXP (op0, 0),
                   4564:                                           force_reg (Pmode, offset_rtx)));
1.1.1.6   root     4565:          /* If we have a variable offset, the known alignment
                   4566:             is only that of the innermost structure containing the field.
                   4567:             (Actually, we could sometimes do better by using the
                   4568:             size of an element of the innermost array, but no need.)  */
                   4569:          if (TREE_CODE (exp) == COMPONENT_REF
                   4570:              || TREE_CODE (exp) == BIT_FIELD_REF)
                   4571:            alignment = (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
                   4572:                         / BITS_PER_UNIT);
1.1.1.3   root     4573:          }
                   4574: 
1.1       root     4575:        /* Don't forget about volatility even if this is a bitfield.  */
                   4576:        if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
                   4577:          {
                   4578:            op0 = copy_rtx (op0);
                   4579:            MEM_VOLATILE_P (op0) = 1;
                   4580:          }
                   4581: 
1.1.1.6   root     4582:        /* In cases where an aligned union has an unaligned object
                   4583:           as a field, we might be extracting a BLKmode value from
                   4584:           an integer-mode (e.g., SImode) object.  Handle this case
                   4585:           by doing the extract into an object as wide as the field
                   4586:           (which we know to be the width of a basic mode), then
                   4587:           storing into memory, and changing the mode to BLKmode.  */
1.1       root     4588:        if (mode1 == VOIDmode
1.1.1.4   root     4589:            || (mode1 != BLKmode && ! direct_load[(int) mode1]
                   4590:                && modifier != EXPAND_CONST_ADDRESS
                   4591:                && modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
1.1.1.6   root     4592:            || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
                   4593:            /* If the field isn't aligned enough to fetch as a memref,
                   4594:               fetch it as a bit field.  */
                   4595:            || (STRICT_ALIGNMENT
                   4596:                && TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode))
                   4597:            || (STRICT_ALIGNMENT && bitpos % GET_MODE_ALIGNMENT (mode) != 0))
1.1       root     4598:          {
                   4599:            enum machine_mode ext_mode = mode;
                   4600: 
                   4601:            if (ext_mode == BLKmode)
                   4602:              ext_mode = mode_for_size (bitsize, MODE_INT, 1);
                   4603: 
                   4604:            if (ext_mode == BLKmode)
                   4605:              abort ();
                   4606: 
                   4607:            op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos,
                   4608:                                     unsignedp, target, ext_mode, ext_mode,
1.1.1.6   root     4609:                                     alignment,
1.1       root     4610:                                     int_size_in_bytes (TREE_TYPE (tem)));
                   4611:            if (mode == BLKmode)
                   4612:              {
                   4613:                rtx new = assign_stack_temp (ext_mode,
                   4614:                                             bitsize / BITS_PER_UNIT, 0);
                   4615: 
                   4616:                emit_move_insn (new, op0);
                   4617:                op0 = copy_rtx (new);
                   4618:                PUT_MODE (op0, BLKmode);
1.1.1.6   root     4619:                MEM_IN_STRUCT_P (op0) = 1;
1.1       root     4620:              }
                   4621: 
                   4622:            return op0;
                   4623:          }
                   4624: 
                   4625:        /* Get a reference to just this component.  */
                   4626:        if (modifier == EXPAND_CONST_ADDRESS
                   4627:            || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
                   4628:          op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0),
                   4629:                                                    (bitpos / BITS_PER_UNIT)));
                   4630:        else
                   4631:          op0 = change_address (op0, mode1,
                   4632:                                plus_constant (XEXP (op0, 0),
                   4633:                                               (bitpos / BITS_PER_UNIT)));
                   4634:        MEM_IN_STRUCT_P (op0) = 1;
                   4635:        MEM_VOLATILE_P (op0) |= volatilep;
                   4636:        if (mode == mode1 || mode1 == BLKmode || mode1 == tmode)
                   4637:          return op0;
                   4638:        if (target == 0)
                   4639:          target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
                   4640:        convert_move (target, op0, unsignedp);
                   4641:        return target;
                   4642:       }
                   4643: 
                   4644:     case OFFSET_REF:
                   4645:       {
1.1.1.5   root     4646:        tree base = build1 (ADDR_EXPR, type, TREE_OPERAND (exp, 0));
1.1       root     4647:        tree addr = build (PLUS_EXPR, type, base, TREE_OPERAND (exp, 1));
1.1.1.4   root     4648:        op0 = expand_expr (addr, NULL_RTX, VOIDmode, EXPAND_SUM);
1.1       root     4649:        temp = gen_rtx (MEM, mode, memory_address (mode, op0));
                   4650:        MEM_IN_STRUCT_P (temp) = 1;
1.1.1.5   root     4651:        MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp);
                   4652: #if 0 /* It is incorrect to set RTX_UNCHANGING_P here, because the fact that
1.1       root     4653:         a location is accessed through a pointer to const does not mean
                   4654:         that the value there can never change.  */
                   4655:        RTX_UNCHANGING_P (temp) = TREE_READONLY (exp);
                   4656: #endif
                   4657:        return temp;
                   4658:       }
                   4659: 
                   4660:       /* Intended for a reference to a buffer of a file-object in Pascal.
                   4661:         But it's not certain that a special tree code will really be
                   4662:         necessary for these.  INDIRECT_REF might work for them.  */
                   4663:     case BUFFER_REF:
                   4664:       abort ();
                   4665: 
1.1.1.4   root     4666:     case IN_EXPR:
                   4667:       {
1.1.1.7 ! root     4668:        /* Pascal set IN expression.
        !          4669: 
        !          4670:           Algorithm:
        !          4671:               rlo       = set_low - (set_low%bits_per_word);
        !          4672:               the_word  = set [ (index - rlo)/bits_per_word ];
        !          4673:               bit_index = index % bits_per_word;
        !          4674:               bitmask   = 1 << bit_index;
        !          4675:               return !!(the_word & bitmask);  */
        !          4676: 
1.1.1.4   root     4677:        tree set = TREE_OPERAND (exp, 0);
                   4678:        tree index = TREE_OPERAND (exp, 1);
1.1.1.7 ! root     4679:        int iunsignedp = TREE_UNSIGNED (TREE_TYPE (index));
1.1.1.4   root     4680:        tree set_type = TREE_TYPE (set);
                   4681:        tree set_low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (set_type));
                   4682:        tree set_high_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (set_type));
1.1.1.7 ! root     4683:        rtx index_val = expand_expr (index, 0, VOIDmode, 0);
        !          4684:        rtx lo_r = expand_expr (set_low_bound, 0, VOIDmode, 0);
        !          4685:        rtx hi_r = expand_expr (set_high_bound, 0, VOIDmode, 0);
        !          4686:        rtx setval = expand_expr (set, 0, VOIDmode, 0);
        !          4687:        rtx setaddr = XEXP (setval, 0);
        !          4688:        enum machine_mode index_mode = TYPE_MODE (TREE_TYPE (index));
1.1.1.4   root     4689:        rtx rlow;
                   4690:        rtx diff, quo, rem, addr, bit, result;
                   4691: 
1.1.1.7 ! root     4692:        preexpand_calls (exp);
1.1.1.4   root     4693: 
1.1.1.7 ! root     4694:        /* If domain is empty, answer is no.  Likewise if index is constant
        !          4695:           and out of bounds.  */
        !          4696:        if ((TREE_CODE (set_high_bound) == INTEGER_CST
        !          4697:             && TREE_CODE (set_low_bound) == INTEGER_CST
        !          4698:             && tree_int_cst_lt (set_high_bound, set_low_bound)
        !          4699:             || (TREE_CODE (index) == INTEGER_CST
        !          4700:                 && TREE_CODE (set_low_bound) == INTEGER_CST
        !          4701:                 && tree_int_cst_lt (index, set_low_bound))
        !          4702:             || (TREE_CODE (set_high_bound) == INTEGER_CST
        !          4703:                 && TREE_CODE (index) == INTEGER_CST
        !          4704:                 && tree_int_cst_lt (set_high_bound, index))))
1.1.1.4   root     4705:          return const0_rtx;
                   4706: 
1.1.1.7 ! root     4707:        if (target == 0)
        !          4708:          target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
1.1.1.4   root     4709: 
                   4710:        /* If we get here, we have to generate the code for both cases
                   4711:           (in range and out of range).  */
                   4712: 
                   4713:        op0 = gen_label_rtx ();
                   4714:        op1 = gen_label_rtx ();
                   4715: 
                   4716:        if (! (GET_CODE (index_val) == CONST_INT
                   4717:               && GET_CODE (lo_r) == CONST_INT))
                   4718:          {
1.1.1.5   root     4719:            emit_cmp_insn (index_val, lo_r, LT, NULL_RTX,
1.1.1.7 ! root     4720:                           GET_MODE (index_val), iunsignedp, 0);
1.1.1.4   root     4721:            emit_jump_insn (gen_blt (op1));
                   4722:          }
                   4723: 
                   4724:        if (! (GET_CODE (index_val) == CONST_INT
                   4725:               && GET_CODE (hi_r) == CONST_INT))
                   4726:          {
1.1.1.5   root     4727:            emit_cmp_insn (index_val, hi_r, GT, NULL_RTX,
1.1.1.7 ! root     4728:                           GET_MODE (index_val), iunsignedp, 0);
1.1.1.4   root     4729:            emit_jump_insn (gen_bgt (op1));
                   4730:          }
                   4731: 
                   4732:        /* Calculate the element number of bit zero in the first word
                   4733:           of the set.  */
                   4734:        if (GET_CODE (lo_r) == CONST_INT)
1.1.1.5   root     4735:          rlow = GEN_INT (INTVAL (lo_r)
                   4736:                          & ~ ((HOST_WIDE_INT) 1 << BITS_PER_UNIT));
1.1.1.4   root     4737:        else
1.1.1.5   root     4738:          rlow = expand_binop (index_mode, and_optab, lo_r,
                   4739:                               GEN_INT (~((HOST_WIDE_INT) 1 << BITS_PER_UNIT)),
1.1.1.7 ! root     4740:                               NULL_RTX, iunsignedp, OPTAB_LIB_WIDEN);
1.1.1.4   root     4741: 
1.1.1.7 ! root     4742:        diff = expand_binop (index_mode, sub_optab, index_val, rlow,
        !          4743:                             NULL_RTX, iunsignedp, OPTAB_LIB_WIDEN);
1.1.1.4   root     4744: 
                   4745:        quo = expand_divmod (0, TRUNC_DIV_EXPR, index_mode, diff,
1.1.1.7 ! root     4746:                             GEN_INT (BITS_PER_UNIT), NULL_RTX, iunsignedp);
1.1.1.4   root     4747:        rem = expand_divmod (1, TRUNC_MOD_EXPR, index_mode, index_val,
1.1.1.7 ! root     4748:                             GEN_INT (BITS_PER_UNIT), NULL_RTX, iunsignedp);
        !          4749: 
1.1.1.4   root     4750:        addr = memory_address (byte_mode,
1.1.1.7 ! root     4751:                               expand_binop (index_mode, add_optab, diff,
        !          4752:                                             setaddr, NULL_RTX, iunsignedp,
1.1.1.5   root     4753:                                             OPTAB_LIB_WIDEN));
1.1.1.7 ! root     4754: 
1.1.1.4   root     4755:        /* Extract the bit we want to examine */
                   4756:        bit = expand_shift (RSHIFT_EXPR, byte_mode,
1.1.1.5   root     4757:                            gen_rtx (MEM, byte_mode, addr),
                   4758:                            make_tree (TREE_TYPE (index), rem),
                   4759:                            NULL_RTX, 1);
                   4760:        result = expand_binop (byte_mode, and_optab, bit, const1_rtx,
                   4761:                               GET_MODE (target) == byte_mode ? target : 0,
1.1.1.4   root     4762:                               1, OPTAB_LIB_WIDEN);
1.1.1.5   root     4763: 
                   4764:        if (result != target)
                   4765:          convert_move (target, result, 1);
1.1.1.4   root     4766: 
                   4767:        /* Output the code to handle the out-of-range case.  */
                   4768:        emit_jump (op0);
                   4769:        emit_label (op1);
                   4770:        emit_move_insn (target, const0_rtx);
                   4771:        emit_label (op0);
                   4772:        return target;
                   4773:       }
                   4774: 
1.1       root     4775:     case WITH_CLEANUP_EXPR:
                   4776:       if (RTL_EXPR_RTL (exp) == 0)
                   4777:        {
                   4778:          RTL_EXPR_RTL (exp)
1.1.1.7 ! root     4779:            = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
1.1.1.4   root     4780:          cleanups_this_call
                   4781:            = tree_cons (NULL_TREE, TREE_OPERAND (exp, 2), cleanups_this_call);
1.1       root     4782:          /* That's it for this cleanup.  */
                   4783:          TREE_OPERAND (exp, 2) = 0;
1.1.1.7 ! root     4784:          (*interim_eh_hook) (NULL_TREE);
1.1       root     4785:        }
                   4786:       return RTL_EXPR_RTL (exp);
                   4787: 
1.1.1.7 ! root     4788:     case CLEANUP_POINT_EXPR:
        !          4789:       {
        !          4790:        extern int temp_slot_level;
        !          4791:        tree old_cleanups = cleanups_this_call;
        !          4792:        int old_temp_level = target_temp_slot_level;
        !          4793:        push_temp_slots ();
        !          4794:        target_temp_slot_level = temp_slot_level;
        !          4795:        op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier);
        !          4796:        expand_cleanups_to (old_cleanups);
        !          4797:        preserve_temp_slots (op0);
        !          4798:        free_temp_slots ();
        !          4799:        pop_temp_slots ();
        !          4800:        target_temp_slot_level = old_temp_level;
        !          4801:       }
        !          4802:       return op0;
        !          4803: 
1.1       root     4804:     case CALL_EXPR:
                   4805:       /* Check for a built-in function.  */
                   4806:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1.1.1.7 ! root     4807:          && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
        !          4808:              == FUNCTION_DECL)
1.1       root     4809:          && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   4810:        return expand_builtin (exp, target, subtarget, tmode, ignore);
1.1.1.7 ! root     4811: 
1.1       root     4812:       /* If this call was expanded already by preexpand_calls,
                   4813:         just return the result we got.  */
                   4814:       if (CALL_EXPR_RTL (exp) != 0)
                   4815:        return CALL_EXPR_RTL (exp);
1.1.1.7 ! root     4816: 
1.1.1.3   root     4817:       return expand_call (exp, target, ignore);
1.1       root     4818: 
                   4819:     case NON_LVALUE_EXPR:
                   4820:     case NOP_EXPR:
                   4821:     case CONVERT_EXPR:
                   4822:     case REFERENCE_EXPR:
                   4823:       if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
1.1.1.7 ! root     4824:        {
        !          4825:          op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode,
        !          4826:                             modifier);
        !          4827: 
        !          4828:          /* If the signedness of the conversion differs and OP0 is
        !          4829:             a promoted SUBREG, clear that indication since we now
        !          4830:             have to do the proper extension.  */
        !          4831:          if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) != unsignedp
        !          4832:              && GET_CODE (op0) == SUBREG)
        !          4833:            SUBREG_PROMOTED_VAR_P (op0) = 0;
        !          4834: 
        !          4835:          return op0;
        !          4836:        }
        !          4837: 
1.1       root     4838:       if (TREE_CODE (type) == UNION_TYPE)
                   4839:        {
                   4840:          tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
                   4841:          if (target == 0)
                   4842:            {
                   4843:              if (mode == BLKmode)
                   4844:                {
                   4845:                  if (TYPE_SIZE (type) == 0
                   4846:                      || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
                   4847:                    abort ();
                   4848:                  target = assign_stack_temp (BLKmode,
                   4849:                                              (TREE_INT_CST_LOW (TYPE_SIZE (type))
                   4850:                                               + BITS_PER_UNIT - 1)
                   4851:                                              / BITS_PER_UNIT, 0);
                   4852:                }
                   4853:              else
1.1.1.7 ! root     4854:                target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
1.1       root     4855:            }
1.1.1.7 ! root     4856: 
1.1       root     4857:          if (GET_CODE (target) == MEM)
                   4858:            /* Store data into beginning of memory target.  */
                   4859:            store_expr (TREE_OPERAND (exp, 0),
                   4860:                        change_address (target, TYPE_MODE (valtype), 0), 0);
1.1.1.4   root     4861: 
1.1       root     4862:          else if (GET_CODE (target) == REG)
                   4863:            /* Store this field into a union of the proper type.  */
                   4864:            store_field (target, GET_MODE_BITSIZE (TYPE_MODE (valtype)), 0,
                   4865:                         TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
                   4866:                         VOIDmode, 0, 1,
                   4867:                         int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   4868:          else
                   4869:            abort ();
                   4870: 
                   4871:          /* Return the entire union.  */
                   4872:          return target;
                   4873:        }
1.1.1.7 ! root     4874: 
1.1.1.4   root     4875:       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0);
1.1.1.5   root     4876:       if (GET_MODE (op0) == mode)
                   4877:        return op0;
                   4878: 
1.1.1.7 ! root     4879:       /* If OP0 is a constant, just convert it into the proper mode.  */
        !          4880:       if (CONSTANT_P (op0))
        !          4881:        return
        !          4882:          convert_modes (mode, TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
        !          4883:                         op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
        !          4884: 
1.1.1.4   root     4885:       if (modifier == EXPAND_INITIALIZER)
                   4886:        return gen_rtx (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
1.1.1.7 ! root     4887: 
1.1       root     4888:       if (flag_force_mem && GET_CODE (op0) == MEM)
                   4889:        op0 = copy_to_reg (op0);
                   4890: 
                   4891:       if (target == 0)
1.1.1.7 ! root     4892:        return
        !          4893:          convert_to_mode (mode, op0,
        !          4894:                           TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
1.1       root     4895:       else
1.1.1.7 ! root     4896:        convert_move (target, op0,
        !          4897:                      TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
1.1       root     4898:       return target;
                   4899: 
                   4900:     case PLUS_EXPR:
                   4901:       /* We come here from MINUS_EXPR when the second operand is a constant. */
                   4902:     plus_expr:
                   4903:       this_optab = add_optab;
                   4904: 
                   4905:       /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
                   4906:         something else, make sure we add the register to the constant and
                   4907:         then to the other thing.  This case can occur during strength
                   4908:         reduction and doing it this way will produce better code if the
                   4909:         frame pointer or argument pointer is eliminated.
                   4910: 
                   4911:         fold-const.c will ensure that the constant is always in the inner
                   4912:         PLUS_EXPR, so the only case we need to do anything about is if
                   4913:         sp, ap, or fp is our second argument, in which case we must swap
                   4914:         the innermost first argument and our second argument.  */
                   4915: 
                   4916:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
                   4917:          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
                   4918:          && TREE_CODE (TREE_OPERAND (exp, 1)) == RTL_EXPR
                   4919:          && (RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
                   4920:              || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx
                   4921:              || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx))
                   4922:        {
                   4923:          tree t = TREE_OPERAND (exp, 1);
                   4924: 
                   4925:          TREE_OPERAND (exp, 1) = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
                   4926:          TREE_OPERAND (TREE_OPERAND (exp, 0), 0) = t;
                   4927:        }
                   4928: 
                   4929:       /* If the result is to be Pmode and we are adding an integer to
                   4930:         something, we might be forming a constant.  So try to use
                   4931:         plus_constant.  If it produces a sum and we can't accept it,
                   4932:         use force_operand.  This allows P = &ARR[const] to generate
                   4933:         efficient code on machines where a SYMBOL_REF is not a valid
                   4934:         address.
                   4935: 
                   4936:         If this is an EXPAND_SUM call, always return the sum.  */
1.1.1.6   root     4937:       if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
                   4938:          || mode == Pmode)
                   4939:        {
                   4940:          if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
                   4941:              && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
                   4942:              && TREE_CONSTANT (TREE_OPERAND (exp, 1)))
                   4943:            {
                   4944:              op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode,
                   4945:                                 EXPAND_SUM);
                   4946:              op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)));
                   4947:              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                   4948:                op1 = force_operand (op1, target);
                   4949:              return op1;
                   4950:            }
                   4951: 
                   4952:          else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   4953:                   && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT
                   4954:                   && TREE_CONSTANT (TREE_OPERAND (exp, 0)))
                   4955:            {
                   4956:              op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
                   4957:                                 EXPAND_SUM);
                   4958:              if (! CONSTANT_P (op0))
                   4959:                {
                   4960:                  op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
                   4961:                                     VOIDmode, modifier);
                   4962:                  /* Don't go to both_summands if modifier
                   4963:                     says it's not right to return a PLUS.  */
                   4964:                  if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                   4965:                    goto binop2;
                   4966:                  goto both_summands;
                   4967:                }
                   4968:              op0 = plus_constant (op0, TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
                   4969:              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                   4970:                op0 = force_operand (op0, target);
                   4971:              return op0;
                   4972:            }
1.1       root     4973:        }
                   4974: 
                   4975:       /* No sense saving up arithmetic to be done
                   4976:         if it's all in the wrong mode to form part of an address.
                   4977:         And force_operand won't know whether to sign-extend or
                   4978:         zero-extend.  */
                   4979:       if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
1.1.1.6   root     4980:          || mode != Pmode)
                   4981:        goto binop;
1.1       root     4982: 
                   4983:       preexpand_calls (exp);
                   4984:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   4985:        subtarget = 0;
                   4986: 
                   4987:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
1.1.1.4   root     4988:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
1.1.1.2   root     4989: 
1.1.1.6   root     4990:     both_summands:
1.1       root     4991:       /* Make sure any term that's a sum with a constant comes last.  */
                   4992:       if (GET_CODE (op0) == PLUS
                   4993:          && CONSTANT_P (XEXP (op0, 1)))
                   4994:        {
                   4995:          temp = op0;
                   4996:          op0 = op1;
                   4997:          op1 = temp;
                   4998:        }
                   4999:       /* If adding to a sum including a constant,
                   5000:         associate it to put the constant outside.  */
                   5001:       if (GET_CODE (op1) == PLUS
                   5002:          && CONSTANT_P (XEXP (op1, 1)))
                   5003:        {
1.1.1.2   root     5004:          rtx constant_term = const0_rtx;
                   5005: 
                   5006:          temp = simplify_binary_operation (PLUS, mode, XEXP (op1, 0), op0);
                   5007:          if (temp != 0)
                   5008:            op0 = temp;
1.1.1.3   root     5009:          /* Ensure that MULT comes first if there is one.  */
                   5010:          else if (GET_CODE (op0) == MULT)
                   5011:            op0 = gen_rtx (PLUS, mode, op0, XEXP (op1, 0));
1.1.1.2   root     5012:          else
                   5013:            op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0);
1.1       root     5014: 
                   5015:          /* Let's also eliminate constants from op0 if possible.  */
1.1.1.2   root     5016:          op0 = eliminate_constant_term (op0, &constant_term);
                   5017: 
                   5018:          /* CONSTANT_TERM and XEXP (op1, 1) are known to be constant, so
                   5019:             their sum should be a constant.  Form it into OP1, since the 
                   5020:             result we want will then be OP0 + OP1.  */
                   5021: 
                   5022:          temp = simplify_binary_operation (PLUS, mode, constant_term,
                   5023:                                            XEXP (op1, 1));
                   5024:          if (temp != 0)
                   5025:            op1 = temp;
1.1       root     5026:          else
1.1.1.2   root     5027:            op1 = gen_rtx (PLUS, mode, constant_term, XEXP (op1, 1));
1.1       root     5028:        }
1.1.1.2   root     5029: 
                   5030:       /* Put a constant term last and put a multiplication first.  */
                   5031:       if (CONSTANT_P (op0) || GET_CODE (op1) == MULT)
                   5032:        temp = op1, op1 = op0, op0 = temp;
                   5033: 
                   5034:       temp = simplify_binary_operation (PLUS, mode, op0, op1);
                   5035:       return temp ? temp : gen_rtx (PLUS, mode, op0, op1);
1.1       root     5036: 
                   5037:     case MINUS_EXPR:
1.1.1.6   root     5038:       /* For initializers, we are allowed to return a MINUS of two
                   5039:         symbolic constants.  Here we handle all cases when both operands
                   5040:         are constant.  */
1.1       root     5041:       /* Handle difference of two symbolic constants,
                   5042:         for the sake of an initializer.  */
                   5043:       if ((modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
                   5044:          && really_constant_p (TREE_OPERAND (exp, 0))
                   5045:          && really_constant_p (TREE_OPERAND (exp, 1)))
                   5046:        {
1.1.1.4   root     5047:          rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX,
                   5048:                                 VOIDmode, modifier);
                   5049:          rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
                   5050:                                 VOIDmode, modifier);
1.1.1.6   root     5051: 
                   5052:          /* If one operand is a CONST_INT, put it last.  */
                   5053:          if (GET_CODE (op0) == CONST_INT)
                   5054:            temp = op0, op0 = op1, op1 = temp;
                   5055: 
                   5056:          /* If the last operand is a CONST_INT, use plus_constant of
                   5057:             the negated constant.  Else make the MINUS.  */
                   5058:          if (GET_CODE (op1) == CONST_INT)
                   5059:            return plus_constant (op0, - INTVAL (op1));
                   5060:          else
                   5061:            return gen_rtx (MINUS, mode, op0, op1);
1.1       root     5062:        }
                   5063:       /* Convert A - const to A + (-const).  */
                   5064:       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
                   5065:        {
                   5066:          exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0),
                   5067:                       fold (build1 (NEGATE_EXPR, type,
                   5068:                                     TREE_OPERAND (exp, 1))));
                   5069:          goto plus_expr;
                   5070:        }
                   5071:       this_optab = sub_optab;
                   5072:       goto binop;
                   5073: 
                   5074:     case MULT_EXPR:
                   5075:       preexpand_calls (exp);
                   5076:       /* If first operand is constant, swap them.
                   5077:         Thus the following special case checks need only
                   5078:         check the second operand.  */
                   5079:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
                   5080:        {
                   5081:          register tree t1 = TREE_OPERAND (exp, 0);
                   5082:          TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
                   5083:          TREE_OPERAND (exp, 1) = t1;
                   5084:        }
                   5085: 
                   5086:       /* Attempt to return something suitable for generating an
                   5087:         indexed address, for machines that support that.  */
                   5088: 
                   5089:       if (modifier == EXPAND_SUM && mode == Pmode
                   5090:          && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
1.1.1.4   root     5091:          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
1.1       root     5092:        {
                   5093:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
                   5094: 
                   5095:          /* Apply distributive law if OP0 is x+c.  */
                   5096:          if (GET_CODE (op0) == PLUS
                   5097:              && GET_CODE (XEXP (op0, 1)) == CONST_INT)
                   5098:            return gen_rtx (PLUS, mode,
                   5099:                            gen_rtx (MULT, mode, XEXP (op0, 0),
1.1.1.4   root     5100:                                     GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))),
                   5101:                            GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
                   5102:                                     * INTVAL (XEXP (op0, 1))));
1.1       root     5103: 
                   5104:          if (GET_CODE (op0) != REG)
1.1.1.4   root     5105:            op0 = force_operand (op0, NULL_RTX);
1.1       root     5106:          if (GET_CODE (op0) != REG)
                   5107:            op0 = copy_to_mode_reg (mode, op0);
                   5108: 
                   5109:          return gen_rtx (MULT, mode, op0,
1.1.1.4   root     5110:                          GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))));
1.1       root     5111:        }
                   5112: 
                   5113:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   5114:        subtarget = 0;
                   5115: 
                   5116:       /* Check for multiplying things that have been extended
                   5117:         from a narrower type.  If this machine supports multiplying
                   5118:         in that narrower type with a result in the desired type,
                   5119:         do it that way, and avoid the explicit type-conversion.  */
                   5120:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
                   5121:          && TREE_CODE (type) == INTEGER_TYPE
                   5122:          && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   5123:              < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   5124:          && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   5125:               && int_fits_type_p (TREE_OPERAND (exp, 1),
                   5126:                                   TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   5127:               /* Don't use a widening multiply if a shift will do.  */
                   5128:               && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))))
1.1.1.4   root     5129:                    > HOST_BITS_PER_WIDE_INT)
1.1       root     5130:                   || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0))
                   5131:              ||
                   5132:              (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
                   5133:               && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
                   5134:                   ==
                   5135:                   TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
                   5136:               /* If both operands are extended, they must either both
                   5137:                  be zero-extended or both be sign-extended.  */
                   5138:               && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
                   5139:                   ==
                   5140:                   TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
                   5141:        {
                   5142:          enum machine_mode innermode
                   5143:            = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
                   5144:          this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   5145:                        ? umul_widen_optab : smul_widen_optab);
                   5146:          if (mode == GET_MODE_WIDER_MODE (innermode)
                   5147:              && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   5148:            {
                   5149:              op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
1.1.1.4   root     5150:                                 NULL_RTX, VOIDmode, 0);
1.1       root     5151:              if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
1.1.1.4   root     5152:                op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
                   5153:                                   VOIDmode, 0);
1.1       root     5154:              else
                   5155:                op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
1.1.1.4   root     5156:                                   NULL_RTX, VOIDmode, 0);
1.1       root     5157:              goto binop2;
                   5158:            }
                   5159:        }
                   5160:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4   root     5161:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     5162:       return expand_mult (mode, op0, op1, target, unsignedp);
                   5163: 
                   5164:     case TRUNC_DIV_EXPR:
                   5165:     case FLOOR_DIV_EXPR:
                   5166:     case CEIL_DIV_EXPR:
                   5167:     case ROUND_DIV_EXPR:
                   5168:     case EXACT_DIV_EXPR:
                   5169:       preexpand_calls (exp);
                   5170:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   5171:        subtarget = 0;
                   5172:       /* Possible optimization: compute the dividend with EXPAND_SUM
                   5173:         then if the divisor is constant can optimize the case
                   5174:         where some terms of the dividend have coeffs divisible by it.  */
                   5175:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4   root     5176:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     5177:       return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
                   5178: 
                   5179:     case RDIV_EXPR:
                   5180:       this_optab = flodiv_optab;
                   5181:       goto binop;
                   5182: 
                   5183:     case TRUNC_MOD_EXPR:
                   5184:     case FLOOR_MOD_EXPR:
                   5185:     case CEIL_MOD_EXPR:
                   5186:     case ROUND_MOD_EXPR:
                   5187:       preexpand_calls (exp);
                   5188:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   5189:        subtarget = 0;
                   5190:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4   root     5191:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     5192:       return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
                   5193: 
                   5194:     case FIX_ROUND_EXPR:
                   5195:     case FIX_FLOOR_EXPR:
                   5196:     case FIX_CEIL_EXPR:
                   5197:       abort ();                        /* Not used for C.  */
                   5198: 
                   5199:     case FIX_TRUNC_EXPR:
1.1.1.4   root     5200:       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
1.1       root     5201:       if (target == 0)
                   5202:        target = gen_reg_rtx (mode);
                   5203:       expand_fix (target, op0, unsignedp);
                   5204:       return target;
                   5205: 
                   5206:     case FLOAT_EXPR:
1.1.1.4   root     5207:       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
1.1       root     5208:       if (target == 0)
                   5209:        target = gen_reg_rtx (mode);
                   5210:       /* expand_float can't figure out what to do if FROM has VOIDmode.
                   5211:         So give it the correct mode.  With -O, cse will optimize this.  */
                   5212:       if (GET_MODE (op0) == VOIDmode)
                   5213:        op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
                   5214:                                op0);
                   5215:       expand_float (target, op0,
                   5216:                    TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   5217:       return target;
                   5218: 
                   5219:     case NEGATE_EXPR:
1.1.1.7 ! root     5220:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1       root     5221:       temp = expand_unop (mode, neg_optab, op0, target, 0);
                   5222:       if (temp == 0)
                   5223:        abort ();
                   5224:       return temp;
                   5225: 
                   5226:     case ABS_EXPR:
                   5227:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   5228: 
1.1.1.4   root     5229:       /* Handle complex values specially.  */
1.1.1.7 ! root     5230:       if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
        !          5231:          || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
        !          5232:        return expand_complex_abs (mode, op0, target, unsignedp);
1.1.1.4   root     5233: 
1.1       root     5234:       /* Unsigned abs is simply the operand.  Testing here means we don't
                   5235:         risk generating incorrect code below.  */
                   5236:       if (TREE_UNSIGNED (type))
                   5237:        return op0;
                   5238: 
1.1.1.7 ! root     5239:       return expand_abs (mode, op0, target, unsignedp,
        !          5240:                         safe_from_p (target, TREE_OPERAND (exp, 0)));
1.1       root     5241: 
                   5242:     case MAX_EXPR:
                   5243:     case MIN_EXPR:
                   5244:       target = original_target;
                   5245:       if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 1))
1.1.1.6   root     5246:          || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
1.1.1.7 ! root     5247:          || GET_MODE (target) != mode
1.1       root     5248:          || (GET_CODE (target) == REG
                   5249:              && REGNO (target) < FIRST_PSEUDO_REGISTER))
                   5250:        target = gen_reg_rtx (mode);
1.1.1.4   root     5251:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     5252:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   5253: 
                   5254:       /* First try to do it with a special MIN or MAX instruction.
                   5255:         If that does not win, use a conditional jump to select the proper
                   5256:         value.  */
                   5257:       this_optab = (TREE_UNSIGNED (type)
                   5258:                    ? (code == MIN_EXPR ? umin_optab : umax_optab)
                   5259:                    : (code == MIN_EXPR ? smin_optab : smax_optab));
                   5260: 
                   5261:       temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
                   5262:                           OPTAB_WIDEN);
                   5263:       if (temp != 0)
                   5264:        return temp;
                   5265: 
                   5266:       if (target != op0)
                   5267:        emit_move_insn (target, op0);
1.1.1.7 ! root     5268: 
1.1       root     5269:       op0 = gen_label_rtx ();
1.1.1.7 ! root     5270: 
1.1.1.5   root     5271:       /* If this mode is an integer too wide to compare properly,
                   5272:         compare word by word.  Rely on cse to optimize constant cases.  */
1.1.1.7 ! root     5273:       if (GET_MODE_CLASS (mode) == MODE_INT && !can_compare_p (mode))
1.1       root     5274:        {
1.1.1.5   root     5275:          if (code == MAX_EXPR)
1.1.1.7 ! root     5276:            do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
        !          5277:                                          target, op1, NULL_RTX, op0);
1.1       root     5278:          else
1.1.1.7 ! root     5279:            do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
        !          5280:                                          op1, target, NULL_RTX, op0);
1.1       root     5281:          emit_move_insn (target, op1);
                   5282:        }
1.1.1.5   root     5283:       else
                   5284:        {
                   5285:          if (code == MAX_EXPR)
                   5286:            temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
                   5287:                    ? compare_from_rtx (target, op1, GEU, 1, mode, NULL_RTX, 0)
                   5288:                    : compare_from_rtx (target, op1, GE, 0, mode, NULL_RTX, 0));
                   5289:          else
                   5290:            temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
                   5291:                    ? compare_from_rtx (target, op1, LEU, 1, mode, NULL_RTX, 0)
                   5292:                    : compare_from_rtx (target, op1, LE, 0, mode, NULL_RTX, 0));
                   5293:          if (temp == const0_rtx)
                   5294:            emit_move_insn (target, op1);
                   5295:          else if (temp != const_true_rtx)
                   5296:            {
                   5297:              if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
                   5298:                emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op0));
                   5299:              else
                   5300:                abort ();
                   5301:              emit_move_insn (target, op1);
                   5302:            }
                   5303:        }
1.1       root     5304:       emit_label (op0);
                   5305:       return target;
                   5306: 
                   5307:     case BIT_NOT_EXPR:
                   5308:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   5309:       temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
                   5310:       if (temp == 0)
                   5311:        abort ();
                   5312:       return temp;
                   5313: 
                   5314:     case FFS_EXPR:
                   5315:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   5316:       temp = expand_unop (mode, ffs_optab, op0, target, 1);
                   5317:       if (temp == 0)
                   5318:        abort ();
                   5319:       return temp;
                   5320: 
1.1.1.7 ! root     5321:       /* ??? Can optimize bitwise operations with one arg constant.
        !          5322:         Can optimize (a bitwise1 n) bitwise2 (a bitwise3 b)
        !          5323:         and (a bitwise1 b) bitwise2 b (etc)
        !          5324:         but that is probably not worth while.  */
        !          5325: 
        !          5326:       /* BIT_AND_EXPR is for bitwise anding.  TRUTH_AND_EXPR is for anding two
        !          5327:         boolean values when we want in all cases to compute both of them.  In
        !          5328:         general it is fastest to do TRUTH_AND_EXPR by computing both operands
        !          5329:         as actual zero-or-1 values and then bitwise anding.  In cases where
        !          5330:         there cannot be any side effects, better code would be made by
        !          5331:         treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR; but the question is
        !          5332:         how to recognize those cases.  */
1.1       root     5333: 
                   5334:     case TRUTH_AND_EXPR:
                   5335:     case BIT_AND_EXPR:
                   5336:       this_optab = and_optab;
                   5337:       goto binop;
                   5338: 
                   5339:     case TRUTH_OR_EXPR:
                   5340:     case BIT_IOR_EXPR:
                   5341:       this_optab = ior_optab;
                   5342:       goto binop;
                   5343: 
1.1.1.5   root     5344:     case TRUTH_XOR_EXPR:
1.1       root     5345:     case BIT_XOR_EXPR:
                   5346:       this_optab = xor_optab;
                   5347:       goto binop;
                   5348: 
                   5349:     case LSHIFT_EXPR:
                   5350:     case RSHIFT_EXPR:
                   5351:     case LROTATE_EXPR:
                   5352:     case RROTATE_EXPR:
                   5353:       preexpand_calls (exp);
                   5354:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   5355:        subtarget = 0;
                   5356:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   5357:       return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
                   5358:                           unsignedp);
                   5359: 
1.1.1.7 ! root     5360:       /* Could determine the answer when only additive constants differ.  Also,
        !          5361:         the addition of one can be handled by changing the condition.  */
1.1       root     5362:     case LT_EXPR:
                   5363:     case LE_EXPR:
                   5364:     case GT_EXPR:
                   5365:     case GE_EXPR:
                   5366:     case EQ_EXPR:
                   5367:     case NE_EXPR:
                   5368:       preexpand_calls (exp);
                   5369:       temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0);
                   5370:       if (temp != 0)
                   5371:        return temp;
1.1.1.7 ! root     5372: 
1.1       root     5373:       /* For foo != 0, load foo, and if it is nonzero load 1 instead. */
                   5374:       if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
                   5375:          && original_target
                   5376:          && GET_CODE (original_target) == REG
                   5377:          && (GET_MODE (original_target)
                   5378:              == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   5379:        {
1.1.1.7 ! root     5380:          temp = expand_expr (TREE_OPERAND (exp, 0), original_target,
        !          5381:                              VOIDmode, 0);
        !          5382: 
1.1       root     5383:          if (temp != original_target)
                   5384:            temp = copy_to_reg (temp);
1.1.1.7 ! root     5385: 
1.1       root     5386:          op1 = gen_label_rtx ();
1.1.1.4   root     5387:          emit_cmp_insn (temp, const0_rtx, EQ, NULL_RTX,
1.1       root     5388:                         GET_MODE (temp), unsignedp, 0);
                   5389:          emit_jump_insn (gen_beq (op1));
                   5390:          emit_move_insn (temp, const1_rtx);
                   5391:          emit_label (op1);
                   5392:          return temp;
                   5393:        }
1.1.1.7 ! root     5394: 
1.1       root     5395:       /* If no set-flag instruction, must generate a conditional
                   5396:         store into a temporary variable.  Drop through
                   5397:         and handle this like && and ||.  */
                   5398: 
                   5399:     case TRUTH_ANDIF_EXPR:
                   5400:     case TRUTH_ORIF_EXPR:
1.1.1.6   root     5401:       if (! ignore
                   5402:          && (target == 0 || ! safe_from_p (target, exp)
                   5403:              /* Make sure we don't have a hard reg (such as function's return
                   5404:                 value) live across basic blocks, if not optimizing.  */
                   5405:              || (!optimize && GET_CODE (target) == REG
                   5406:                  && REGNO (target) < FIRST_PSEUDO_REGISTER)))
1.1       root     5407:        target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
1.1.1.6   root     5408: 
                   5409:       if (target)
                   5410:        emit_clr_insn (target);
                   5411: 
1.1       root     5412:       op1 = gen_label_rtx ();
                   5413:       jumpifnot (exp, op1);
1.1.1.6   root     5414: 
                   5415:       if (target)
                   5416:        emit_0_to_1_insn (target);
                   5417: 
1.1       root     5418:       emit_label (op1);
1.1.1.6   root     5419:       return ignore ? const0_rtx : target;
1.1       root     5420: 
                   5421:     case TRUTH_NOT_EXPR:
                   5422:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   5423:       /* The parser is careful to generate TRUTH_NOT_EXPR
                   5424:         only with operands that are always zero or one.  */
1.1.1.4   root     5425:       temp = expand_binop (mode, xor_optab, op0, const1_rtx,
1.1       root     5426:                           target, 1, OPTAB_LIB_WIDEN);
                   5427:       if (temp == 0)
                   5428:        abort ();
                   5429:       return temp;
                   5430: 
                   5431:     case COMPOUND_EXPR:
                   5432:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
                   5433:       emit_queue ();
                   5434:       return expand_expr (TREE_OPERAND (exp, 1),
                   5435:                          (ignore ? const0_rtx : target),
                   5436:                          VOIDmode, 0);
                   5437: 
                   5438:     case COND_EXPR:
                   5439:       {
1.1.1.7 ! root     5440:        rtx flag = NULL_RTX;
        !          5441:        tree left_cleanups = NULL_TREE;
        !          5442:        tree right_cleanups = NULL_TREE;
        !          5443: 
        !          5444:        /* Used to save a pointer to the place to put the setting of
        !          5445:           the flag that indicates if this side of the conditional was
        !          5446:           taken.  We backpatch the code, if we find out later that we
        !          5447:           have any conditional cleanups that need to be performed. */
        !          5448:        rtx dest_right_flag = NULL_RTX;
        !          5449:        rtx dest_left_flag = NULL_RTX;
        !          5450: 
1.1       root     5451:        /* Note that COND_EXPRs whose type is a structure or union
                   5452:           are required to be constructed to contain assignments of
                   5453:           a temporary variable, so that we can evaluate them here
                   5454:           for side effect only.  If type is void, we must do likewise.  */
                   5455: 
                   5456:        /* If an arm of the branch requires a cleanup,
                   5457:           only that cleanup is performed.  */
                   5458: 
                   5459:        tree singleton = 0;
                   5460:        tree binary_op = 0, unary_op = 0;
                   5461:        tree old_cleanups = cleanups_this_call;
                   5462: 
                   5463:        /* If this is (A ? 1 : 0) and A is a condition, just evaluate it and
                   5464:           convert it to our mode, if necessary.  */
                   5465:        if (integer_onep (TREE_OPERAND (exp, 1))
                   5466:            && integer_zerop (TREE_OPERAND (exp, 2))
                   5467:            && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
                   5468:          {
1.1.1.6   root     5469:            if (ignore)
                   5470:              {
                   5471:                expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
                   5472:                             modifier);
                   5473:                return const0_rtx;
                   5474:              }
                   5475: 
1.1       root     5476:            op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier);
                   5477:            if (GET_MODE (op0) == mode)
                   5478:              return op0;
1.1.1.7 ! root     5479: 
1.1       root     5480:            if (target == 0)
                   5481:              target = gen_reg_rtx (mode);
                   5482:            convert_move (target, op0, unsignedp);
                   5483:            return target;
                   5484:          }
                   5485: 
                   5486:        /* If we are not to produce a result, we have no target.  Otherwise,
                   5487:           if a target was specified use it; it will not be used as an
                   5488:           intermediate target unless it is safe.  If no target, use a 
                   5489:           temporary.  */
                   5490: 
1.1.1.6   root     5491:        if (ignore)
1.1       root     5492:          temp = 0;
                   5493:        else if (original_target
1.1.1.7 ! root     5494:                 && safe_from_p (original_target, TREE_OPERAND (exp, 0))
        !          5495:                 && GET_MODE (original_target) == mode
        !          5496:                 && ! (GET_CODE (original_target) == MEM
        !          5497:                       && MEM_VOLATILE_P (original_target)))
1.1       root     5498:          temp = original_target;
                   5499:        else if (mode == BLKmode)
                   5500:          {
                   5501:            if (TYPE_SIZE (type) == 0
                   5502:                || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
                   5503:              abort ();
1.1.1.6   root     5504: 
1.1       root     5505:            temp = assign_stack_temp (BLKmode,
                   5506:                                      (TREE_INT_CST_LOW (TYPE_SIZE (type))
                   5507:                                       + BITS_PER_UNIT - 1)
                   5508:                                      / BITS_PER_UNIT, 0);
1.1.1.7 ! root     5509:            MEM_IN_STRUCT_P (temp) = AGGREGATE_TYPE_P (type);
1.1       root     5510:          }
                   5511:        else
                   5512:          temp = gen_reg_rtx (mode);
                   5513: 
                   5514:        /* Check for X ? A + B : A.  If we have this, we can copy
                   5515:           A to the output and conditionally add B.  Similarly for unary
                   5516:           operations.  Don't do this if X has side-effects because
                   5517:           those side effects might affect A or B and the "?" operation is
                   5518:           a sequence point in ANSI.  (We test for side effects later.)  */
                   5519: 
                   5520:        if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '2'
                   5521:            && operand_equal_p (TREE_OPERAND (exp, 2),
                   5522:                                TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
                   5523:          singleton = TREE_OPERAND (exp, 2), binary_op = TREE_OPERAND (exp, 1);
                   5524:        else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '2'
                   5525:                 && operand_equal_p (TREE_OPERAND (exp, 1),
                   5526:                                     TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
                   5527:          singleton = TREE_OPERAND (exp, 1), binary_op = TREE_OPERAND (exp, 2);
                   5528:        else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '1'
                   5529:                 && operand_equal_p (TREE_OPERAND (exp, 2),
                   5530:                                     TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
                   5531:          singleton = TREE_OPERAND (exp, 2), unary_op = TREE_OPERAND (exp, 1);
                   5532:        else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '1'
                   5533:                 && operand_equal_p (TREE_OPERAND (exp, 1),
                   5534:                                     TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
                   5535:          singleton = TREE_OPERAND (exp, 1), unary_op = TREE_OPERAND (exp, 2);
                   5536: 
                   5537:        /* If we had X ? A + 1 : A and we can do the test of X as a store-flag
                   5538:           operation, do this as A + (X != 0).  Similarly for other simple
                   5539:           binary operators.  */
1.1.1.6   root     5540:        if (temp && singleton && binary_op
1.1       root     5541:            && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
                   5542:            && (TREE_CODE (binary_op) == PLUS_EXPR
                   5543:                || TREE_CODE (binary_op) == MINUS_EXPR
                   5544:                || TREE_CODE (binary_op) == BIT_IOR_EXPR
1.1.1.7 ! root     5545:                || TREE_CODE (binary_op) == BIT_XOR_EXPR)
1.1       root     5546:            && integer_onep (TREE_OPERAND (binary_op, 1))
                   5547:            && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
                   5548:          {
                   5549:            rtx result;
                   5550:            optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab
                   5551:                            : TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab
                   5552:                            : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
1.1.1.7 ! root     5553:                            : xor_optab);
1.1       root     5554: 
                   5555:            /* If we had X ? A : A + 1, do this as A + (X == 0).
                   5556: 
                   5557:               We have to invert the truth value here and then put it
                   5558:               back later if do_store_flag fails.  We cannot simply copy
                   5559:               TREE_OPERAND (exp, 0) to another variable and modify that
                   5560:               because invert_truthvalue can modify the tree pointed to
                   5561:               by its argument.  */
                   5562:            if (singleton == TREE_OPERAND (exp, 1))
                   5563:              TREE_OPERAND (exp, 0)
                   5564:                = invert_truthvalue (TREE_OPERAND (exp, 0));
                   5565: 
                   5566:            result = do_store_flag (TREE_OPERAND (exp, 0),
1.1.1.4   root     5567:                                    (safe_from_p (temp, singleton)
                   5568:                                     ? temp : NULL_RTX),
1.1       root     5569:                                    mode, BRANCH_COST <= 1);
                   5570: 
                   5571:            if (result)
                   5572:              {
1.1.1.4   root     5573:                op1 = expand_expr (singleton, NULL_RTX, VOIDmode, 0);
1.1       root     5574:                return expand_binop (mode, boptab, op1, result, temp,
                   5575:                                     unsignedp, OPTAB_LIB_WIDEN);
                   5576:              }
                   5577:            else if (singleton == TREE_OPERAND (exp, 1))
                   5578:              TREE_OPERAND (exp, 0)
                   5579:                = invert_truthvalue (TREE_OPERAND (exp, 0));
                   5580:          }
                   5581:            
                   5582:        NO_DEFER_POP;
                   5583:        op0 = gen_label_rtx ();
                   5584: 
1.1.1.7 ! root     5585:        flag = gen_reg_rtx (word_mode);
1.1       root     5586:        if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
                   5587:          {
                   5588:            if (temp != 0)
                   5589:              {
                   5590:                /* If the target conflicts with the other operand of the
                   5591:                   binary op, we can't use it.  Also, we can't use the target
                   5592:                   if it is a hard register, because evaluating the condition
                   5593:                   might clobber it.  */
                   5594:                if ((binary_op
                   5595:                     && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1)))
                   5596:                    || (GET_CODE (temp) == REG
                   5597:                        && REGNO (temp) < FIRST_PSEUDO_REGISTER))
                   5598:                  temp = gen_reg_rtx (mode);
                   5599:                store_expr (singleton, temp, 0);
                   5600:              }
                   5601:            else
1.1.1.4   root     5602:              expand_expr (singleton,
1.1.1.5   root     5603:                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
1.1.1.7 ! root     5604:            dest_left_flag = get_last_insn ();
1.1       root     5605:            if (singleton == TREE_OPERAND (exp, 1))
                   5606:              jumpif (TREE_OPERAND (exp, 0), op0);
                   5607:            else
                   5608:              jumpifnot (TREE_OPERAND (exp, 0), op0);
                   5609: 
1.1.1.7 ! root     5610:            /* Allows cleanups up to here. */
        !          5611:            old_cleanups = cleanups_this_call;
1.1       root     5612:            if (binary_op && temp == 0)
                   5613:              /* Just touch the other operand.  */
                   5614:              expand_expr (TREE_OPERAND (binary_op, 1),
1.1.1.4   root     5615:                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
1.1       root     5616:            else if (binary_op)
                   5617:              store_expr (build (TREE_CODE (binary_op), type,
                   5618:                                 make_tree (type, temp),
                   5619:                                 TREE_OPERAND (binary_op, 1)),
                   5620:                          temp, 0);
                   5621:            else
                   5622:              store_expr (build1 (TREE_CODE (unary_op), type,
                   5623:                                  make_tree (type, temp)),
                   5624:                          temp, 0);
                   5625:            op1 = op0;
1.1.1.7 ! root     5626:            dest_right_flag = get_last_insn ();
1.1       root     5627:          }
                   5628: #if 0
                   5629:        /* This is now done in jump.c and is better done there because it
                   5630:           produces shorter register lifetimes.  */
                   5631:           
                   5632:        /* Check for both possibilities either constants or variables
                   5633:           in registers (but not the same as the target!).  If so, can
                   5634:           save branches by assigning one, branching, and assigning the
                   5635:           other.  */
                   5636:        else if (temp && GET_MODE (temp) != BLKmode
                   5637:                 && (TREE_CONSTANT (TREE_OPERAND (exp, 1))
                   5638:                     || ((TREE_CODE (TREE_OPERAND (exp, 1)) == PARM_DECL
                   5639:                          || TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL)
                   5640:                         && DECL_RTL (TREE_OPERAND (exp, 1))
                   5641:                         && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 1))) == REG
                   5642:                         && DECL_RTL (TREE_OPERAND (exp, 1)) != temp))
                   5643:                 && (TREE_CONSTANT (TREE_OPERAND (exp, 2))
                   5644:                     || ((TREE_CODE (TREE_OPERAND (exp, 2)) == PARM_DECL
                   5645:                          || TREE_CODE (TREE_OPERAND (exp, 2)) == VAR_DECL)
                   5646:                         && DECL_RTL (TREE_OPERAND (exp, 2))
                   5647:                         && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 2))) == REG
                   5648:                         && DECL_RTL (TREE_OPERAND (exp, 2)) != temp)))
                   5649:          {
                   5650:            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
                   5651:              temp = gen_reg_rtx (mode);
                   5652:            store_expr (TREE_OPERAND (exp, 2), temp, 0);
1.1.1.7 ! root     5653:            dest_left_flag = get_last_insn ();
1.1       root     5654:            jumpifnot (TREE_OPERAND (exp, 0), op0);
1.1.1.7 ! root     5655: 
        !          5656:            /* Allows cleanups up to here. */
        !          5657:            old_cleanups = cleanups_this_call;
1.1       root     5658:            store_expr (TREE_OPERAND (exp, 1), temp, 0);
                   5659:            op1 = op0;
1.1.1.7 ! root     5660:            dest_right_flag = get_last_insn ();
1.1       root     5661:          }
                   5662: #endif
                   5663:        /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any
                   5664:           comparison operator.  If we have one of these cases, set the
                   5665:           output to A, branch on A (cse will merge these two references),
                   5666:           then set the output to FOO.  */
                   5667:        else if (temp
                   5668:                 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
                   5669:                 && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
                   5670:                 && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                   5671:                                     TREE_OPERAND (exp, 1), 0)
                   5672:                 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
                   5673:                 && safe_from_p (temp, TREE_OPERAND (exp, 2)))
                   5674:          {
                   5675:            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
                   5676:              temp = gen_reg_rtx (mode);
                   5677:            store_expr (TREE_OPERAND (exp, 1), temp, 0);
1.1.1.7 ! root     5678:            dest_left_flag = get_last_insn ();
1.1       root     5679:            jumpif (TREE_OPERAND (exp, 0), op0);
1.1.1.7 ! root     5680: 
        !          5681:            /* Allows cleanups up to here. */
        !          5682:            old_cleanups = cleanups_this_call;
1.1       root     5683:            store_expr (TREE_OPERAND (exp, 2), temp, 0);
                   5684:            op1 = op0;
1.1.1.7 ! root     5685:            dest_right_flag = get_last_insn ();
1.1       root     5686:          }
                   5687:        else if (temp
                   5688:                 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
                   5689:                 && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
                   5690:                 && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                   5691:                                     TREE_OPERAND (exp, 2), 0)
                   5692:                 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
                   5693:                 && safe_from_p (temp, TREE_OPERAND (exp, 1)))
                   5694:          {
                   5695:            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
                   5696:              temp = gen_reg_rtx (mode);
                   5697:            store_expr (TREE_OPERAND (exp, 2), temp, 0);
1.1.1.7 ! root     5698:            dest_left_flag = get_last_insn ();
1.1       root     5699:            jumpifnot (TREE_OPERAND (exp, 0), op0);
1.1.1.7 ! root     5700: 
        !          5701:            /* Allows cleanups up to here. */
        !          5702:            old_cleanups = cleanups_this_call;
1.1       root     5703:            store_expr (TREE_OPERAND (exp, 1), temp, 0);
                   5704:            op1 = op0;
1.1.1.7 ! root     5705:            dest_right_flag = get_last_insn ();
1.1       root     5706:          }
                   5707:        else
                   5708:          {
                   5709:            op1 = gen_label_rtx ();
                   5710:            jumpifnot (TREE_OPERAND (exp, 0), op0);
1.1.1.7 ! root     5711: 
        !          5712:            /* Allows cleanups up to here. */
        !          5713:            old_cleanups = cleanups_this_call;
1.1       root     5714:            if (temp != 0)
                   5715:              store_expr (TREE_OPERAND (exp, 1), temp, 0);
                   5716:            else
1.1.1.4   root     5717:              expand_expr (TREE_OPERAND (exp, 1),
                   5718:                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
1.1.1.7 ! root     5719:            dest_left_flag = get_last_insn ();
        !          5720: 
        !          5721:            /* Handle conditional cleanups, if any. */
        !          5722:            left_cleanups = defer_cleanups_to (old_cleanups);
1.1       root     5723: 
                   5724:            emit_queue ();
                   5725:            emit_jump_insn (gen_jump (op1));
                   5726:            emit_barrier ();
                   5727:            emit_label (op0);
                   5728:            if (temp != 0)
                   5729:              store_expr (TREE_OPERAND (exp, 2), temp, 0);
                   5730:            else
1.1.1.4   root     5731:              expand_expr (TREE_OPERAND (exp, 2),
                   5732:                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
1.1.1.7 ! root     5733:            dest_right_flag = get_last_insn ();
1.1       root     5734:          }
                   5735: 
1.1.1.7 ! root     5736:        /* Handle conditional cleanups, if any. */
        !          5737:        right_cleanups = defer_cleanups_to (old_cleanups);
1.1       root     5738: 
                   5739:        emit_queue ();
                   5740:        emit_label (op1);
                   5741:        OK_DEFER_POP;
1.1.1.7 ! root     5742: 
        !          5743:        /* Add back in, any conditional cleanups. */
        !          5744:        if (left_cleanups || right_cleanups)
        !          5745:          {
        !          5746:            tree new_cleanups;
        !          5747:            tree cond;
        !          5748:            rtx last;
        !          5749: 
        !          5750:            /* Now that we know that a flag is needed, go back and add in the
        !          5751:               setting of the flag. */
        !          5752: 
        !          5753:            /* Do the left side flag. */
        !          5754:            last = get_last_insn ();
        !          5755:            /* Flag left cleanups as needed. */
        !          5756:            emit_move_insn (flag, const1_rtx);
        !          5757:            /* ??? deprecated, use sequences instead.  */
        !          5758:            reorder_insns (NEXT_INSN (last), get_last_insn (), dest_left_flag);
        !          5759: 
        !          5760:            /* Do the right side flag. */
        !          5761:            last = get_last_insn ();
        !          5762:            /* Flag left cleanups as needed. */
        !          5763:            emit_move_insn (flag, const0_rtx);
        !          5764:            /* ??? deprecated, use sequences instead.  */
        !          5765:            reorder_insns (NEXT_INSN (last), get_last_insn (), dest_right_flag);
        !          5766: 
        !          5767:            /* convert flag, which is an rtx, into a tree. */
        !          5768:            cond = make_node (RTL_EXPR);
        !          5769:            TREE_TYPE (cond) = integer_type_node;
        !          5770:            RTL_EXPR_RTL (cond) = flag;
        !          5771:            RTL_EXPR_SEQUENCE (cond) = NULL_RTX;
        !          5772: 
        !          5773:            if (! left_cleanups)
        !          5774:              left_cleanups = integer_zero_node;
        !          5775:            if (! right_cleanups)
        !          5776:              right_cleanups = integer_zero_node;
        !          5777:            new_cleanups = build (COND_EXPR, void_type_node,
        !          5778:                                  truthvalue_conversion (cond),
        !          5779:                                  left_cleanups, right_cleanups);
        !          5780:            new_cleanups = fold (new_cleanups);
        !          5781: 
        !          5782:            /* Now add in the conditionalized cleanups. */
        !          5783:            cleanups_this_call
        !          5784:              = tree_cons (NULL_TREE, new_cleanups, cleanups_this_call);
        !          5785:            (*interim_eh_hook) (NULL_TREE);
        !          5786:          }
1.1       root     5787:        return temp;
                   5788:       }
                   5789: 
                   5790:     case TARGET_EXPR:
                   5791:       {
1.1.1.7 ! root     5792:        int need_exception_region = 0;
1.1       root     5793:        /* Something needs to be initialized, but we didn't know
                   5794:           where that thing was when building the tree.  For example,
                   5795:           it could be the return value of a function, or a parameter
                   5796:           to a function which lays down in the stack, or a temporary
                   5797:           variable which must be passed by reference.
                   5798: 
                   5799:           We guarantee that the expression will either be constructed
                   5800:           or copied into our original target.  */
                   5801: 
                   5802:        tree slot = TREE_OPERAND (exp, 0);
1.1.1.4   root     5803:        tree exp1;
1.1.1.7 ! root     5804:        rtx temp;
1.1       root     5805: 
                   5806:        if (TREE_CODE (slot) != VAR_DECL)
                   5807:          abort ();
                   5808: 
                   5809:        if (target == 0)
                   5810:          {
                   5811:            if (DECL_RTL (slot) != 0)
1.1.1.4   root     5812:              {
                   5813:                target = DECL_RTL (slot);
                   5814:                /* If we have already expanded the slot, so don't do
                   5815:                   it again.  (mrs)  */
                   5816:                if (TREE_OPERAND (exp, 1) == NULL_TREE)
                   5817:                  return target;
                   5818:              }
1.1       root     5819:            else
                   5820:              {
1.1.1.7 ! root     5821:                target = assign_stack_temp (mode, int_size_in_bytes (type), 2);
1.1       root     5822:                /* All temp slots at this level must not conflict.  */
                   5823:                preserve_temp_slots (target);
                   5824:                DECL_RTL (slot) = target;
                   5825: 
1.1.1.6   root     5826:                /* Since SLOT is not known to the called function
                   5827:                   to belong to its stack frame, we must build an explicit
                   5828:                   cleanup.  This case occurs when we must build up a reference
                   5829:                   to pass the reference as an argument.  In this case,
                   5830:                   it is very likely that such a reference need not be
                   5831:                   built here.  */
                   5832: 
                   5833:                if (TREE_OPERAND (exp, 2) == 0)
                   5834:                  TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot);
                   5835:                if (TREE_OPERAND (exp, 2))
1.1.1.7 ! root     5836:                  {
        !          5837:                    cleanups_this_call = tree_cons (NULL_TREE,
        !          5838:                                                    TREE_OPERAND (exp, 2),
        !          5839:                                                    cleanups_this_call);
        !          5840:                    need_exception_region = 1;
        !          5841:                  }
1.1.1.6   root     5842:              }
1.1       root     5843:          }
                   5844:        else
                   5845:          {
                   5846:            /* This case does occur, when expanding a parameter which
                   5847:               needs to be constructed on the stack.  The target
                   5848:               is the actual stack address that we want to initialize.
                   5849:               The function we call will perform the cleanup in this case.  */
                   5850: 
1.1.1.5   root     5851:            /* If we have already assigned it space, use that space,
                   5852:               not target that we were passed in, as our target
                   5853:               parameter is only a hint.  */
                   5854:            if (DECL_RTL (slot) != 0)
                   5855:               {
                   5856:                 target = DECL_RTL (slot);
                   5857:                 /* If we have already expanded the slot, so don't do
                   5858:                    it again.  (mrs)  */
                   5859:                 if (TREE_OPERAND (exp, 1) == NULL_TREE)
                   5860:                   return target;
                   5861:              }
                   5862: 
1.1       root     5863:            DECL_RTL (slot) = target;
                   5864:          }
                   5865: 
1.1.1.4   root     5866:        exp1 = TREE_OPERAND (exp, 1);
                   5867:        /* Mark it as expanded.  */
                   5868:        TREE_OPERAND (exp, 1) = NULL_TREE;
                   5869: 
1.1.1.7 ! root     5870:        temp = expand_expr (exp1, target, tmode, modifier);
        !          5871: 
        !          5872:        if (need_exception_region)
        !          5873:          (*interim_eh_hook) (NULL_TREE);
        !          5874:        
        !          5875:        return temp;
1.1       root     5876:       }
                   5877: 
                   5878:     case INIT_EXPR:
                   5879:       {
                   5880:        tree lhs = TREE_OPERAND (exp, 0);
                   5881:        tree rhs = TREE_OPERAND (exp, 1);
                   5882:        tree noncopied_parts = 0;
                   5883:        tree lhs_type = TREE_TYPE (lhs);
                   5884: 
                   5885:        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
                   5886:        if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 && !fixed_type_p (rhs))
                   5887:          noncopied_parts = init_noncopied_parts (stabilize_reference (lhs),
                   5888:                                                  TYPE_NONCOPIED_PARTS (lhs_type));
                   5889:        while (noncopied_parts != 0)
                   5890:          {
                   5891:            expand_assignment (TREE_VALUE (noncopied_parts),
                   5892:                               TREE_PURPOSE (noncopied_parts), 0, 0);
                   5893:            noncopied_parts = TREE_CHAIN (noncopied_parts);
                   5894:          }
                   5895:        return temp;
                   5896:       }
                   5897: 
                   5898:     case MODIFY_EXPR:
                   5899:       {
                   5900:        /* If lhs is complex, expand calls in rhs before computing it.
                   5901:           That's so we don't compute a pointer and save it over a call.
                   5902:           If lhs is simple, compute it first so we can give it as a
                   5903:           target if the rhs is just a call.  This avoids an extra temp and copy
                   5904:           and that prevents a partial-subsumption which makes bad code.
                   5905:           Actually we could treat component_ref's of vars like vars.  */
                   5906: 
                   5907:        tree lhs = TREE_OPERAND (exp, 0);
                   5908:        tree rhs = TREE_OPERAND (exp, 1);
                   5909:        tree noncopied_parts = 0;
                   5910:        tree lhs_type = TREE_TYPE (lhs);
                   5911: 
                   5912:        temp = 0;
                   5913: 
                   5914:        if (TREE_CODE (lhs) != VAR_DECL
                   5915:            && TREE_CODE (lhs) != RESULT_DECL
                   5916:            && TREE_CODE (lhs) != PARM_DECL)
                   5917:          preexpand_calls (exp);
                   5918: 
                   5919:        /* Check for |= or &= of a bitfield of size one into another bitfield
                   5920:           of size 1.  In this case, (unless we need the result of the
                   5921:           assignment) we can do this more efficiently with a
                   5922:           test followed by an assignment, if necessary.
                   5923: 
                   5924:           ??? At this point, we can't get a BIT_FIELD_REF here.  But if
                   5925:           things change so we do, this code should be enhanced to
                   5926:           support it.  */
                   5927:        if (ignore
                   5928:            && TREE_CODE (lhs) == COMPONENT_REF
                   5929:            && (TREE_CODE (rhs) == BIT_IOR_EXPR
                   5930:                || TREE_CODE (rhs) == BIT_AND_EXPR)
                   5931:            && TREE_OPERAND (rhs, 0) == lhs
                   5932:            && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
                   5933:            && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (lhs, 1))) == 1
                   5934:            && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))) == 1)
                   5935:          {
                   5936:            rtx label = gen_label_rtx ();
                   5937: 
                   5938:            do_jump (TREE_OPERAND (rhs, 1),
                   5939:                     TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0,
                   5940:                     TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0);
                   5941:            expand_assignment (lhs, convert (TREE_TYPE (rhs),
                   5942:                                             (TREE_CODE (rhs) == BIT_IOR_EXPR
                   5943:                                              ? integer_one_node
                   5944:                                              : integer_zero_node)),
                   5945:                               0, 0);
1.1.1.3   root     5946:            do_pending_stack_adjust ();
1.1       root     5947:            emit_label (label);
                   5948:            return const0_rtx;
                   5949:          }
                   5950: 
                   5951:        if (TYPE_NONCOPIED_PARTS (lhs_type) != 0
                   5952:            && ! (fixed_type_p (lhs) && fixed_type_p (rhs)))
                   5953:          noncopied_parts = save_noncopied_parts (stabilize_reference (lhs),
                   5954:                                                  TYPE_NONCOPIED_PARTS (lhs_type));
                   5955: 
                   5956:        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
                   5957:        while (noncopied_parts != 0)
                   5958:          {
                   5959:            expand_assignment (TREE_PURPOSE (noncopied_parts),
                   5960:                               TREE_VALUE (noncopied_parts), 0, 0);
                   5961:            noncopied_parts = TREE_CHAIN (noncopied_parts);
                   5962:          }
                   5963:        return temp;
                   5964:       }
                   5965: 
                   5966:     case PREINCREMENT_EXPR:
                   5967:     case PREDECREMENT_EXPR:
                   5968:       return expand_increment (exp, 0);
                   5969: 
                   5970:     case POSTINCREMENT_EXPR:
                   5971:     case POSTDECREMENT_EXPR:
                   5972:       /* Faster to treat as pre-increment if result is not used.  */
                   5973:       return expand_increment (exp, ! ignore);
                   5974: 
                   5975:     case ADDR_EXPR:
1.1.1.7 ! root     5976:       /* If nonzero, TEMP will be set to the address of something that might
        !          5977:         be a MEM corresponding to a stack slot. */
        !          5978:       temp = 0;
        !          5979: 
1.1       root     5980:       /* Are we taking the address of a nested function?  */
                   5981:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
                   5982:          && decl_function_context (TREE_OPERAND (exp, 0)) != 0)
                   5983:        {
                   5984:          op0 = trampoline_address (TREE_OPERAND (exp, 0));
                   5985:          op0 = force_operand (op0, target);
                   5986:        }
1.1.1.7 ! root     5987:       /* If we are taking the address of something erroneous, just
        !          5988:         return a zero.  */
        !          5989:       else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
        !          5990:        return const0_rtx;
1.1       root     5991:       else
                   5992:        {
1.1.1.6   root     5993:          /* We make sure to pass const0_rtx down if we came in with
                   5994:             ignore set, to avoid doing the cleanups twice for something.  */
                   5995:          op0 = expand_expr (TREE_OPERAND (exp, 0),
                   5996:                             ignore ? const0_rtx : NULL_RTX, VOIDmode,
1.1       root     5997:                             (modifier == EXPAND_INITIALIZER
                   5998:                              ? modifier : EXPAND_CONST_ADDRESS));
1.1.1.5   root     5999: 
1.1.1.7 ! root     6000:          /* If we are going to ignore the result, OP0 will have been set
        !          6001:             to const0_rtx, so just return it.  Don't get confused and
        !          6002:             think we are taking the address of the constant.  */
        !          6003:          if (ignore)
        !          6004:            return op0;
        !          6005: 
1.1.1.5   root     6006:          /* We would like the object in memory.  If it is a constant,
                   6007:             we can have it be statically allocated into memory.  For
1.1.1.7 ! root     6008:             a non-constant (REG, SUBREG or CONCAT), we need to allocate some
1.1.1.5   root     6009:             memory and store the value into it.  */
                   6010: 
                   6011:          if (CONSTANT_P (op0))
                   6012:            op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
                   6013:                                   op0);
1.1.1.7 ! root     6014:          else if (GET_CODE (op0) == MEM)
        !          6015:            {
        !          6016:              mark_temp_addr_taken (op0);
        !          6017:              temp = XEXP (op0, 0);
        !          6018:            }
1.1.1.5   root     6019: 
1.1.1.7 ! root     6020:          else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
        !          6021:                   || GET_CODE (op0) == CONCAT)
1.1.1.5   root     6022:            {
                   6023:              /* If this object is in a register, it must be not
                   6024:                 be BLKmode. */
                   6025:              tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
                   6026:              enum machine_mode inner_mode = TYPE_MODE (inner_type);
                   6027:              rtx memloc
                   6028:                = assign_stack_temp (inner_mode,
                   6029:                                     int_size_in_bytes (inner_type), 1);
                   6030: 
1.1.1.7 ! root     6031:              mark_temp_addr_taken (memloc);
1.1.1.5   root     6032:              emit_move_insn (memloc, op0);
                   6033:              op0 = memloc;
                   6034:            }
                   6035: 
1.1       root     6036:          if (GET_CODE (op0) != MEM)
                   6037:            abort ();
                   6038:   
                   6039:          if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
                   6040:            return XEXP (op0, 0);
1.1.1.7 ! root     6041: 
1.1       root     6042:          op0 = force_operand (XEXP (op0, 0), target);
                   6043:        }
1.1.1.7 ! root     6044: 
1.1       root     6045:       if (flag_force_addr && GET_CODE (op0) != REG)
1.1.1.7 ! root     6046:        op0 = force_reg (Pmode, op0);
        !          6047: 
        !          6048:       if (GET_CODE (op0) == REG)
        !          6049:        mark_reg_pointer (op0);
        !          6050: 
        !          6051:       /* If we might have had a temp slot, add an equivalent address
        !          6052:         for it.  */
        !          6053:       if (temp != 0)
        !          6054:        update_temp_slot_address (temp, op0);
        !          6055: 
1.1       root     6056:       return op0;
                   6057: 
                   6058:     case ENTRY_VALUE_EXPR:
                   6059:       abort ();
                   6060: 
1.1.1.4   root     6061:     /* COMPLEX type for Extended Pascal & Fortran  */
                   6062:     case COMPLEX_EXPR:
                   6063:       {
                   6064:        enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
1.1.1.7 ! root     6065:        rtx insns;
1.1.1.4   root     6066: 
                   6067:        /* Get the rtx code of the operands.  */
                   6068:        op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   6069:        op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   6070: 
                   6071:        if (! target)
                   6072:          target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
                   6073: 
1.1.1.7 ! root     6074:        start_sequence ();
1.1.1.4   root     6075: 
                   6076:        /* Move the real (op0) and imaginary (op1) parts to their location.  */
                   6077:        emit_move_insn (gen_realpart (mode, target), op0);
                   6078:        emit_move_insn (gen_imagpart (mode, target), op1);
                   6079: 
1.1.1.7 ! root     6080:        insns = get_insns ();
        !          6081:        end_sequence ();
        !          6082: 
1.1.1.4   root     6083:        /* Complex construction should appear as a single unit.  */
1.1.1.7 ! root     6084:        /* If TARGET is a CONCAT, we got insns like RD = RS, ID = IS,
        !          6085:           each with a separate pseudo as destination.
        !          6086:           It's not correct for flow to treat them as a unit.  */
1.1.1.6   root     6087:        if (GET_CODE (target) != CONCAT)
1.1.1.7 ! root     6088:          emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
        !          6089:        else
        !          6090:          emit_insns (insns);
1.1.1.4   root     6091: 
                   6092:        return target;
                   6093:       }
                   6094: 
                   6095:     case REALPART_EXPR:
                   6096:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   6097:       return gen_realpart (mode, op0);
                   6098:       
                   6099:     case IMAGPART_EXPR:
                   6100:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   6101:       return gen_imagpart (mode, op0);
                   6102: 
                   6103:     case CONJ_EXPR:
                   6104:       {
1.1.1.7 ! root     6105:        enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
1.1.1.4   root     6106:        rtx imag_t;
1.1.1.7 ! root     6107:        rtx insns;
1.1.1.4   root     6108:        
                   6109:        op0  = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   6110: 
                   6111:        if (! target)
1.1.1.7 ! root     6112:          target = gen_reg_rtx (mode);
1.1.1.4   root     6113:                                                                    
1.1.1.7 ! root     6114:        start_sequence ();
1.1.1.4   root     6115: 
                   6116:        /* Store the realpart and the negated imagpart to target.  */
1.1.1.7 ! root     6117:        emit_move_insn (gen_realpart (partmode, target),
        !          6118:                        gen_realpart (partmode, op0));
1.1.1.4   root     6119: 
1.1.1.7 ! root     6120:        imag_t = gen_imagpart (partmode, target);
        !          6121:        temp = expand_unop (partmode, neg_optab,
        !          6122:                               gen_imagpart (partmode, op0), imag_t, 0);
1.1.1.4   root     6123:        if (temp != imag_t)
                   6124:          emit_move_insn (imag_t, temp);
                   6125: 
1.1.1.7 ! root     6126:        insns = get_insns ();
        !          6127:        end_sequence ();
        !          6128: 
        !          6129:        /* Conjugate should appear as a single unit 
        !          6130:           If TARGET is a CONCAT, we got insns like RD = RS, ID = - IS,
        !          6131:           each with a separate pseudo as destination.
        !          6132:           It's not correct for flow to treat them as a unit.  */
1.1.1.6   root     6133:        if (GET_CODE (target) != CONCAT)
1.1.1.7 ! root     6134:          emit_no_conflict_block (insns, target, op0, NULL_RTX, NULL_RTX);
        !          6135:        else
        !          6136:          emit_insns (insns);
1.1.1.4   root     6137: 
                   6138:        return target;
                   6139:       }
                   6140: 
1.1       root     6141:     case ERROR_MARK:
1.1.1.5   root     6142:       op0 = CONST0_RTX (tmode);
                   6143:       if (op0 != 0)
                   6144:        return op0;
1.1       root     6145:       return const0_rtx;
                   6146: 
                   6147:     default:
1.1.1.6   root     6148:       return (*lang_expand_expr) (exp, original_target, tmode, modifier);
1.1       root     6149:     }
                   6150: 
                   6151:   /* Here to do an ordinary binary operator, generating an instruction
                   6152:      from the optab already placed in `this_optab'.  */
                   6153:  binop:
                   6154:   preexpand_calls (exp);
                   6155:   if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   6156:     subtarget = 0;
                   6157:   op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4   root     6158:   op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     6159:  binop2:
                   6160:   temp = expand_binop (mode, this_optab, op0, op1, target,
                   6161:                       unsignedp, OPTAB_LIB_WIDEN);
                   6162:   if (temp == 0)
                   6163:     abort ();
                   6164:   return temp;
                   6165: }
                   6166: 
                   6167: 
1.1.1.6   root     6168: /* Emit bytecode to evaluate the given expression EXP to the stack. */
                   6169: void
                   6170: bc_expand_expr (exp)
                   6171:     tree exp;
1.1       root     6172: {
1.1.1.6   root     6173:   enum tree_code code;
                   6174:   tree type, arg0;
                   6175:   rtx r;
                   6176:   struct binary_operator *binoptab;
                   6177:   struct unary_operator *unoptab;
                   6178:   struct increment_operator *incroptab;
                   6179:   struct bc_label *lab, *lab1;
                   6180:   enum bytecode_opcode opcode;
                   6181:   
                   6182:   
                   6183:   code = TREE_CODE (exp);
                   6184:   
                   6185:   switch (code)
                   6186:     {
                   6187:     case PARM_DECL:
                   6188:       
                   6189:       if (DECL_RTL (exp) == 0)
                   6190:        {
                   6191:          error_with_decl (exp, "prior parameter's size depends on `%s'");
                   6192:          return;
                   6193:        }
                   6194:       
                   6195:       bc_load_parmaddr (DECL_RTL (exp));
                   6196:       bc_load_memory (TREE_TYPE (exp), exp);
                   6197:       
                   6198:       return;
                   6199:       
                   6200:     case VAR_DECL:
                   6201:       
                   6202:       if (DECL_RTL (exp) == 0)
                   6203:        abort ();
                   6204:       
                   6205: #if 0
                   6206:       if (BYTECODE_LABEL (DECL_RTL (exp)))
                   6207:        bc_load_externaddr (DECL_RTL (exp));
                   6208:       else
                   6209:        bc_load_localaddr (DECL_RTL (exp));
                   6210: #endif
                   6211:       if (TREE_PUBLIC (exp))
                   6212:        bc_load_externaddr_id (DECL_ASSEMBLER_NAME (exp),
                   6213:                               BYTECODE_BC_LABEL (DECL_RTL (exp))->offset);
                   6214:       else
                   6215:        bc_load_localaddr (DECL_RTL (exp));
                   6216:       
                   6217:       bc_load_memory (TREE_TYPE (exp), exp);
                   6218:       return;
                   6219:       
                   6220:     case INTEGER_CST:
                   6221:       
                   6222: #ifdef DEBUG_PRINT_CODE
                   6223:       fprintf (stderr, " [%x]\n", TREE_INT_CST_LOW (exp));
                   6224: #endif
                   6225:       bc_emit_instruction (mode_to_const_map[(int) (DECL_BIT_FIELD (exp)
                   6226:                                             ? SImode
                   6227:                                             : TYPE_MODE (TREE_TYPE (exp)))],
                   6228:                           (HOST_WIDE_INT) TREE_INT_CST_LOW (exp));
                   6229:       return;
                   6230:       
                   6231:     case REAL_CST:
                   6232:       
                   6233: #if 0
                   6234: #ifdef DEBUG_PRINT_CODE
                   6235:       fprintf (stderr, " [%g]\n", (double) TREE_INT_CST_LOW (exp));
                   6236: #endif
                   6237:       /* FIX THIS: find a better way to pass real_cst's. -bson */
                   6238:       bc_emit_instruction (mode_to_const_map[TYPE_MODE (TREE_TYPE (exp))],
                   6239:                           (double) TREE_REAL_CST (exp));
                   6240: #else
                   6241:       abort ();
                   6242: #endif
                   6243: 
                   6244:       return;
                   6245:       
                   6246:     case CALL_EXPR:
                   6247:       
                   6248:       /* We build a call description vector describing the type of
                   6249:         the return value and of the arguments; this call vector,
                   6250:         together with a pointer to a location for the return value
                   6251:         and the base of the argument list, is passed to the low
                   6252:         level machine dependent call subroutine, which is responsible
                   6253:         for putting the arguments wherever real functions expect
                   6254:         them, as well as getting the return value back.  */
                   6255:       {
                   6256:        tree calldesc = 0, arg;
                   6257:        int nargs = 0, i;
                   6258:        rtx retval;
                   6259:        
                   6260:        /* Push the evaluated args on the evaluation stack in reverse
                   6261:           order.  Also make an entry for each arg in the calldesc
                   6262:           vector while we're at it.  */
                   6263:        
                   6264:        TREE_OPERAND (exp, 1) = nreverse (TREE_OPERAND (exp, 1));
                   6265:        
                   6266:        for (arg = TREE_OPERAND (exp, 1); arg; arg = TREE_CHAIN (arg))
                   6267:          {
                   6268:            ++nargs;
                   6269:            bc_expand_expr (TREE_VALUE (arg));
                   6270:            
                   6271:            calldesc = tree_cons ((tree) 0,
                   6272:                                  size_in_bytes (TREE_TYPE (TREE_VALUE (arg))),
                   6273:                                  calldesc);
                   6274:            calldesc = tree_cons ((tree) 0,
                   6275:                                  bc_runtime_type_code (TREE_TYPE (TREE_VALUE (arg))),
                   6276:                                  calldesc);
                   6277:          }
                   6278:        
                   6279:        TREE_OPERAND (exp, 1) = nreverse (TREE_OPERAND (exp, 1));
                   6280:        
                   6281:        /* Allocate a location for the return value and push its
                   6282:           address on the evaluation stack.  Also make an entry
                   6283:           at the front of the calldesc for the return value type. */
                   6284:        
                   6285:        type = TREE_TYPE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   6286:        retval = bc_allocate_local (int_size_in_bytes (type), TYPE_ALIGN (type));
                   6287:        bc_load_localaddr (retval);
                   6288:        
                   6289:        calldesc = tree_cons ((tree) 0, size_in_bytes (type), calldesc);
                   6290:        calldesc = tree_cons ((tree) 0, bc_runtime_type_code (type), calldesc);
                   6291:        
                   6292:        /* Prepend the argument count.  */
                   6293:        calldesc = tree_cons ((tree) 0,
                   6294:                              build_int_2 (nargs, 0),
                   6295:                              calldesc);
                   6296:        
                   6297:        /* Push the address of the call description vector on the stack.  */
                   6298:        calldesc = build_nt (CONSTRUCTOR, (tree) 0, calldesc);
                   6299:        TREE_TYPE (calldesc) = build_array_type (integer_type_node,
                   6300:                                                 build_index_type (build_int_2 (nargs * 2, 0)));
                   6301:        r = output_constant_def (calldesc);
                   6302:        bc_load_externaddr (r);
                   6303:        
                   6304:        /* Push the address of the function to be called. */
                   6305:        bc_expand_expr (TREE_OPERAND (exp, 0));
                   6306:        
                   6307:        /* Call the function, popping its address and the calldesc vector
                   6308:           address off the evaluation stack in the process.  */
                   6309:        bc_emit_instruction (call);
                   6310:        
                   6311:        /* Pop the arguments off the stack.  */
                   6312:        bc_adjust_stack (nargs);
                   6313:        
                   6314:        /* Load the return value onto the stack.  */
                   6315:        bc_load_localaddr (retval);
                   6316:        bc_load_memory (type, TREE_OPERAND (exp, 0));
                   6317:       }
                   6318:       return;
                   6319:       
                   6320:     case SAVE_EXPR:
                   6321:       
                   6322:       if (!SAVE_EXPR_RTL (exp))
                   6323:        {
                   6324:          /* First time around: copy to local variable */
                   6325:          SAVE_EXPR_RTL (exp) = bc_allocate_local (int_size_in_bytes (TREE_TYPE (exp)),
                   6326:                                                   TYPE_ALIGN (TREE_TYPE(exp)));
                   6327:          bc_expand_expr (TREE_OPERAND (exp, 0));
                   6328:          bc_emit_instruction (duplicate);
                   6329:          
                   6330:          bc_load_localaddr (SAVE_EXPR_RTL (exp));
                   6331:          bc_store_memory (TREE_TYPE (exp), TREE_OPERAND (exp, 0));
                   6332:        }
                   6333:       else
                   6334:        {
                   6335:          /* Consecutive reference: use saved copy */
                   6336:          bc_load_localaddr (SAVE_EXPR_RTL (exp));
                   6337:          bc_load_memory (TREE_TYPE (exp), TREE_OPERAND (exp, 0));
                   6338:        }
                   6339:       return;
                   6340:       
                   6341: #if 0
                   6342:       /* FIXME: the XXXX_STMT codes have been removed in GCC2, but
                   6343:         how are they handled instead? */
                   6344:     case LET_STMT:
                   6345:       
                   6346:       TREE_USED (exp) = 1;
                   6347:       bc_expand_expr (STMT_BODY (exp));
                   6348:       return;
                   6349: #endif
                   6350:       
                   6351:     case NOP_EXPR:
                   6352:     case CONVERT_EXPR:
                   6353:       
                   6354:       bc_expand_expr (TREE_OPERAND (exp, 0));
                   6355:       bc_expand_conversion (TREE_TYPE (TREE_OPERAND (exp, 0)), TREE_TYPE (exp));
                   6356:       return;
                   6357:       
                   6358:     case MODIFY_EXPR:
                   6359:       
                   6360:       expand_assignment (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), 0, 0);
                   6361:       return;
                   6362:       
                   6363:     case ADDR_EXPR:
                   6364:       
                   6365:       bc_expand_address (TREE_OPERAND (exp, 0));
                   6366:       return;
                   6367:       
                   6368:     case INDIRECT_REF:
                   6369:       
                   6370:       bc_expand_expr (TREE_OPERAND (exp, 0));
                   6371:       bc_load_memory (TREE_TYPE (exp), TREE_OPERAND (exp, 0));
                   6372:       return;
                   6373:       
                   6374:     case ARRAY_REF:
                   6375:       
                   6376:       bc_expand_expr (bc_canonicalize_array_ref (exp));
                   6377:       return;
                   6378:       
                   6379:     case COMPONENT_REF:
                   6380:       
                   6381:       bc_expand_component_address (exp);
                   6382:       
                   6383:       /* If we have a bitfield, generate a proper load */
                   6384:       bc_load_memory (TREE_TYPE (TREE_OPERAND (exp, 1)), TREE_OPERAND (exp, 1));
                   6385:       return;
                   6386:       
                   6387:     case COMPOUND_EXPR:
                   6388:       
                   6389:       bc_expand_expr (TREE_OPERAND (exp, 0));
                   6390:       bc_emit_instruction (drop);
                   6391:       bc_expand_expr (TREE_OPERAND (exp, 1));
                   6392:       return;
                   6393:       
                   6394:     case COND_EXPR:
                   6395:       
                   6396:       bc_expand_expr (TREE_OPERAND (exp, 0));
                   6397:       bc_expand_truth_conversion (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   6398:       lab = bc_get_bytecode_label ();
                   6399:       bc_emit_bytecode (xjumpifnot);
                   6400:       bc_emit_bytecode_labelref (lab);
                   6401:       
                   6402: #ifdef DEBUG_PRINT_CODE
                   6403:       fputc ('\n', stderr);
                   6404: #endif
                   6405:       bc_expand_expr (TREE_OPERAND (exp, 1));
                   6406:       lab1 = bc_get_bytecode_label ();
                   6407:       bc_emit_bytecode (jump);
                   6408:       bc_emit_bytecode_labelref (lab1);
                   6409:       
                   6410: #ifdef DEBUG_PRINT_CODE
                   6411:       fputc ('\n', stderr);
                   6412: #endif
                   6413:       
                   6414:       bc_emit_bytecode_labeldef (lab);
                   6415:       bc_expand_expr (TREE_OPERAND (exp, 2));
                   6416:       bc_emit_bytecode_labeldef (lab1);
                   6417:       return;
                   6418:       
                   6419:     case TRUTH_ANDIF_EXPR:
                   6420:       
                   6421:       opcode = xjumpifnot;
                   6422:       goto andorif;
                   6423:       
                   6424:     case TRUTH_ORIF_EXPR:
                   6425:       
                   6426:       opcode = xjumpif;
                   6427:       goto andorif;
                   6428:       
                   6429:     case PLUS_EXPR:
                   6430:       
                   6431:       binoptab = optab_plus_expr;
                   6432:       goto binop;
                   6433:       
                   6434:     case MINUS_EXPR:
                   6435:       
                   6436:       binoptab = optab_minus_expr;
                   6437:       goto binop;
                   6438:       
                   6439:     case MULT_EXPR:
                   6440:       
                   6441:       binoptab = optab_mult_expr;
                   6442:       goto binop;
                   6443:       
                   6444:     case TRUNC_DIV_EXPR:
                   6445:     case FLOOR_DIV_EXPR:
                   6446:     case CEIL_DIV_EXPR:
                   6447:     case ROUND_DIV_EXPR:
                   6448:     case EXACT_DIV_EXPR:
                   6449:       
                   6450:       binoptab = optab_trunc_div_expr;
                   6451:       goto binop;
                   6452:       
                   6453:     case TRUNC_MOD_EXPR:
                   6454:     case FLOOR_MOD_EXPR:
                   6455:     case CEIL_MOD_EXPR:
                   6456:     case ROUND_MOD_EXPR:
                   6457:       
                   6458:       binoptab = optab_trunc_mod_expr;
                   6459:       goto binop;
                   6460:       
                   6461:     case FIX_ROUND_EXPR:
                   6462:     case FIX_FLOOR_EXPR:
                   6463:     case FIX_CEIL_EXPR:
                   6464:       abort ();                        /* Not used for C.  */
                   6465:       
                   6466:     case FIX_TRUNC_EXPR:
                   6467:     case FLOAT_EXPR:
                   6468:     case MAX_EXPR:
                   6469:     case MIN_EXPR:
                   6470:     case FFS_EXPR:
                   6471:     case LROTATE_EXPR:
                   6472:     case RROTATE_EXPR:
                   6473:       abort ();                        /* FIXME */
                   6474:       
                   6475:     case RDIV_EXPR:
                   6476:       
                   6477:       binoptab = optab_rdiv_expr;
                   6478:       goto binop;
                   6479:       
                   6480:     case BIT_AND_EXPR:
                   6481:       
                   6482:       binoptab = optab_bit_and_expr;
                   6483:       goto binop;
                   6484:       
                   6485:     case BIT_IOR_EXPR:
                   6486:       
                   6487:       binoptab = optab_bit_ior_expr;
                   6488:       goto binop;
                   6489:       
                   6490:     case BIT_XOR_EXPR:
                   6491:       
                   6492:       binoptab = optab_bit_xor_expr;
                   6493:       goto binop;
                   6494:       
                   6495:     case LSHIFT_EXPR:
                   6496:       
                   6497:       binoptab = optab_lshift_expr;
                   6498:       goto binop;
                   6499:       
                   6500:     case RSHIFT_EXPR:
                   6501:       
                   6502:       binoptab = optab_rshift_expr;
                   6503:       goto binop;
                   6504:       
                   6505:     case TRUTH_AND_EXPR:
                   6506:       
                   6507:       binoptab = optab_truth_and_expr;
                   6508:       goto binop;
                   6509:       
                   6510:     case TRUTH_OR_EXPR:
                   6511:       
                   6512:       binoptab = optab_truth_or_expr;
                   6513:       goto binop;
                   6514:       
                   6515:     case LT_EXPR:
                   6516:       
                   6517:       binoptab = optab_lt_expr;
                   6518:       goto binop;
                   6519:       
                   6520:     case LE_EXPR:
                   6521:       
                   6522:       binoptab = optab_le_expr;
                   6523:       goto binop;
                   6524:       
                   6525:     case GE_EXPR:
                   6526:       
                   6527:       binoptab = optab_ge_expr;
                   6528:       goto binop;
                   6529:       
                   6530:     case GT_EXPR:
                   6531:       
                   6532:       binoptab = optab_gt_expr;
                   6533:       goto binop;
                   6534:       
                   6535:     case EQ_EXPR:
                   6536:       
                   6537:       binoptab = optab_eq_expr;
                   6538:       goto binop;
                   6539:       
                   6540:     case NE_EXPR:
                   6541:       
                   6542:       binoptab = optab_ne_expr;
                   6543:       goto binop;
                   6544:       
                   6545:     case NEGATE_EXPR:
                   6546:       
                   6547:       unoptab = optab_negate_expr;
                   6548:       goto unop;
                   6549:       
                   6550:     case BIT_NOT_EXPR:
                   6551:       
                   6552:       unoptab = optab_bit_not_expr;
                   6553:       goto unop;
                   6554:       
                   6555:     case TRUTH_NOT_EXPR:
                   6556:       
                   6557:       unoptab = optab_truth_not_expr;
                   6558:       goto unop;
                   6559:       
                   6560:     case PREDECREMENT_EXPR:
                   6561:       
                   6562:       incroptab = optab_predecrement_expr;
                   6563:       goto increment;
                   6564:       
                   6565:     case PREINCREMENT_EXPR:
                   6566:       
                   6567:       incroptab = optab_preincrement_expr;
                   6568:       goto increment;
                   6569:       
                   6570:     case POSTDECREMENT_EXPR:
                   6571:       
                   6572:       incroptab = optab_postdecrement_expr;
                   6573:       goto increment;
                   6574:       
                   6575:     case POSTINCREMENT_EXPR:
                   6576:       
                   6577:       incroptab = optab_postincrement_expr;
                   6578:       goto increment;
                   6579:       
                   6580:     case CONSTRUCTOR:
                   6581:       
                   6582:       bc_expand_constructor (exp);
                   6583:       return;
                   6584:       
                   6585:     case ERROR_MARK:
                   6586:     case RTL_EXPR:
                   6587:       
                   6588:       return;
                   6589:       
                   6590:     case BIND_EXPR:
                   6591:       {
                   6592:        tree vars = TREE_OPERAND (exp, 0);
                   6593:        int vars_need_expansion = 0;
                   6594:        
                   6595:        /* Need to open a binding contour here because
                   6596:           if there are any cleanups they most be contained here.  */
                   6597:        expand_start_bindings (0);
                   6598:        
                   6599:        /* Mark the corresponding BLOCK for output.  */
                   6600:        if (TREE_OPERAND (exp, 2) != 0)
                   6601:          TREE_USED (TREE_OPERAND (exp, 2)) = 1;
                   6602:        
                   6603:        /* If VARS have not yet been expanded, expand them now.  */
                   6604:        while (vars)
                   6605:          {
                   6606:            if (DECL_RTL (vars) == 0)
                   6607:              {
                   6608:                vars_need_expansion = 1;
1.1.1.7 ! root     6609:                expand_decl (vars);
1.1.1.6   root     6610:              }
1.1.1.7 ! root     6611:            expand_decl_init (vars);
1.1.1.6   root     6612:            vars = TREE_CHAIN (vars);
                   6613:          }
                   6614:        
                   6615:        bc_expand_expr (TREE_OPERAND (exp, 1));
                   6616:        
                   6617:        expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
                   6618:        
                   6619:        return;
                   6620:       }
                   6621:     }
                   6622:   
                   6623:   abort ();
                   6624:   
                   6625:  binop:
                   6626:   
                   6627:   bc_expand_binary_operation (binoptab, TREE_TYPE (exp),
                   6628:                              TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1));
                   6629:   return;
                   6630:   
                   6631:   
                   6632:  unop:
                   6633:   
                   6634:   bc_expand_unary_operation (unoptab, TREE_TYPE (exp), TREE_OPERAND (exp, 0));
                   6635:   return;
                   6636:   
                   6637:   
                   6638:  andorif:
                   6639:   
                   6640:   bc_expand_expr (TREE_OPERAND (exp, 0));
                   6641:   bc_expand_truth_conversion (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   6642:   lab = bc_get_bytecode_label ();
                   6643:   
                   6644:   bc_emit_instruction (duplicate);
                   6645:   bc_emit_bytecode (opcode);
                   6646:   bc_emit_bytecode_labelref (lab);
                   6647:   
                   6648: #ifdef DEBUG_PRINT_CODE
                   6649:   fputc ('\n', stderr);
                   6650: #endif
                   6651:   
                   6652:   bc_emit_instruction (drop);
                   6653:   
                   6654:   bc_expand_expr (TREE_OPERAND (exp, 1));
                   6655:   bc_expand_truth_conversion (TREE_TYPE (TREE_OPERAND (exp, 1)));
                   6656:   bc_emit_bytecode_labeldef (lab);
                   6657:   return;
                   6658:   
                   6659:   
                   6660:  increment:
                   6661:   
                   6662:   type = TREE_TYPE (TREE_OPERAND (exp, 0));
                   6663:   
                   6664:   /* Push the quantum.  */
                   6665:   bc_expand_expr (TREE_OPERAND (exp, 1));
                   6666:   
                   6667:   /* Convert it to the lvalue's type.  */
                   6668:   bc_expand_conversion (TREE_TYPE (TREE_OPERAND (exp, 1)), type);
                   6669:   
                   6670:   /* Push the address of the lvalue */
                   6671:   bc_expand_expr (build1 (ADDR_EXPR, TYPE_POINTER_TO (type), TREE_OPERAND (exp, 0)));
                   6672:   
                   6673:   /* Perform actual increment */
                   6674:   bc_expand_increment (incroptab, type);
                   6675:   return;
                   6676: }
                   6677: 
                   6678: /* Return the alignment in bits of EXP, a pointer valued expression.
                   6679:    But don't return more than MAX_ALIGN no matter what.
                   6680:    The alignment returned is, by default, the alignment of the thing that
                   6681:    EXP points to (if it is not a POINTER_TYPE, 0 is returned).
                   6682: 
                   6683:    Otherwise, look at the expression to see if we can do better, i.e., if the
                   6684:    expression is actually pointing at an object whose alignment is tighter.  */
                   6685: 
                   6686: static int
                   6687: get_pointer_alignment (exp, max_align)
                   6688:      tree exp;
                   6689:      unsigned max_align;
                   6690: {
                   6691:   unsigned align, inner;
                   6692: 
                   6693:   if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
                   6694:     return 0;
                   6695: 
                   6696:   align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
                   6697:   align = MIN (align, max_align);
                   6698: 
                   6699:   while (1)
                   6700:     {
                   6701:       switch (TREE_CODE (exp))
                   6702:        {
                   6703:        case NOP_EXPR:
                   6704:        case CONVERT_EXPR:
                   6705:        case NON_LVALUE_EXPR:
                   6706:          exp = TREE_OPERAND (exp, 0);
                   6707:          if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
                   6708:            return align;
                   6709:          inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
1.1.1.7 ! root     6710:          align = MIN (inner, max_align);
1.1.1.6   root     6711:          break;
                   6712: 
                   6713:        case PLUS_EXPR:
                   6714:          /* If sum of pointer + int, restrict our maximum alignment to that
                   6715:             imposed by the integer.  If not, we can't do any better than
                   6716:             ALIGN.  */
                   6717:          if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST)
                   6718:            return align;
                   6719: 
                   6720:          while (((TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT)
                   6721:                  & (max_align - 1))
                   6722:                 != 0)
                   6723:            max_align >>= 1;
                   6724: 
                   6725:          exp = TREE_OPERAND (exp, 0);
                   6726:          break;
                   6727: 
                   6728:        case ADDR_EXPR:
                   6729:          /* See what we are pointing at and look at its alignment.  */
                   6730:          exp = TREE_OPERAND (exp, 0);
                   6731:          if (TREE_CODE (exp) == FUNCTION_DECL)
1.1.1.7 ! root     6732:            align = FUNCTION_BOUNDARY;
1.1.1.6   root     6733:          else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
1.1.1.7 ! root     6734:            align = DECL_ALIGN (exp);
1.1.1.6   root     6735: #ifdef CONSTANT_ALIGNMENT
                   6736:          else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
                   6737:            align = CONSTANT_ALIGNMENT (exp, align);
                   6738: #endif
                   6739:          return MIN (align, max_align);
                   6740: 
                   6741:        default:
                   6742:          return align;
                   6743:        }
                   6744:     }
                   6745: }
                   6746: 
                   6747: /* Return the tree node and offset if a given argument corresponds to
                   6748:    a string constant.  */
                   6749: 
                   6750: static tree
                   6751: string_constant (arg, ptr_offset)
                   6752:      tree arg;
                   6753:      tree *ptr_offset;
                   6754: {
                   6755:   STRIP_NOPS (arg);
                   6756: 
                   6757:   if (TREE_CODE (arg) == ADDR_EXPR
                   6758:       && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
                   6759:     {
                   6760:       *ptr_offset = integer_zero_node;
                   6761:       return TREE_OPERAND (arg, 0);
                   6762:     }
                   6763:   else if (TREE_CODE (arg) == PLUS_EXPR)
                   6764:     {
                   6765:       tree arg0 = TREE_OPERAND (arg, 0);
                   6766:       tree arg1 = TREE_OPERAND (arg, 1);
                   6767: 
                   6768:       STRIP_NOPS (arg0);
                   6769:       STRIP_NOPS (arg1);
                   6770: 
                   6771:       if (TREE_CODE (arg0) == ADDR_EXPR
                   6772:          && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST)
                   6773:        {
                   6774:          *ptr_offset = arg1;
                   6775:          return TREE_OPERAND (arg0, 0);
                   6776:        }
                   6777:       else if (TREE_CODE (arg1) == ADDR_EXPR
                   6778:               && TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST)
                   6779:        {
                   6780:          *ptr_offset = arg0;
                   6781:          return TREE_OPERAND (arg1, 0);
                   6782:        }
                   6783:     }
                   6784: 
                   6785:   return 0;
                   6786: }
                   6787: 
                   6788: /* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
                   6789:    way, because it could contain a zero byte in the middle.
                   6790:    TREE_STRING_LENGTH is the size of the character array, not the string.
                   6791: 
                   6792:    Unfortunately, string_constant can't access the values of const char
                   6793:    arrays with initializers, so neither can we do so here.  */
                   6794: 
                   6795: static tree
                   6796: c_strlen (src)
                   6797:      tree src;
                   6798: {
                   6799:   tree offset_node;
                   6800:   int offset, max;
                   6801:   char *ptr;
                   6802: 
                   6803:   src = string_constant (src, &offset_node);
                   6804:   if (src == 0)
                   6805:     return 0;
                   6806:   max = TREE_STRING_LENGTH (src);
                   6807:   ptr = TREE_STRING_POINTER (src);
                   6808:   if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
                   6809:     {
                   6810:       /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
                   6811:         compute the offset to the following null if we don't know where to
                   6812:         start searching for it.  */
                   6813:       int i;
                   6814:       for (i = 0; i < max; i++)
                   6815:        if (ptr[i] == 0)
                   6816:          return 0;
                   6817:       /* We don't know the starting offset, but we do know that the string
                   6818:         has no internal zero bytes.  We can assume that the offset falls
                   6819:         within the bounds of the string; otherwise, the programmer deserves
                   6820:         what he gets.  Subtract the offset from the length of the string,
                   6821:         and return that.  */
                   6822:       /* This would perhaps not be valid if we were dealing with named
                   6823:          arrays in addition to literal string constants.  */
                   6824:       return size_binop (MINUS_EXPR, size_int (max), offset_node);
                   6825:     }
                   6826: 
                   6827:   /* We have a known offset into the string.  Start searching there for
                   6828:      a null character.  */
                   6829:   if (offset_node == 0)
                   6830:     offset = 0;
                   6831:   else
                   6832:     {
                   6833:       /* Did we get a long long offset?  If so, punt.  */
                   6834:       if (TREE_INT_CST_HIGH (offset_node) != 0)
                   6835:        return 0;
                   6836:       offset = TREE_INT_CST_LOW (offset_node);
                   6837:     }
                   6838:   /* If the offset is known to be out of bounds, warn, and call strlen at
                   6839:      runtime.  */
                   6840:   if (offset < 0 || offset > max)
                   6841:     {
                   6842:       warning ("offset outside bounds of constant string");
                   6843:       return 0;
                   6844:     }
                   6845:   /* Use strlen to search for the first zero byte.  Since any strings
                   6846:      constructed with build_string will have nulls appended, we win even
                   6847:      if we get handed something like (char[4])"abcd".
                   6848: 
                   6849:      Since OFFSET is our starting index into the string, no further
                   6850:      calculation is needed.  */
                   6851:   return size_int (strlen (ptr + offset));
                   6852: }
                   6853: 
                   6854: /* Expand an expression EXP that calls a built-in function,
                   6855:    with result going to TARGET if that's convenient
                   6856:    (and in mode MODE if that's convenient).
                   6857:    SUBTARGET may be used as the target for computing one of EXP's operands.
                   6858:    IGNORE is nonzero if the value is to be ignored.  */
                   6859: 
1.1.1.7 ! root     6860: #define CALLED_AS_BUILT_IN(NODE) \
        !          6861:    (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
        !          6862: 
1.1.1.6   root     6863: static rtx
                   6864: expand_builtin (exp, target, subtarget, mode, ignore)
                   6865:      tree exp;
                   6866:      rtx target;
                   6867:      rtx subtarget;
                   6868:      enum machine_mode mode;
                   6869:      int ignore;
                   6870: {
                   6871:   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
                   6872:   tree arglist = TREE_OPERAND (exp, 1);
                   6873:   rtx op0;
                   6874:   rtx lab1, insns;
                   6875:   enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
                   6876:   optab builtin_optab;
                   6877: 
                   6878:   switch (DECL_FUNCTION_CODE (fndecl))
                   6879:     {
                   6880:     case BUILT_IN_ABS:
                   6881:     case BUILT_IN_LABS:
                   6882:     case BUILT_IN_FABS:
                   6883:       /* build_function_call changes these into ABS_EXPR.  */
                   6884:       abort ();
                   6885: 
                   6886:     case BUILT_IN_SIN:
                   6887:     case BUILT_IN_COS:
1.1.1.7 ! root     6888:       /* Treat these like sqrt, but only if the user asks for them. */
        !          6889:       if (! flag_fast_math)
        !          6890:        break;
1.1.1.6   root     6891:     case BUILT_IN_FSQRT:
                   6892:       /* If not optimizing, call the library function.  */
                   6893:       if (! optimize)
                   6894:        break;
                   6895: 
                   6896:       if (arglist == 0
                   6897:          /* Arg could be wrong type if user redeclared this fcn wrong.  */
                   6898:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
                   6899:        break;
                   6900: 
                   6901:       /* Stabilize and compute the argument.  */
                   6902:       if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
                   6903:          && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
                   6904:        {
                   6905:          exp = copy_node (exp);
                   6906:          arglist = copy_node (arglist);
                   6907:          TREE_OPERAND (exp, 1) = arglist;
                   6908:          TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
                   6909:        }
                   6910:       op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
                   6911: 
                   6912:       /* Make a suitable register to place result in.  */
                   6913:       target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
                   6914: 
                   6915:       emit_queue ();
                   6916:       start_sequence ();
                   6917: 
                   6918:       switch (DECL_FUNCTION_CODE (fndecl))
                   6919:        {
                   6920:        case BUILT_IN_SIN:
                   6921:          builtin_optab = sin_optab; break;
                   6922:        case BUILT_IN_COS:
                   6923:          builtin_optab = cos_optab; break;
                   6924:        case BUILT_IN_FSQRT:
                   6925:          builtin_optab = sqrt_optab; break;
                   6926:        default:
                   6927:          abort ();
                   6928:        }
                   6929: 
                   6930:       /* Compute into TARGET.
                   6931:         Set TARGET to wherever the result comes back.  */
                   6932:       target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
                   6933:                            builtin_optab, op0, target, 0);
                   6934: 
                   6935:       /* If we were unable to expand via the builtin, stop the
                   6936:         sequence (without outputting the insns) and break, causing
                   6937:         a call the the library function.  */
                   6938:       if (target == 0)
                   6939:        {
                   6940:          end_sequence ();
                   6941:          break;
                   6942:         }
                   6943: 
                   6944:       /* Check the results by default.  But if flag_fast_math is turned on,
                   6945:         then assume sqrt will always be called with valid arguments.  */
                   6946: 
                   6947:       if (! flag_fast_math)
                   6948:        {
                   6949:          /* Don't define the builtin FP instructions
                   6950:             if your machine is not IEEE.  */
                   6951:          if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
                   6952:            abort ();
                   6953: 
                   6954:          lab1 = gen_label_rtx ();
                   6955: 
                   6956:          /* Test the result; if it is NaN, set errno=EDOM because
                   6957:             the argument was not in the domain.  */
                   6958:          emit_cmp_insn (target, target, EQ, 0, GET_MODE (target), 0, 0);
                   6959:          emit_jump_insn (gen_beq (lab1));
                   6960: 
1.1.1.7 ! root     6961: #ifdef TARGET_EDOM
1.1.1.6   root     6962:          {
                   6963: #ifdef GEN_ERRNO_RTX
                   6964:            rtx errno_rtx = GEN_ERRNO_RTX;
                   6965: #else
                   6966:            rtx errno_rtx
1.1.1.7 ! root     6967:              = gen_rtx (MEM, word_mode, gen_rtx (SYMBOL_REF, Pmode, "errno"));
1.1.1.6   root     6968: #endif
                   6969: 
                   6970:            emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
                   6971:          }
                   6972: #else
                   6973:          /* We can't set errno=EDOM directly; let the library call do it.
                   6974:             Pop the arguments right away in case the call gets deleted. */
                   6975:          NO_DEFER_POP;
                   6976:          expand_call (exp, target, 0);
                   6977:          OK_DEFER_POP;
                   6978: #endif
                   6979: 
                   6980:          emit_label (lab1);
                   6981:        }
                   6982: 
                   6983:       /* Output the entire sequence. */
                   6984:       insns = get_insns ();
                   6985:       end_sequence ();
                   6986:       emit_insns (insns);
                   6987:  
                   6988:       return target;
                   6989: 
                   6990:       /* __builtin_apply_args returns block of memory allocated on
                   6991:         the stack into which is stored the arg pointer, structure
                   6992:         value address, static chain, and all the registers that might
                   6993:         possibly be used in performing a function call.  The code is
                   6994:         moved to the start of the function so the incoming values are
                   6995:         saved.  */
                   6996:     case BUILT_IN_APPLY_ARGS:
                   6997:       /* Don't do __builtin_apply_args more than once in a function.
                   6998:         Save the result of the first call and reuse it.  */
                   6999:       if (apply_args_value != 0)
                   7000:        return apply_args_value;
                   7001:       {
                   7002:        /* When this function is called, it means that registers must be
                   7003:           saved on entry to this function.  So we migrate the
                   7004:           call to the first insn of this function.  */
                   7005:        rtx temp;
                   7006:        rtx seq;
                   7007: 
                   7008:        start_sequence ();
                   7009:        temp = expand_builtin_apply_args ();
                   7010:        seq = get_insns ();
                   7011:        end_sequence ();
                   7012: 
                   7013:        apply_args_value = temp;
                   7014: 
                   7015:        /* Put the sequence after the NOTE that starts the function.
                   7016:           If this is inside a SEQUENCE, make the outer-level insn
                   7017:           chain current, so the code is placed at the start of the
                   7018:           function.  */
                   7019:        push_topmost_sequence ();
                   7020:        emit_insns_before (seq, NEXT_INSN (get_insns ()));
                   7021:        pop_topmost_sequence ();
                   7022:        return temp;
                   7023:       }
                   7024: 
                   7025:       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
                   7026:         FUNCTION with a copy of the parameters described by
                   7027:         ARGUMENTS, and ARGSIZE.  It returns a block of memory
                   7028:         allocated on the stack into which is stored all the registers
                   7029:         that might possibly be used for returning the result of a
                   7030:         function.  ARGUMENTS is the value returned by
                   7031:         __builtin_apply_args.  ARGSIZE is the number of bytes of
                   7032:         arguments that must be copied.  ??? How should this value be
                   7033:         computed?  We'll also need a safe worst case value for varargs
                   7034:         functions.  */
                   7035:     case BUILT_IN_APPLY:
                   7036:       if (arglist == 0
                   7037:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   7038:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   7039:          || TREE_CHAIN (arglist) == 0
                   7040:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
                   7041:          || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
                   7042:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
                   7043:        return const0_rtx;
                   7044:       else
                   7045:        {
                   7046:          int i;
                   7047:          tree t;
                   7048:          rtx ops[3];
                   7049: 
                   7050:          for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
                   7051:            ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
                   7052: 
                   7053:          return expand_builtin_apply (ops[0], ops[1], ops[2]);
                   7054:        }
                   7055: 
                   7056:       /* __builtin_return (RESULT) causes the function to return the
                   7057:         value described by RESULT.  RESULT is address of the block of
                   7058:         memory returned by __builtin_apply.  */
                   7059:     case BUILT_IN_RETURN:
                   7060:       if (arglist
                   7061:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   7062:          && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
                   7063:        expand_builtin_return (expand_expr (TREE_VALUE (arglist),
                   7064:                                            NULL_RTX, VOIDmode, 0));
                   7065:       return const0_rtx;
                   7066: 
                   7067:     case BUILT_IN_SAVEREGS:
                   7068:       /* Don't do __builtin_saveregs more than once in a function.
                   7069:         Save the result of the first call and reuse it.  */
                   7070:       if (saveregs_value != 0)
                   7071:        return saveregs_value;
                   7072:       {
                   7073:        /* When this function is called, it means that registers must be
                   7074:           saved on entry to this function.  So we migrate the
                   7075:           call to the first insn of this function.  */
                   7076:        rtx temp;
                   7077:        rtx seq;
                   7078: 
                   7079:        /* Now really call the function.  `expand_call' does not call
                   7080:           expand_builtin, so there is no danger of infinite recursion here.  */
                   7081:        start_sequence ();
                   7082: 
                   7083: #ifdef EXPAND_BUILTIN_SAVEREGS
                   7084:        /* Do whatever the machine needs done in this case.  */
                   7085:        temp = EXPAND_BUILTIN_SAVEREGS (arglist);
                   7086: #else
                   7087:        /* The register where the function returns its value
                   7088:           is likely to have something else in it, such as an argument.
                   7089:           So preserve that register around the call.  */
1.1.1.7 ! root     7090: 
1.1.1.6   root     7091:        if (value_mode != VOIDmode)
                   7092:          {
1.1.1.7 ! root     7093:            rtx valreg = hard_libcall_value (value_mode);
        !          7094:            rtx saved_valreg = gen_reg_rtx (value_mode);
        !          7095: 
1.1.1.6   root     7096:            emit_move_insn (saved_valreg, valreg);
1.1.1.7 ! root     7097:            temp = expand_call (exp, target, ignore);
        !          7098:            emit_move_insn (valreg, saved_valreg);
1.1.1.6   root     7099:          }
1.1.1.7 ! root     7100:        else
        !          7101:          /* Generate the call, putting the value in a pseudo.  */
        !          7102:          temp = expand_call (exp, target, ignore);
1.1.1.6   root     7103: #endif
                   7104: 
                   7105:        seq = get_insns ();
                   7106:        end_sequence ();
                   7107: 
                   7108:        saveregs_value = temp;
                   7109: 
                   7110:        /* Put the sequence after the NOTE that starts the function.
                   7111:           If this is inside a SEQUENCE, make the outer-level insn
                   7112:           chain current, so the code is placed at the start of the
                   7113:           function.  */
                   7114:        push_topmost_sequence ();
                   7115:        emit_insns_before (seq, NEXT_INSN (get_insns ()));
                   7116:        pop_topmost_sequence ();
                   7117:        return temp;
                   7118:       }
                   7119: 
                   7120:       /* __builtin_args_info (N) returns word N of the arg space info
                   7121:         for the current function.  The number and meanings of words
                   7122:         is controlled by the definition of CUMULATIVE_ARGS.  */
                   7123:     case BUILT_IN_ARGS_INFO:
                   7124:       {
                   7125:        int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
                   7126:        int i;
                   7127:        int *word_ptr = (int *) &current_function_args_info;
                   7128:        tree type, elts, result;
                   7129: 
                   7130:        if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
                   7131:          fatal ("CUMULATIVE_ARGS type defined badly; see %s, line %d",
                   7132:                 __FILE__, __LINE__);
                   7133: 
                   7134:        if (arglist != 0)
                   7135:          {
                   7136:            tree arg = TREE_VALUE (arglist);
                   7137:            if (TREE_CODE (arg) != INTEGER_CST)
                   7138:              error ("argument of `__builtin_args_info' must be constant");
                   7139:            else
                   7140:              {
                   7141:                int wordnum = TREE_INT_CST_LOW (arg);
                   7142: 
                   7143:                if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
                   7144:                  error ("argument of `__builtin_args_info' out of range");
                   7145:                else
                   7146:                  return GEN_INT (word_ptr[wordnum]);
                   7147:              }
                   7148:          }
                   7149:        else
                   7150:          error ("missing argument in `__builtin_args_info'");
                   7151: 
                   7152:        return const0_rtx;
                   7153: 
                   7154: #if 0
                   7155:        for (i = 0; i < nwords; i++)
                   7156:          elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
                   7157: 
                   7158:        type = build_array_type (integer_type_node,
                   7159:                                 build_index_type (build_int_2 (nwords, 0)));
                   7160:        result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
                   7161:        TREE_CONSTANT (result) = 1;
                   7162:        TREE_STATIC (result) = 1;
                   7163:        result = build (INDIRECT_REF, build_pointer_type (type), result);
                   7164:        TREE_CONSTANT (result) = 1;
                   7165:        return expand_expr (result, NULL_RTX, VOIDmode, 0);
                   7166: #endif
                   7167:       }
                   7168: 
                   7169:       /* Return the address of the first anonymous stack arg.  */
                   7170:     case BUILT_IN_NEXT_ARG:
                   7171:       {
                   7172:        tree fntype = TREE_TYPE (current_function_decl);
1.1.1.7 ! root     7173: 
        !          7174:        if ((TYPE_ARG_TYPES (fntype) == 0
        !          7175:             || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
        !          7176:                 == void_type_node))
        !          7177:            && ! current_function_varargs)
1.1.1.6   root     7178:          {
                   7179:            error ("`va_start' used in function with fixed args");
                   7180:            return const0_rtx;
                   7181:          }
1.1.1.7 ! root     7182: 
        !          7183:        if (arglist)
        !          7184:          {
        !          7185:            tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
        !          7186:            tree arg = TREE_VALUE (arglist);
        !          7187: 
        !          7188:            /* Strip off all nops for the sake of the comparison.  This
        !          7189:               is not quite the same as STRIP_NOPS.  It does more.  */
        !          7190:            while (TREE_CODE (arg) == NOP_EXPR
        !          7191:                   || TREE_CODE (arg) == CONVERT_EXPR
        !          7192:                   || TREE_CODE (arg) == NON_LVALUE_EXPR)
        !          7193:              arg = TREE_OPERAND (arg, 0);
        !          7194:            if (arg != last_parm)
        !          7195:              warning ("second parameter of `va_start' not last named argument");
        !          7196:          }
        !          7197:        else
        !          7198:          /* Evidently an out of date version of <stdarg.h>; can't validate
        !          7199:             va_start's second argument, but can still work as intended.  */
        !          7200:          warning ("`__builtin_next_arg' called without an argument");
1.1.1.6   root     7201:       }
                   7202: 
                   7203:       return expand_binop (Pmode, add_optab,
                   7204:                           current_function_internal_arg_pointer,
                   7205:                           current_function_arg_offset_rtx,
                   7206:                           NULL_RTX, 0, OPTAB_LIB_WIDEN);
                   7207: 
                   7208:     case BUILT_IN_CLASSIFY_TYPE:
                   7209:       if (arglist != 0)
                   7210:        {
                   7211:          tree type = TREE_TYPE (TREE_VALUE (arglist));
                   7212:          enum tree_code code = TREE_CODE (type);
                   7213:          if (code == VOID_TYPE)
                   7214:            return GEN_INT (void_type_class);
                   7215:          if (code == INTEGER_TYPE)
                   7216:            return GEN_INT (integer_type_class);
                   7217:          if (code == CHAR_TYPE)
                   7218:            return GEN_INT (char_type_class);
                   7219:          if (code == ENUMERAL_TYPE)
                   7220:            return GEN_INT (enumeral_type_class);
                   7221:          if (code == BOOLEAN_TYPE)
                   7222:            return GEN_INT (boolean_type_class);
                   7223:          if (code == POINTER_TYPE)
                   7224:            return GEN_INT (pointer_type_class);
                   7225:          if (code == REFERENCE_TYPE)
                   7226:            return GEN_INT (reference_type_class);
                   7227:          if (code == OFFSET_TYPE)
                   7228:            return GEN_INT (offset_type_class);
                   7229:          if (code == REAL_TYPE)
                   7230:            return GEN_INT (real_type_class);
                   7231:          if (code == COMPLEX_TYPE)
                   7232:            return GEN_INT (complex_type_class);
                   7233:          if (code == FUNCTION_TYPE)
                   7234:            return GEN_INT (function_type_class);
                   7235:          if (code == METHOD_TYPE)
                   7236:            return GEN_INT (method_type_class);
                   7237:          if (code == RECORD_TYPE)
                   7238:            return GEN_INT (record_type_class);
                   7239:          if (code == UNION_TYPE || code == QUAL_UNION_TYPE)
                   7240:            return GEN_INT (union_type_class);
                   7241:          if (code == ARRAY_TYPE)
1.1.1.7 ! root     7242:            {
        !          7243:              if (TYPE_STRING_FLAG (type))
        !          7244:                return GEN_INT (string_type_class);
        !          7245:              else
        !          7246:                return GEN_INT (array_type_class);
        !          7247:            }
1.1.1.6   root     7248:          if (code == SET_TYPE)
                   7249:            return GEN_INT (set_type_class);
                   7250:          if (code == FILE_TYPE)
                   7251:            return GEN_INT (file_type_class);
                   7252:          if (code == LANG_TYPE)
                   7253:            return GEN_INT (lang_type_class);
                   7254:        }
                   7255:       return GEN_INT (no_type_class);
                   7256: 
                   7257:     case BUILT_IN_CONSTANT_P:
                   7258:       if (arglist == 0)
                   7259:        return const0_rtx;
                   7260:       else
                   7261:        return (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (arglist))) == 'c'
                   7262:                ? const1_rtx : const0_rtx);
                   7263: 
                   7264:     case BUILT_IN_FRAME_ADDRESS:
                   7265:       /* The argument must be a nonnegative integer constant.
                   7266:         It counts the number of frames to scan up the stack.
                   7267:         The value is the address of that frame.  */
                   7268:     case BUILT_IN_RETURN_ADDRESS:
                   7269:       /* The argument must be a nonnegative integer constant.
                   7270:         It counts the number of frames to scan up the stack.
                   7271:         The value is the return address saved in that frame.  */
                   7272:       if (arglist == 0)
                   7273:        /* Warning about missing arg was already issued.  */
                   7274:        return const0_rtx;
                   7275:       else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST)
                   7276:        {
                   7277:          error ("invalid arg to `__builtin_return_address'");
                   7278:          return const0_rtx;
                   7279:        }
1.1.1.7 ! root     7280:       else if (tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
1.1.1.6   root     7281:        {
                   7282:          error ("invalid arg to `__builtin_return_address'");
                   7283:          return const0_rtx;
                   7284:        }
                   7285:       else
                   7286:        {
                   7287:          int count = TREE_INT_CST_LOW (TREE_VALUE (arglist)); 
                   7288:          rtx tem = frame_pointer_rtx;
                   7289:          int i;
                   7290: 
                   7291:          /* Some machines need special handling before we can access arbitrary
                   7292:             frames.  For example, on the sparc, we must first flush all
                   7293:             register windows to the stack.  */
                   7294: #ifdef SETUP_FRAME_ADDRESSES
                   7295:          SETUP_FRAME_ADDRESSES ();
                   7296: #endif
                   7297: 
                   7298:          /* On the sparc, the return address is not in the frame, it is
                   7299:             in a register.  There is no way to access it off of the current
                   7300:             frame pointer, but it can be accessed off the previous frame
                   7301:             pointer by reading the value from the register window save
                   7302:             area.  */
                   7303: #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
                   7304:          if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_RETURN_ADDRESS)
                   7305:            count--;
                   7306: #endif
                   7307: 
                   7308:          /* Scan back COUNT frames to the specified frame.  */
                   7309:          for (i = 0; i < count; i++)
                   7310:            {
                   7311:              /* Assume the dynamic chain pointer is in the word that
                   7312:                 the frame address points to, unless otherwise specified.  */
                   7313: #ifdef DYNAMIC_CHAIN_ADDRESS
                   7314:              tem = DYNAMIC_CHAIN_ADDRESS (tem);
                   7315: #endif
                   7316:              tem = memory_address (Pmode, tem);
                   7317:              tem = copy_to_reg (gen_rtx (MEM, Pmode, tem));
                   7318:            }
                   7319: 
                   7320:          /* For __builtin_frame_address, return what we've got.  */
                   7321:          if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
                   7322:            return tem;
                   7323: 
                   7324:          /* For __builtin_return_address,
                   7325:             Get the return address from that frame.  */
                   7326: #ifdef RETURN_ADDR_RTX
                   7327:          return RETURN_ADDR_RTX (count, tem);
                   7328: #else
                   7329:          tem = memory_address (Pmode,
                   7330:                                plus_constant (tem, GET_MODE_SIZE (Pmode)));
                   7331:          return copy_to_reg (gen_rtx (MEM, Pmode, tem));
                   7332: #endif
                   7333:        }
                   7334: 
                   7335:     case BUILT_IN_ALLOCA:
                   7336:       if (arglist == 0
                   7337:          /* Arg could be non-integer if user redeclared this fcn wrong.  */
                   7338:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
                   7339:        break;
1.1.1.7 ! root     7340: 
1.1.1.6   root     7341:       /* Compute the argument.  */
                   7342:       op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
1.1       root     7343: 
1.1.1.6   root     7344:       /* Allocate the desired space.  */
1.1.1.7 ! root     7345:       return allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
1.1       root     7346: 
1.1.1.6   root     7347:     case BUILT_IN_FFS:
                   7348:       /* If not optimizing, call the library function.  */
1.1.1.7 ! root     7349:       if (!optimize && ! CALLED_AS_BUILT_IN (fndecl))
1.1.1.6   root     7350:        break;
                   7351: 
                   7352:       if (arglist == 0
                   7353:          /* Arg could be non-integer if user redeclared this fcn wrong.  */
                   7354:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
                   7355:        break;
                   7356: 
                   7357:       /* Compute the argument.  */
                   7358:       op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
                   7359:       /* Compute ffs, into TARGET if possible.
                   7360:         Set TARGET to wherever the result comes back.  */
                   7361:       target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
                   7362:                            ffs_optab, op0, target, 1);
                   7363:       if (target == 0)
                   7364:        abort ();
                   7365:       return target;
                   7366: 
                   7367:     case BUILT_IN_STRLEN:
                   7368:       /* If not optimizing, call the library function.  */
1.1.1.7 ! root     7369:       if (!optimize && ! CALLED_AS_BUILT_IN (fndecl))
1.1.1.6   root     7370:        break;
                   7371: 
                   7372:       if (arglist == 0
                   7373:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   7374:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
                   7375:        break;
                   7376:       else
1.1       root     7377:        {
1.1.1.6   root     7378:          tree src = TREE_VALUE (arglist);
                   7379:          tree len = c_strlen (src);
1.1       root     7380: 
1.1.1.6   root     7381:          int align
                   7382:            = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1.1       root     7383: 
1.1.1.6   root     7384:          rtx result, src_rtx, char_rtx;
                   7385:          enum machine_mode insn_mode = value_mode, char_mode;
                   7386:          enum insn_code icode;
1.1       root     7387: 
1.1.1.6   root     7388:          /* If the length is known, just return it. */
                   7389:          if (len != 0)
                   7390:            return expand_expr (len, target, mode, 0);
1.1       root     7391: 
1.1.1.6   root     7392:          /* If SRC is not a pointer type, don't do this operation inline. */
                   7393:          if (align == 0)
                   7394:            break;
1.1       root     7395: 
1.1.1.6   root     7396:          /* Call a function if we can't compute strlen in the right mode. */
1.1       root     7397: 
1.1.1.6   root     7398:          while (insn_mode != VOIDmode)
                   7399:            {
                   7400:              icode = strlen_optab->handlers[(int) insn_mode].insn_code;
                   7401:              if (icode != CODE_FOR_nothing)
                   7402:                break;
1.1       root     7403: 
1.1.1.6   root     7404:              insn_mode = GET_MODE_WIDER_MODE (insn_mode);
                   7405:            }
                   7406:          if (insn_mode == VOIDmode)
                   7407:            break;
1.1       root     7408: 
1.1.1.6   root     7409:          /* Make a place to write the result of the instruction.  */
                   7410:          result = target;
                   7411:          if (! (result != 0
                   7412:                 && GET_CODE (result) == REG
                   7413:                 && GET_MODE (result) == insn_mode
                   7414:                 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
                   7415:            result = gen_reg_rtx (insn_mode);
1.1       root     7416: 
1.1.1.6   root     7417:          /* Make sure the operands are acceptable to the predicates.  */
                   7418: 
                   7419:          if (! (*insn_operand_predicate[(int)icode][0]) (result, insn_mode))
                   7420:            result = gen_reg_rtx (insn_mode);
                   7421: 
                   7422:          src_rtx = memory_address (BLKmode,
                   7423:                                    expand_expr (src, NULL_RTX, Pmode,
                   7424:                                                 EXPAND_NORMAL));
                   7425:          if (! (*insn_operand_predicate[(int)icode][1]) (src_rtx, Pmode))
                   7426:            src_rtx = copy_to_mode_reg (Pmode, src_rtx);
                   7427: 
                   7428:          char_rtx = const0_rtx;
                   7429:          char_mode = insn_operand_mode[(int)icode][2];
                   7430:          if (! (*insn_operand_predicate[(int)icode][2]) (char_rtx, char_mode))
                   7431:            char_rtx = copy_to_mode_reg (char_mode, char_rtx);
                   7432: 
                   7433:          emit_insn (GEN_FCN (icode) (result,
                   7434:                                      gen_rtx (MEM, BLKmode, src_rtx),
                   7435:                                      char_rtx, GEN_INT (align)));
                   7436: 
                   7437:          /* Return the value in the proper mode for this function.  */
                   7438:          if (GET_MODE (result) == value_mode)
                   7439:            return result;
                   7440:          else if (target != 0)
                   7441:            {
                   7442:              convert_move (target, result, 0);
                   7443:              return target;
                   7444:            }
                   7445:          else
                   7446:            return convert_to_mode (value_mode, result, 0);
1.1       root     7447:        }
1.1.1.6   root     7448: 
                   7449:     case BUILT_IN_STRCPY:
                   7450:       /* If not optimizing, call the library function.  */
1.1.1.7 ! root     7451:       if (!optimize && ! CALLED_AS_BUILT_IN (fndecl))
1.1.1.6   root     7452:        break;
                   7453: 
                   7454:       if (arglist == 0
                   7455:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   7456:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   7457:          || TREE_CHAIN (arglist) == 0
                   7458:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE)
                   7459:        break;
                   7460:       else
1.1       root     7461:        {
1.1.1.6   root     7462:          tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
                   7463: 
                   7464:          if (len == 0)
                   7465:            break;
                   7466: 
                   7467:          len = size_binop (PLUS_EXPR, len, integer_one_node);
                   7468: 
                   7469:          chainon (arglist, build_tree_list (NULL_TREE, len));
1.1       root     7470:        }
                   7471: 
1.1.1.6   root     7472:       /* Drops in.  */
                   7473:     case BUILT_IN_MEMCPY:
                   7474:       /* If not optimizing, call the library function.  */
1.1.1.7 ! root     7475:       if (!optimize && ! CALLED_AS_BUILT_IN (fndecl))
1.1.1.6   root     7476:        break;
1.1       root     7477: 
1.1.1.6   root     7478:       if (arglist == 0
                   7479:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   7480:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   7481:          || TREE_CHAIN (arglist) == 0
                   7482:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
                   7483:          || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
                   7484:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
                   7485:        break;
                   7486:       else
                   7487:        {
                   7488:          tree dest = TREE_VALUE (arglist);
                   7489:          tree src = TREE_VALUE (TREE_CHAIN (arglist));
                   7490:          tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1.1       root     7491: 
1.1.1.6   root     7492:          int src_align
                   7493:            = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   7494:          int dest_align
                   7495:            = get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   7496:          rtx dest_rtx, dest_mem, src_mem;
1.1       root     7497: 
1.1.1.6   root     7498:          /* If either SRC or DEST is not a pointer type, don't do
                   7499:             this operation in-line.  */
                   7500:          if (src_align == 0 || dest_align == 0)
                   7501:            {
                   7502:              if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCPY)
                   7503:                TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
                   7504:              break;
                   7505:            }
                   7506: 
                   7507:          dest_rtx = expand_expr (dest, NULL_RTX, Pmode, EXPAND_NORMAL);
                   7508:          dest_mem = gen_rtx (MEM, BLKmode,
                   7509:                              memory_address (BLKmode, dest_rtx));
                   7510:          src_mem = gen_rtx (MEM, BLKmode,
                   7511:                             memory_address (BLKmode,
                   7512:                                             expand_expr (src, NULL_RTX,
                   7513:                                                          Pmode,
                   7514:                                                          EXPAND_NORMAL)));
                   7515: 
                   7516:          /* Copy word part most expediently.  */
                   7517:          emit_block_move (dest_mem, src_mem,
                   7518:                           expand_expr (len, NULL_RTX, VOIDmode, 0),
                   7519:                           MIN (src_align, dest_align));
                   7520:          return dest_rtx;
                   7521:        }
1.1       root     7522: 
1.1.1.6   root     7523: /* These comparison functions need an instruction that returns an actual
                   7524:    index.  An ordinary compare that just sets the condition codes
                   7525:    is not enough.  */
                   7526: #ifdef HAVE_cmpstrsi
                   7527:     case BUILT_IN_STRCMP:
                   7528:       /* If not optimizing, call the library function.  */
1.1.1.7 ! root     7529:       if (!optimize && ! CALLED_AS_BUILT_IN (fndecl))
1.1.1.6   root     7530:        break;
1.1       root     7531: 
1.1.1.6   root     7532:       if (arglist == 0
                   7533:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   7534:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   7535:          || TREE_CHAIN (arglist) == 0
                   7536:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE)
                   7537:        break;
                   7538:       else if (!HAVE_cmpstrsi)
                   7539:        break;
                   7540:       {
                   7541:        tree arg1 = TREE_VALUE (arglist);
                   7542:        tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
                   7543:        tree offset;
                   7544:        tree len, len2;
1.1       root     7545: 
1.1.1.6   root     7546:        len = c_strlen (arg1);
                   7547:        if (len)
                   7548:          len = size_binop (PLUS_EXPR, integer_one_node, len);
                   7549:        len2 = c_strlen (arg2);
                   7550:        if (len2)
                   7551:          len2 = size_binop (PLUS_EXPR, integer_one_node, len2);
1.1       root     7552: 
1.1.1.6   root     7553:        /* If we don't have a constant length for the first, use the length
                   7554:           of the second, if we know it.  We don't require a constant for
                   7555:           this case; some cost analysis could be done if both are available
                   7556:           but neither is constant.  For now, assume they're equally cheap.
1.1       root     7557: 
1.1.1.6   root     7558:           If both strings have constant lengths, use the smaller.  This
                   7559:           could arise if optimization results in strcpy being called with
                   7560:           two fixed strings, or if the code was machine-generated.  We should
                   7561:           add some code to the `memcmp' handler below to deal with such
                   7562:           situations, someday.  */
                   7563:        if (!len || TREE_CODE (len) != INTEGER_CST)
                   7564:          {
                   7565:            if (len2)
                   7566:              len = len2;
                   7567:            else if (len == 0)
                   7568:              break;
                   7569:          }
                   7570:        else if (len2 && TREE_CODE (len2) == INTEGER_CST)
                   7571:          {
                   7572:            if (tree_int_cst_lt (len2, len))
                   7573:              len = len2;
                   7574:          }
1.1       root     7575: 
1.1.1.6   root     7576:        chainon (arglist, build_tree_list (NULL_TREE, len));
                   7577:       }
                   7578: 
                   7579:       /* Drops in.  */
                   7580:     case BUILT_IN_MEMCMP:
1.1.1.2   root     7581:       /* If not optimizing, call the library function.  */
1.1.1.7 ! root     7582:       if (!optimize && ! CALLED_AS_BUILT_IN (fndecl))
1.1.1.2   root     7583:        break;
                   7584: 
                   7585:       if (arglist == 0
1.1.1.6   root     7586:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   7587:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   7588:          || TREE_CHAIN (arglist) == 0
                   7589:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
                   7590:          || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
                   7591:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
                   7592:        break;
                   7593:       else if (!HAVE_cmpstrsi)
                   7594:        break;
                   7595:       {
                   7596:        tree arg1 = TREE_VALUE (arglist);
                   7597:        tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
                   7598:        tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
                   7599:        rtx result;
1.1.1.2   root     7600: 
1.1.1.6   root     7601:        int arg1_align
                   7602:          = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   7603:        int arg2_align
                   7604:          = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   7605:        enum machine_mode insn_mode
                   7606:          = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
1.1.1.3   root     7607: 
1.1.1.6   root     7608:        /* If we don't have POINTER_TYPE, call the function.  */
                   7609:        if (arg1_align == 0 || arg2_align == 0)
                   7610:          {
                   7611:            if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCMP)
                   7612:              TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
                   7613:            break;
                   7614:          }
1.1.1.3   root     7615: 
1.1.1.6   root     7616:        /* Make a place to write the result of the instruction.  */
                   7617:        result = target;
                   7618:        if (! (result != 0
                   7619:               && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
                   7620:               && REGNO (result) >= FIRST_PSEUDO_REGISTER))
                   7621:          result = gen_reg_rtx (insn_mode);
1.1.1.3   root     7622: 
1.1.1.6   root     7623:        emit_insn (gen_cmpstrsi (result,
                   7624:                                 gen_rtx (MEM, BLKmode,
                   7625:                                          expand_expr (arg1, NULL_RTX, Pmode,
                   7626:                                                       EXPAND_NORMAL)),
                   7627:                                 gen_rtx (MEM, BLKmode,
                   7628:                                          expand_expr (arg2, NULL_RTX, Pmode,
                   7629:                                                       EXPAND_NORMAL)),
                   7630:                                 expand_expr (len, NULL_RTX, VOIDmode, 0),
                   7631:                                 GEN_INT (MIN (arg1_align, arg2_align))));
1.1.1.3   root     7632: 
1.1.1.6   root     7633:        /* Return the value in the proper mode for this function.  */
                   7634:        mode = TYPE_MODE (TREE_TYPE (exp));
                   7635:        if (GET_MODE (result) == mode)
                   7636:          return result;
                   7637:        else if (target != 0)
                   7638:          {
                   7639:            convert_move (target, result, 0);
                   7640:            return target;
                   7641:          }
                   7642:        else
                   7643:          return convert_to_mode (mode, result, 0);
                   7644:       }        
                   7645: #else
                   7646:     case BUILT_IN_STRCMP:
                   7647:     case BUILT_IN_MEMCMP:
                   7648:       break;
                   7649: #endif
1.1.1.3   root     7650: 
1.1.1.6   root     7651:     default:                   /* just do library call, if unknown builtin */
                   7652:       error ("built-in function `%s' not currently supported",
                   7653:             IDENTIFIER_POINTER (DECL_NAME (fndecl)));
                   7654:     }
1.1.1.2   root     7655: 
1.1.1.6   root     7656:   /* The switch statement above can drop through to cause the function
                   7657:      to be called normally.  */
1.1.1.4   root     7658: 
1.1.1.6   root     7659:   return expand_call (exp, target, ignore);
                   7660: }
                   7661: 
                   7662: /* Built-in functions to perform an untyped call and return.  */
                   7663: 
                   7664: /* For each register that may be used for calling a function, this
                   7665:    gives a mode used to copy the register's value.  VOIDmode indicates
                   7666:    the register is not used for calling a function.  If the machine
                   7667:    has register windows, this gives only the outbound registers.
                   7668:    INCOMING_REGNO gives the corresponding inbound register.  */
                   7669: static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1.1.1.4   root     7670: 
1.1.1.6   root     7671: /* For each register that may be used for returning values, this gives
                   7672:    a mode used to copy the register's value.  VOIDmode indicates the
                   7673:    register is not used for returning values.  If the machine has
                   7674:    register windows, this gives only the outbound registers.
                   7675:    INCOMING_REGNO gives the corresponding inbound register.  */
                   7676: static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1.1.1.4   root     7677: 
1.1.1.6   root     7678: /* For each register that may be used for calling a function, this
                   7679:    gives the offset of that register into the block returned by
                   7680:    __bultin_apply_args.  0 indicates that the register is not
                   7681:    used for calling a function. */
                   7682: static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
                   7683: 
                   7684: /* Return the offset of register REGNO into the block returned by 
                   7685:    __builtin_apply_args.  This is not declared static, since it is
                   7686:    needed in objc-act.c. */
1.1.1.4   root     7687: 
1.1.1.6   root     7688: int 
                   7689: apply_args_register_offset (regno)
                   7690:      int regno;
                   7691: {
                   7692:   apply_args_size ();
1.1.1.4   root     7693: 
1.1.1.6   root     7694:   /* Arguments are always put in outgoing registers (in the argument
                   7695:      block) if such make sense. */
                   7696: #ifdef OUTGOING_REGNO
                   7697:   regno = OUTGOING_REGNO(regno);
1.1.1.4   root     7698: #endif
1.1.1.6   root     7699:   return apply_args_reg_offset[regno];
                   7700: }
1.1.1.4   root     7701: 
1.1.1.6   root     7702: /* Return the size required for the block returned by __builtin_apply_args,
                   7703:    and initialize apply_args_mode.  */
1.1.1.2   root     7704: 
1.1.1.6   root     7705: static int
                   7706: apply_args_size ()
                   7707: {
                   7708:   static int size = -1;
                   7709:   int align, regno;
                   7710:   enum machine_mode mode;
1.1.1.3   root     7711: 
1.1.1.6   root     7712:   /* The values computed by this function never change.  */
                   7713:   if (size < 0)
                   7714:     {
                   7715:       /* The first value is the incoming arg-pointer.  */
                   7716:       size = GET_MODE_SIZE (Pmode);
1.1.1.5   root     7717: 
1.1.1.6   root     7718:       /* The second value is the structure value address unless this is
                   7719:         passed as an "invisible" first argument.  */
                   7720:       if (struct_value_rtx)
                   7721:        size += GET_MODE_SIZE (Pmode);
1.1.1.5   root     7722: 
1.1.1.6   root     7723:       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   7724:        if (FUNCTION_ARG_REGNO_P (regno))
                   7725:          {
                   7726:            /* Search for the proper mode for copying this register's
                   7727:               value.  I'm not sure this is right, but it works so far.  */
                   7728:            enum machine_mode best_mode = VOIDmode;
1.1.1.5   root     7729: 
1.1.1.6   root     7730:            for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
                   7731:                 mode != VOIDmode;
                   7732:                 mode = GET_MODE_WIDER_MODE (mode))
                   7733:              if (HARD_REGNO_MODE_OK (regno, mode)
                   7734:                  && HARD_REGNO_NREGS (regno, mode) == 1)
                   7735:                best_mode = mode;
1.1.1.5   root     7736: 
1.1.1.6   root     7737:            if (best_mode == VOIDmode)
                   7738:              for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
                   7739:                   mode != VOIDmode;
                   7740:                   mode = GET_MODE_WIDER_MODE (mode))
                   7741:                if (HARD_REGNO_MODE_OK (regno, mode)
                   7742:                    && (mov_optab->handlers[(int) mode].insn_code
                   7743:                        != CODE_FOR_nothing))
                   7744:                  best_mode = mode;
1.1.1.5   root     7745: 
1.1.1.6   root     7746:            mode = best_mode;
                   7747:            if (mode == VOIDmode)
                   7748:              abort ();
1.1.1.5   root     7749: 
1.1.1.6   root     7750:            align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                   7751:            if (size % align != 0)
                   7752:              size = CEIL (size, align) * align;
                   7753:            apply_args_reg_offset[regno] = size;
                   7754:            size += GET_MODE_SIZE (mode);
                   7755:            apply_args_mode[regno] = mode;
                   7756:          }
                   7757:        else
                   7758:          {
                   7759:            apply_args_mode[regno] = VOIDmode;
                   7760:            apply_args_reg_offset[regno] = 0;
                   7761:          }
                   7762:     }
                   7763:   return size;
                   7764: }
1.1.1.5   root     7765: 
1.1.1.6   root     7766: /* Return the size required for the block returned by __builtin_apply,
                   7767:    and initialize apply_result_mode.  */
1.1.1.5   root     7768: 
1.1.1.6   root     7769: static int
                   7770: apply_result_size ()
                   7771: {
                   7772:   static int size = -1;
                   7773:   int align, regno;
                   7774:   enum machine_mode mode;
1.1       root     7775: 
1.1.1.6   root     7776:   /* The values computed by this function never change.  */
                   7777:   if (size < 0)
                   7778:     {
                   7779:       size = 0;
1.1       root     7780: 
1.1.1.6   root     7781:       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   7782:        if (FUNCTION_VALUE_REGNO_P (regno))
1.1       root     7783:          {
1.1.1.6   root     7784:            /* Search for the proper mode for copying this register's
                   7785:               value.  I'm not sure this is right, but it works so far.  */
                   7786:            enum machine_mode best_mode = VOIDmode;
                   7787: 
                   7788:            for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
                   7789:                 mode != TImode;
                   7790:                 mode = GET_MODE_WIDER_MODE (mode))
                   7791:              if (HARD_REGNO_MODE_OK (regno, mode))
                   7792:                best_mode = mode;
                   7793: 
                   7794:            if (best_mode == VOIDmode)
                   7795:              for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
                   7796:                   mode != VOIDmode;
                   7797:                   mode = GET_MODE_WIDER_MODE (mode))
                   7798:                if (HARD_REGNO_MODE_OK (regno, mode)
                   7799:                    && (mov_optab->handlers[(int) mode].insn_code
                   7800:                        != CODE_FOR_nothing))
                   7801:                  best_mode = mode;
                   7802: 
                   7803:            mode = best_mode;
                   7804:            if (mode == VOIDmode)
                   7805:              abort ();
                   7806: 
                   7807:            align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                   7808:            if (size % align != 0)
                   7809:              size = CEIL (size, align) * align;
                   7810:            size += GET_MODE_SIZE (mode);
                   7811:            apply_result_mode[regno] = mode;
1.1       root     7812:          }
1.1.1.6   root     7813:        else
                   7814:          apply_result_mode[regno] = VOIDmode;
                   7815: 
                   7816:       /* Allow targets that use untyped_call and untyped_return to override
                   7817:         the size so that machine-specific information can be stored here.  */
                   7818: #ifdef APPLY_RESULT_SIZE
                   7819:       size = APPLY_RESULT_SIZE;
                   7820: #endif
                   7821:     }
                   7822:   return size;
                   7823: }
                   7824: 
                   7825: #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
                   7826: /* Create a vector describing the result block RESULT.  If SAVEP is true,
                   7827:    the result block is used to save the values; otherwise it is used to
                   7828:    restore the values.  */
                   7829: 
                   7830: static rtx
                   7831: result_vector (savep, result)
                   7832:      int savep;
                   7833:      rtx result;
                   7834: {
                   7835:   int regno, size, align, nelts;
                   7836:   enum machine_mode mode;
                   7837:   rtx reg, mem;
                   7838:   rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
                   7839:   
                   7840:   size = nelts = 0;
                   7841:   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   7842:     if ((mode = apply_result_mode[regno]) != VOIDmode)
                   7843:       {
                   7844:        align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                   7845:        if (size % align != 0)
                   7846:          size = CEIL (size, align) * align;
1.1.1.7 ! root     7847:        reg = gen_rtx (REG, mode, savep ? regno : INCOMING_REGNO (regno));
1.1.1.6   root     7848:        mem = change_address (result, mode,
                   7849:                              plus_constant (XEXP (result, 0), size));
                   7850:        savevec[nelts++] = (savep
                   7851:                            ? gen_rtx (SET, VOIDmode, mem, reg)
                   7852:                            : gen_rtx (SET, VOIDmode, reg, mem));
                   7853:        size += GET_MODE_SIZE (mode);
                   7854:       }
                   7855:   return gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (nelts, savevec));
                   7856: }
                   7857: #endif /* HAVE_untyped_call or HAVE_untyped_return */
1.1       root     7858: 
1.1.1.6   root     7859: /* Save the state required to perform an untyped call with the same
                   7860:    arguments as were passed to the current function.  */
1.1       root     7861: 
1.1.1.6   root     7862: static rtx
                   7863: expand_builtin_apply_args ()
                   7864: {
                   7865:   rtx registers;
                   7866:   int size, align, regno;
                   7867:   enum machine_mode mode;
1.1       root     7868: 
1.1.1.6   root     7869:   /* Create a block where the arg-pointer, structure value address,
                   7870:      and argument registers can be saved.  */
                   7871:   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1.1       root     7872: 
1.1.1.6   root     7873:   /* Walk past the arg-pointer and structure value address.  */
                   7874:   size = GET_MODE_SIZE (Pmode);
                   7875:   if (struct_value_rtx)
                   7876:     size += GET_MODE_SIZE (Pmode);
1.1       root     7877: 
1.1.1.6   root     7878:   /* Save each register used in calling a function to the block.  */
                   7879:   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   7880:     if ((mode = apply_args_mode[regno]) != VOIDmode)
                   7881:       {
                   7882:        align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                   7883:        if (size % align != 0)
                   7884:          size = CEIL (size, align) * align;
                   7885:        emit_move_insn (change_address (registers, mode,
                   7886:                                        plus_constant (XEXP (registers, 0),
                   7887:                                                       size)),
                   7888:                        gen_rtx (REG, mode, INCOMING_REGNO (regno)));
                   7889:        size += GET_MODE_SIZE (mode);
1.1       root     7890:       }
                   7891: 
1.1.1.6   root     7892:   /* Save the arg pointer to the block.  */
                   7893:   emit_move_insn (change_address (registers, Pmode, XEXP (registers, 0)),
                   7894:                  copy_to_reg (virtual_incoming_args_rtx));
                   7895:   size = GET_MODE_SIZE (Pmode);
1.1       root     7896: 
1.1.1.6   root     7897:   /* Save the structure value address unless this is passed as an
                   7898:      "invisible" first argument.  */
                   7899:   if (struct_value_incoming_rtx)
                   7900:     {
                   7901:       emit_move_insn (change_address (registers, Pmode,
                   7902:                                      plus_constant (XEXP (registers, 0),
                   7903:                                                     size)),
                   7904:                      copy_to_reg (struct_value_incoming_rtx));
                   7905:       size += GET_MODE_SIZE (Pmode);
                   7906:     }
1.1       root     7907: 
1.1.1.6   root     7908:   /* Return the address of the block.  */
                   7909:   return copy_addr_to_reg (XEXP (registers, 0));
                   7910: }
1.1       root     7911: 
1.1.1.6   root     7912: /* Perform an untyped call and save the state required to perform an
                   7913:    untyped return of whatever value was returned by the given function.  */
1.1       root     7914: 
1.1.1.6   root     7915: static rtx
                   7916: expand_builtin_apply (function, arguments, argsize)
                   7917:      rtx function, arguments, argsize;
                   7918: {
                   7919:   int size, align, regno;
                   7920:   enum machine_mode mode;
                   7921:   rtx incoming_args, result, reg, dest, call_insn;
                   7922:   rtx old_stack_level = 0;
1.1.1.7 ! root     7923:   rtx call_fusage = 0;
1.1       root     7924: 
1.1.1.6   root     7925:   /* Create a block where the return registers can be saved.  */
                   7926:   result = assign_stack_local (BLKmode, apply_result_size (), -1);
1.1       root     7927: 
1.1.1.6   root     7928:   /* ??? The argsize value should be adjusted here.  */
                   7929: 
                   7930:   /* Fetch the arg pointer from the ARGUMENTS block.  */
                   7931:   incoming_args = gen_reg_rtx (Pmode);
                   7932:   emit_move_insn (incoming_args,
                   7933:                  gen_rtx (MEM, Pmode, arguments));
                   7934: #ifndef STACK_GROWS_DOWNWARD
                   7935:   incoming_args = expand_binop (Pmode, sub_optab, incoming_args, argsize,
                   7936:                                incoming_args, 0, OPTAB_LIB_WIDEN);
1.1       root     7937: #endif
                   7938: 
1.1.1.6   root     7939:   /* Perform postincrements before actually calling the function.  */
                   7940:   emit_queue ();
1.1       root     7941: 
1.1.1.6   root     7942:   /* Push a new argument block and copy the arguments.  */
                   7943:   do_pending_stack_adjust ();
                   7944:   emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1.1       root     7945: 
1.1.1.6   root     7946:   /* Push a block of memory onto the stack to store the memory arguments.
                   7947:      Save the address in a register, and copy the memory arguments.  ??? I
                   7948:      haven't figured out how the calling convention macros effect this,
                   7949:      but it's likely that the source and/or destination addresses in
                   7950:      the block copy will need updating in machine specific ways.  */
                   7951:   dest = copy_addr_to_reg (push_block (argsize, 0, 0));
                   7952:   emit_block_move (gen_rtx (MEM, BLKmode, dest),
                   7953:                   gen_rtx (MEM, BLKmode, incoming_args),
                   7954:                   argsize,
                   7955:                   PARM_BOUNDARY / BITS_PER_UNIT);
1.1       root     7956: 
1.1.1.6   root     7957:   /* Refer to the argument block.  */
                   7958:   apply_args_size ();
                   7959:   arguments = gen_rtx (MEM, BLKmode, arguments);
1.1       root     7960: 
1.1.1.6   root     7961:   /* Walk past the arg-pointer and structure value address.  */
                   7962:   size = GET_MODE_SIZE (Pmode);
                   7963:   if (struct_value_rtx)
                   7964:     size += GET_MODE_SIZE (Pmode);
                   7965: 
                   7966:   /* Restore each of the registers previously saved.  Make USE insns
                   7967:      for each of these registers for use in making the call.  */
                   7968:   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   7969:     if ((mode = apply_args_mode[regno]) != VOIDmode)
                   7970:       {
                   7971:        align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                   7972:        if (size % align != 0)
                   7973:          size = CEIL (size, align) * align;
                   7974:        reg = gen_rtx (REG, mode, regno);
                   7975:        emit_move_insn (reg,
                   7976:                        change_address (arguments, mode,
                   7977:                                        plus_constant (XEXP (arguments, 0),
                   7978:                                                       size)));
                   7979: 
1.1.1.7 ! root     7980:        use_reg (&call_fusage, reg);
1.1.1.6   root     7981:        size += GET_MODE_SIZE (mode);
                   7982:       }
                   7983: 
                   7984:   /* Restore the structure value address unless this is passed as an
                   7985:      "invisible" first argument.  */
                   7986:   size = GET_MODE_SIZE (Pmode);
                   7987:   if (struct_value_rtx)
                   7988:     {
                   7989:       rtx value = gen_reg_rtx (Pmode);
                   7990:       emit_move_insn (value,
                   7991:                      change_address (arguments, Pmode,
                   7992:                                      plus_constant (XEXP (arguments, 0),
                   7993:                                                     size)));
                   7994:       emit_move_insn (struct_value_rtx, value);
                   7995:       if (GET_CODE (struct_value_rtx) == REG)
1.1.1.7 ! root     7996:          use_reg (&call_fusage, struct_value_rtx);
1.1.1.6   root     7997:       size += GET_MODE_SIZE (Pmode);
                   7998:     }
1.1       root     7999: 
1.1.1.6   root     8000:   /* All arguments and registers used for the call are set up by now!  */
1.1.1.7 ! root     8001:   function = prepare_call_address (function, NULL_TREE, &call_fusage, 0);
1.1.1.5   root     8002: 
1.1.1.6   root     8003:   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
                   8004:      and we don't want to load it into a register as an optimization,
                   8005:      because prepare_call_address already did it if it should be done.  */
                   8006:   if (GET_CODE (function) != SYMBOL_REF)
                   8007:     function = memory_address (FUNCTION_MODE, function);
1.1.1.5   root     8008: 
1.1.1.6   root     8009:   /* Generate the actual call instruction and save the return value.  */
                   8010: #ifdef HAVE_untyped_call
                   8011:   if (HAVE_untyped_call)
                   8012:     emit_call_insn (gen_untyped_call (gen_rtx (MEM, FUNCTION_MODE, function),
                   8013:                                      result, result_vector (1, result)));
                   8014:   else
1.1       root     8015: #endif
1.1.1.6   root     8016: #ifdef HAVE_call_value
                   8017:   if (HAVE_call_value)
                   8018:     {
                   8019:       rtx valreg = 0;
1.1       root     8020: 
1.1.1.6   root     8021:       /* Locate the unique return register.  It is not possible to
                   8022:         express a call that sets more than one return register using
                   8023:         call_value; use untyped_call for that.  In fact, untyped_call
                   8024:         only needs to save the return registers in the given block.  */
                   8025:       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   8026:        if ((mode = apply_result_mode[regno]) != VOIDmode)
                   8027:          {
                   8028:            if (valreg)
                   8029:              abort (); /* HAVE_untyped_call required.  */
                   8030:            valreg = gen_rtx (REG, mode, regno);
                   8031:          }
1.1       root     8032: 
1.1.1.6   root     8033:       emit_call_insn (gen_call_value (valreg,
                   8034:                                      gen_rtx (MEM, FUNCTION_MODE, function),
                   8035:                                      const0_rtx, NULL_RTX, const0_rtx));
                   8036: 
                   8037:       emit_move_insn (change_address (result, GET_MODE (valreg),
                   8038:                                      XEXP (result, 0)),
                   8039:                      valreg);
                   8040:     }
                   8041:   else
1.1       root     8042: #endif
1.1.1.6   root     8043:     abort ();
1.1       root     8044: 
1.1.1.7 ! root     8045:   /* Find the CALL insn we just emitted.  */
1.1.1.6   root     8046:   for (call_insn = get_last_insn ();
                   8047:        call_insn && GET_CODE (call_insn) != CALL_INSN;
                   8048:        call_insn = PREV_INSN (call_insn))
                   8049:     ;
1.1       root     8050: 
1.1.1.6   root     8051:   if (! call_insn)
                   8052:     abort ();
1.1       root     8053: 
1.1.1.7 ! root     8054:   /* Put the register usage information on the CALL.  If there is already
        !          8055:      some usage information, put ours at the end.  */
        !          8056:   if (CALL_INSN_FUNCTION_USAGE (call_insn))
        !          8057:     {
        !          8058:       rtx link;
        !          8059: 
        !          8060:       for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
        !          8061:           link = XEXP (link, 1))
        !          8062:        ;
        !          8063: 
        !          8064:       XEXP (link, 1) = call_fusage;
        !          8065:     }
        !          8066:   else
        !          8067:     CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1.1       root     8068: 
1.1.1.6   root     8069:   /* Restore the stack.  */
                   8070:   emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1.1       root     8071: 
1.1.1.6   root     8072:   /* Return the address of the result block.  */
                   8073:   return copy_addr_to_reg (XEXP (result, 0));
                   8074: }
1.1       root     8075: 
1.1.1.6   root     8076: /* Perform an untyped return.  */
1.1       root     8077: 
1.1.1.6   root     8078: static void
                   8079: expand_builtin_return (result)
                   8080:      rtx result;
                   8081: {
                   8082:   int size, align, regno;
                   8083:   enum machine_mode mode;
                   8084:   rtx reg;
1.1.1.7 ! root     8085:   rtx call_fusage = 0;
1.1       root     8086: 
1.1.1.6   root     8087:   apply_result_size ();
                   8088:   result = gen_rtx (MEM, BLKmode, result);
1.1       root     8089: 
1.1.1.6   root     8090: #ifdef HAVE_untyped_return
                   8091:   if (HAVE_untyped_return)
                   8092:     {
                   8093:       emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
                   8094:       emit_barrier ();
                   8095:       return;
                   8096:     }
                   8097: #endif
1.1.1.3   root     8098: 
1.1.1.6   root     8099:   /* Restore the return value and note that each value is used.  */
                   8100:   size = 0;
                   8101:   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   8102:     if ((mode = apply_result_mode[regno]) != VOIDmode)
                   8103:       {
                   8104:        align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                   8105:        if (size % align != 0)
                   8106:          size = CEIL (size, align) * align;
                   8107:        reg = gen_rtx (REG, mode, INCOMING_REGNO (regno));
                   8108:        emit_move_insn (reg,
                   8109:                        change_address (result, mode,
                   8110:                                        plus_constant (XEXP (result, 0),
                   8111:                                                       size)));
1.1.1.3   root     8112: 
1.1.1.7 ! root     8113:        push_to_sequence (call_fusage);
1.1.1.6   root     8114:        emit_insn (gen_rtx (USE, VOIDmode, reg));
1.1.1.7 ! root     8115:        call_fusage = get_insns ();
1.1.1.6   root     8116:        end_sequence ();
                   8117:        size += GET_MODE_SIZE (mode);
                   8118:       }
1.1.1.3   root     8119: 
1.1.1.6   root     8120:   /* Put the USE insns before the return.  */
1.1.1.7 ! root     8121:   emit_insns (call_fusage);
1.1.1.3   root     8122: 
1.1.1.6   root     8123:   /* Return whatever values was restored by jumping directly to the end
                   8124:      of the function.  */
                   8125:   expand_null_return ();
                   8126: }
                   8127: 
                   8128: /* Expand code for a post- or pre- increment or decrement
                   8129:    and return the RTX for the result.
                   8130:    POST is 1 for postinc/decrements and 0 for preinc/decrements.  */
1.1.1.3   root     8131: 
1.1.1.6   root     8132: static rtx
                   8133: expand_increment (exp, post)
                   8134:      register tree exp;
                   8135:      int post;
                   8136: {
                   8137:   register rtx op0, op1;
                   8138:   register rtx temp, value;
                   8139:   register tree incremented = TREE_OPERAND (exp, 0);
                   8140:   optab this_optab = add_optab;
                   8141:   int icode;
                   8142:   enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
                   8143:   int op0_is_copy = 0;
                   8144:   int single_insn = 0;
                   8145:   /* 1 means we can't store into OP0 directly,
                   8146:      because it is a subreg narrower than a word,
                   8147:      and we don't dare clobber the rest of the word.  */
                   8148:   int bad_subreg = 0;
1.1.1.3   root     8149: 
1.1.1.6   root     8150:   if (output_bytecode)
                   8151:     {
                   8152:       bc_expand_expr (exp);
                   8153:       return NULL_RTX;
                   8154:     }
                   8155: 
                   8156:   /* Stabilize any component ref that might need to be
                   8157:      evaluated more than once below.  */
                   8158:   if (!post
                   8159:       || TREE_CODE (incremented) == BIT_FIELD_REF
                   8160:       || (TREE_CODE (incremented) == COMPONENT_REF
                   8161:          && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
                   8162:              || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1)))))
                   8163:     incremented = stabilize_reference (incremented);
                   8164:   /* Nested *INCREMENT_EXPRs can happen in C++.  We must force innermost
                   8165:      ones into save exprs so that they don't accidentally get evaluated
                   8166:      more than once by the code below.  */
                   8167:   if (TREE_CODE (incremented) == PREINCREMENT_EXPR
                   8168:       || TREE_CODE (incremented) == PREDECREMENT_EXPR)
                   8169:     incremented = save_expr (incremented);
1.1.1.3   root     8170: 
1.1.1.6   root     8171:   /* Compute the operands as RTX.
                   8172:      Note whether OP0 is the actual lvalue or a copy of it:
                   8173:      I believe it is a copy iff it is a register or subreg
                   8174:      and insns were generated in computing it.   */
1.1.1.3   root     8175: 
1.1.1.6   root     8176:   temp = get_last_insn ();
                   8177:   op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0);
1.1.1.3   root     8178: 
1.1.1.6   root     8179:   /* If OP0 is a SUBREG made for a promoted variable, we cannot increment
                   8180:      in place but intead must do sign- or zero-extension during assignment,
                   8181:      so we copy it into a new register and let the code below use it as
                   8182:      a copy.
1.1.1.3   root     8183: 
1.1.1.6   root     8184:      Note that we can safely modify this SUBREG since it is know not to be
                   8185:      shared (it was made by the expand_expr call above).  */
1.1.1.3   root     8186: 
1.1.1.6   root     8187:   if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0))
1.1.1.7 ! root     8188:     {
        !          8189:       if (post)
        !          8190:        SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0));
        !          8191:       else
        !          8192:        bad_subreg = 1;
        !          8193:     }
1.1.1.6   root     8194:   else if (GET_CODE (op0) == SUBREG
                   8195:           && GET_MODE_BITSIZE (GET_MODE (op0)) < BITS_PER_WORD)
1.1.1.7 ! root     8196:     {
        !          8197:       /* We cannot increment this SUBREG in place.  If we are
        !          8198:         post-incrementing, get a copy of the old value.  Otherwise,
        !          8199:         just mark that we cannot increment in place.  */
        !          8200:       if (post)
        !          8201:        op0 = copy_to_reg (op0);
        !          8202:       else
        !          8203:        bad_subreg = 1;
        !          8204:     }
1.1.1.3   root     8205: 
1.1.1.6   root     8206:   op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
                   8207:                 && temp != get_last_insn ());
                   8208:   op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1.1.3   root     8209: 
1.1.1.6   root     8210:   /* Decide whether incrementing or decrementing.  */
                   8211:   if (TREE_CODE (exp) == POSTDECREMENT_EXPR
                   8212:       || TREE_CODE (exp) == PREDECREMENT_EXPR)
                   8213:     this_optab = sub_optab;
1.1       root     8214: 
1.1.1.6   root     8215:   /* Convert decrement by a constant into a negative increment.  */
                   8216:   if (this_optab == sub_optab
                   8217:       && GET_CODE (op1) == CONST_INT)
                   8218:     {
                   8219:       op1 = GEN_INT (- INTVAL (op1));
                   8220:       this_optab = add_optab;
                   8221:     }
1.1       root     8222: 
1.1.1.6   root     8223:   /* For a preincrement, see if we can do this with a single instruction.  */
                   8224:   if (!post)
                   8225:     {
                   8226:       icode = (int) this_optab->handlers[(int) mode].insn_code;
                   8227:       if (icode != (int) CODE_FOR_nothing
                   8228:          /* Make sure that OP0 is valid for operands 0 and 1
                   8229:             of the insn we want to queue.  */
                   8230:          && (*insn_operand_predicate[icode][0]) (op0, mode)
                   8231:          && (*insn_operand_predicate[icode][1]) (op0, mode)
                   8232:          && (*insn_operand_predicate[icode][2]) (op1, mode))
                   8233:        single_insn = 1;
                   8234:     }
1.1       root     8235: 
1.1.1.6   root     8236:   /* If OP0 is not the actual lvalue, but rather a copy in a register,
                   8237:      then we cannot just increment OP0.  We must therefore contrive to
                   8238:      increment the original value.  Then, for postincrement, we can return
                   8239:      OP0 since it is a copy of the old value.  For preincrement, expand here
                   8240:      unless we can do it with a single insn.
1.1       root     8241: 
1.1.1.6   root     8242:      Likewise if storing directly into OP0 would clobber high bits
                   8243:      we need to preserve (bad_subreg).  */
                   8244:   if (op0_is_copy || (!post && !single_insn) || bad_subreg)
                   8245:     {
                   8246:       /* This is the easiest way to increment the value wherever it is.
                   8247:         Problems with multiple evaluation of INCREMENTED are prevented
                   8248:         because either (1) it is a component_ref or preincrement,
                   8249:         in which case it was stabilized above, or (2) it is an array_ref
                   8250:         with constant index in an array in a register, which is
                   8251:         safe to reevaluate.  */
                   8252:       tree newexp = build (((TREE_CODE (exp) == POSTDECREMENT_EXPR
                   8253:                             || TREE_CODE (exp) == PREDECREMENT_EXPR)
                   8254:                            ? MINUS_EXPR : PLUS_EXPR),
                   8255:                           TREE_TYPE (exp),
                   8256:                           incremented,
                   8257:                           TREE_OPERAND (exp, 1));
                   8258:       temp = expand_assignment (incremented, newexp, ! post, 0);
                   8259:       return post ? op0 : temp;
                   8260:     }
1.1       root     8261: 
1.1.1.6   root     8262:   if (post)
                   8263:     {
                   8264:       /* We have a true reference to the value in OP0.
                   8265:         If there is an insn to add or subtract in this mode, queue it.
                   8266:         Queueing the increment insn avoids the register shuffling
                   8267:         that often results if we must increment now and first save
                   8268:         the old value for subsequent use.  */
1.1       root     8269: 
1.1.1.6   root     8270: #if 0  /* Turned off to avoid making extra insn for indexed memref.  */
                   8271:       op0 = stabilize (op0);
                   8272: #endif
1.1       root     8273: 
1.1.1.6   root     8274:       icode = (int) this_optab->handlers[(int) mode].insn_code;
                   8275:       if (icode != (int) CODE_FOR_nothing
                   8276:          /* Make sure that OP0 is valid for operands 0 and 1
                   8277:             of the insn we want to queue.  */
                   8278:          && (*insn_operand_predicate[icode][0]) (op0, mode)
                   8279:          && (*insn_operand_predicate[icode][1]) (op0, mode))
1.1       root     8280:        {
1.1.1.6   root     8281:          if (! (*insn_operand_predicate[icode][2]) (op1, mode))
                   8282:            op1 = force_reg (mode, op1);
1.1       root     8283: 
1.1.1.6   root     8284:          return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
                   8285:        }
                   8286:     }
1.1       root     8287: 
1.1.1.6   root     8288:   /* Preincrement, or we can't increment with one simple insn.  */
                   8289:   if (post)
                   8290:     /* Save a copy of the value before inc or dec, to return it later.  */
                   8291:     temp = value = copy_to_reg (op0);
                   8292:   else
                   8293:     /* Arrange to return the incremented value.  */
                   8294:     /* Copy the rtx because expand_binop will protect from the queue,
                   8295:        and the results of that would be invalid for us to return
                   8296:        if our caller does emit_queue before using our result.  */
                   8297:     temp = copy_rtx (value = op0);
1.1       root     8298: 
1.1.1.6   root     8299:   /* Increment however we can.  */
                   8300:   op1 = expand_binop (mode, this_optab, value, op1, op0,
                   8301:                      TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
                   8302:   /* Make sure the value is stored into OP0.  */
                   8303:   if (op1 != op0)
                   8304:     emit_move_insn (op0, op1);
1.1       root     8305: 
1.1.1.6   root     8306:   return temp;
                   8307: }
                   8308: 
                   8309: /* Expand all function calls contained within EXP, innermost ones first.
                   8310:    But don't look within expressions that have sequence points.
                   8311:    For each CALL_EXPR, record the rtx for its value
                   8312:    in the CALL_EXPR_RTL field.  */
1.1       root     8313: 
1.1.1.6   root     8314: static void
                   8315: preexpand_calls (exp)
                   8316:      tree exp;
                   8317: {
                   8318:   register int nops, i;
                   8319:   int type = TREE_CODE_CLASS (TREE_CODE (exp));
1.1       root     8320: 
1.1.1.6   root     8321:   if (! do_preexpand_calls)
                   8322:     return;
1.1       root     8323: 
1.1.1.6   root     8324:   /* Only expressions and references can contain calls.  */
1.1       root     8325: 
1.1.1.6   root     8326:   if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r')
                   8327:     return;
1.1       root     8328: 
1.1.1.6   root     8329:   switch (TREE_CODE (exp))
                   8330:     {
                   8331:     case CALL_EXPR:
                   8332:       /* Do nothing if already expanded.  */
                   8333:       if (CALL_EXPR_RTL (exp) != 0)
                   8334:        return;
1.1       root     8335: 
1.1.1.6   root     8336:       /* Do nothing to built-in functions.  */
                   8337:       if (TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR
                   8338:          || TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL
1.1.1.7 ! root     8339:          || ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
        !          8340:          /* Do nothing if the call returns a variable-sized object.  */
        !          8341:          || TREE_CODE (TYPE_SIZE (TREE_TYPE(exp))) != INTEGER_CST)
1.1.1.6   root     8342:        CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0);
                   8343:       return;
1.1       root     8344: 
1.1.1.6   root     8345:     case COMPOUND_EXPR:
                   8346:     case COND_EXPR:
                   8347:     case TRUTH_ANDIF_EXPR:
                   8348:     case TRUTH_ORIF_EXPR:
                   8349:       /* If we find one of these, then we can be sure
                   8350:         the adjust will be done for it (since it makes jumps).
                   8351:         Do it now, so that if this is inside an argument
                   8352:         of a function, we don't get the stack adjustment
                   8353:         after some other args have already been pushed.  */
                   8354:       do_pending_stack_adjust ();
                   8355:       return;
1.1       root     8356: 
1.1.1.6   root     8357:     case BLOCK:
                   8358:     case RTL_EXPR:
                   8359:     case WITH_CLEANUP_EXPR:
                   8360:       return;
1.1       root     8361: 
1.1.1.6   root     8362:     case SAVE_EXPR:
                   8363:       if (SAVE_EXPR_RTL (exp) != 0)
                   8364:        return;
                   8365:     }
1.1       root     8366: 
1.1.1.6   root     8367:   nops = tree_code_length[(int) TREE_CODE (exp)];
                   8368:   for (i = 0; i < nops; i++)
                   8369:     if (TREE_OPERAND (exp, i) != 0)
                   8370:       {
                   8371:        type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i)));
                   8372:        if (type == 'e' || type == '<' || type == '1' || type == '2'
                   8373:            || type == 'r')
                   8374:          preexpand_calls (TREE_OPERAND (exp, i));
                   8375:       }
                   8376: }
                   8377: 
                   8378: /* At the start of a function, record that we have no previously-pushed
                   8379:    arguments waiting to be popped.  */
1.1       root     8380: 
1.1.1.6   root     8381: void
                   8382: init_pending_stack_adjust ()
                   8383: {
                   8384:   pending_stack_adjust = 0;
                   8385: }
1.1       root     8386: 
1.1.1.6   root     8387: /* When exiting from function, if safe, clear out any pending stack adjust
                   8388:    so the adjustment won't get done.  */
1.1       root     8389: 
1.1.1.6   root     8390: void
                   8391: clear_pending_stack_adjust ()
                   8392: {
                   8393: #ifdef EXIT_IGNORE_STACK
                   8394:   if (! flag_omit_frame_pointer && EXIT_IGNORE_STACK
                   8395:       && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
                   8396:       && ! flag_inline_functions)
                   8397:     pending_stack_adjust = 0;
1.1       root     8398: #endif
1.1.1.6   root     8399: }
1.1       root     8400: 
1.1.1.6   root     8401: /* Pop any previously-pushed arguments that have not been popped yet.  */
                   8402: 
                   8403: void
                   8404: do_pending_stack_adjust ()
                   8405: {
                   8406:   if (inhibit_defer_pop == 0)
                   8407:     {
                   8408:       if (pending_stack_adjust != 0)
                   8409:        adjust_stack (GEN_INT (pending_stack_adjust));
                   8410:       pending_stack_adjust = 0;
1.1       root     8411:     }
1.1.1.6   root     8412: }
1.1       root     8413: 
1.1.1.7 ! root     8414: /* Defer the expansion all cleanups up to OLD_CLEANUPS.
        !          8415:    Returns the cleanups to be performed.  */
        !          8416: 
        !          8417: static tree
        !          8418: defer_cleanups_to (old_cleanups)
        !          8419:      tree old_cleanups;
        !          8420: {
        !          8421:   tree new_cleanups = NULL_TREE;
        !          8422:   tree cleanups = cleanups_this_call;
        !          8423:   tree last = NULL_TREE;
        !          8424: 
        !          8425:   while (cleanups_this_call != old_cleanups)
        !          8426:     {
        !          8427:       (*interim_eh_hook) (TREE_VALUE (cleanups_this_call));
        !          8428:       last = cleanups_this_call;
        !          8429:       cleanups_this_call = TREE_CHAIN (cleanups_this_call);
        !          8430:     }      
        !          8431: 
        !          8432:   if (last)
        !          8433:     {
        !          8434:       /* Remove the list from the chain of cleanups.  */
        !          8435:       TREE_CHAIN (last) = NULL_TREE;
        !          8436: 
        !          8437:       /* reverse them so that we can build them in the right order.  */
        !          8438:       cleanups = nreverse (cleanups);
        !          8439: 
        !          8440:       while (cleanups)
        !          8441:        {
        !          8442:          if (new_cleanups)
        !          8443:            new_cleanups = build (COMPOUND_EXPR, TREE_TYPE (new_cleanups),
        !          8444:                                  TREE_VALUE (cleanups), new_cleanups);
        !          8445:          else
        !          8446:            new_cleanups = TREE_VALUE (cleanups);
        !          8447: 
        !          8448:          cleanups = TREE_CHAIN (cleanups);
        !          8449:        }
        !          8450:     }
        !          8451: 
        !          8452:   return new_cleanups;
        !          8453: }
        !          8454: 
1.1.1.6   root     8455: /* Expand all cleanups up to OLD_CLEANUPS.
                   8456:    Needed here, and also for language-dependent calls.  */
1.1       root     8457: 
1.1.1.6   root     8458: void
                   8459: expand_cleanups_to (old_cleanups)
                   8460:      tree old_cleanups;
                   8461: {
                   8462:   while (cleanups_this_call != old_cleanups)
                   8463:     {
1.1.1.7 ! root     8464:       (*interim_eh_hook) (TREE_VALUE (cleanups_this_call));
        !          8465:       expand_expr (TREE_VALUE (cleanups_this_call), const0_rtx, VOIDmode, 0);
1.1.1.6   root     8466:       cleanups_this_call = TREE_CHAIN (cleanups_this_call);
                   8467:     }
1.1       root     8468: }
                   8469: 
1.1.1.6   root     8470: /* Expand conditional expressions.  */
1.1.1.5   root     8471: 
1.1.1.6   root     8472: /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
                   8473:    LABEL is an rtx of code CODE_LABEL, in this function and all the
                   8474:    functions here.  */
1.1.1.5   root     8475: 
1.1.1.6   root     8476: void
                   8477: jumpifnot (exp, label)
                   8478:      tree exp;
                   8479:      rtx label;
                   8480: {
                   8481:   do_jump (exp, label, NULL_RTX);
                   8482: }
1.1.1.5   root     8483: 
1.1.1.6   root     8484: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
                   8485: 
                   8486: void
                   8487: jumpif (exp, label)
                   8488:      tree exp;
                   8489:      rtx label;
1.1.1.5   root     8490: {
1.1.1.6   root     8491:   do_jump (exp, NULL_RTX, label);
                   8492: }
                   8493: 
                   8494: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
                   8495:    the result is zero, or IF_TRUE_LABEL if the result is one.
                   8496:    Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
                   8497:    meaning fall through in that case.
                   8498: 
                   8499:    do_jump always does any pending stack adjust except when it does not
                   8500:    actually perform a jump.  An example where there is no jump
                   8501:    is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
                   8502: 
                   8503:    This function is responsible for optimizing cases such as
                   8504:    &&, || and comparison operators in EXP.  */
                   8505: 
                   8506: void
                   8507: do_jump (exp, if_false_label, if_true_label)
                   8508:      tree exp;
                   8509:      rtx if_false_label, if_true_label;
                   8510: {
                   8511:   register enum tree_code code = TREE_CODE (exp);
                   8512:   /* Some cases need to create a label to jump to
                   8513:      in order to properly fall through.
                   8514:      These cases set DROP_THROUGH_LABEL nonzero.  */
                   8515:   rtx drop_through_label = 0;
                   8516:   rtx temp;
                   8517:   rtx comparison = 0;
                   8518:   int i;
                   8519:   tree type;
1.1.1.7 ! root     8520:   enum machine_mode mode;
1.1.1.6   root     8521: 
                   8522:   emit_queue ();
                   8523: 
                   8524:   switch (code)
                   8525:     {
                   8526:     case ERROR_MARK:
                   8527:       break;
                   8528: 
                   8529:     case INTEGER_CST:
                   8530:       temp = integer_zerop (exp) ? if_false_label : if_true_label;
                   8531:       if (temp)
                   8532:        emit_jump (temp);
                   8533:       break;
                   8534: 
                   8535: #if 0
                   8536:       /* This is not true with #pragma weak  */
                   8537:     case ADDR_EXPR:
                   8538:       /* The address of something can never be zero.  */
                   8539:       if (if_true_label)
                   8540:        emit_jump (if_true_label);
                   8541:       break;
                   8542: #endif
                   8543: 
                   8544:     case NOP_EXPR:
                   8545:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
                   8546:          || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
                   8547:          || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF)
                   8548:        goto normal;
                   8549:     case CONVERT_EXPR:
                   8550:       /* If we are narrowing the operand, we have to do the compare in the
                   8551:         narrower mode.  */
                   8552:       if ((TYPE_PRECISION (TREE_TYPE (exp))
                   8553:           < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   8554:        goto normal;
                   8555:     case NON_LVALUE_EXPR:
                   8556:     case REFERENCE_EXPR:
                   8557:     case ABS_EXPR:
                   8558:     case NEGATE_EXPR:
                   8559:     case LROTATE_EXPR:
                   8560:     case RROTATE_EXPR:
                   8561:       /* These cannot change zero->non-zero or vice versa.  */
                   8562:       do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
                   8563:       break;
1.1.1.5   root     8564: 
1.1.1.6   root     8565: #if 0
                   8566:       /* This is never less insns than evaluating the PLUS_EXPR followed by
                   8567:         a test and can be longer if the test is eliminated.  */
                   8568:     case PLUS_EXPR:
                   8569:       /* Reduce to minus.  */
                   8570:       exp = build (MINUS_EXPR, TREE_TYPE (exp),
                   8571:                   TREE_OPERAND (exp, 0),
                   8572:                   fold (build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
                   8573:                                 TREE_OPERAND (exp, 1))));
                   8574:       /* Process as MINUS.  */
                   8575: #endif
1.1.1.5   root     8576: 
1.1.1.6   root     8577:     case MINUS_EXPR:
                   8578:       /* Non-zero iff operands of minus differ.  */
                   8579:       comparison = compare (build (NE_EXPR, TREE_TYPE (exp),
                   8580:                                   TREE_OPERAND (exp, 0),
                   8581:                                   TREE_OPERAND (exp, 1)),
                   8582:                            NE, NE);
                   8583:       break;
1.1.1.5   root     8584: 
1.1.1.6   root     8585:     case BIT_AND_EXPR:
                   8586:       /* If we are AND'ing with a small constant, do this comparison in the
                   8587:         smallest type that fits.  If the machine doesn't have comparisons
                   8588:         that small, it will be converted back to the wider comparison.
                   8589:         This helps if we are testing the sign bit of a narrower object.
                   8590:         combine can't do this for us because it can't know whether a
                   8591:         ZERO_EXTRACT or a compare in a smaller mode exists, but we do.  */
1.1.1.5   root     8592: 
1.1.1.6   root     8593:       if (! SLOW_BYTE_ACCESS
                   8594:          && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   8595:          && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
                   8596:          && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0
1.1.1.7 ! root     8597:          && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
        !          8598:          && (type = type_for_mode (mode, 1)) != 0
1.1.1.6   root     8599:          && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
                   8600:          && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
                   8601:              != CODE_FOR_nothing))
                   8602:        {
                   8603:          do_jump (convert (type, exp), if_false_label, if_true_label);
                   8604:          break;
                   8605:        }
                   8606:       goto normal;
1.1.1.5   root     8607: 
1.1.1.6   root     8608:     case TRUTH_NOT_EXPR:
                   8609:       do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
                   8610:       break;
1.1.1.5   root     8611: 
1.1.1.6   root     8612:     case TRUTH_ANDIF_EXPR:
1.1.1.7 ! root     8613:       {
        !          8614:        rtx seq1, seq2;
        !          8615:        tree cleanups, old_cleanups;
        !          8616: 
        !          8617:        if (if_false_label == 0)
        !          8618:          if_false_label = drop_through_label = gen_label_rtx ();
        !          8619:        start_sequence ();
        !          8620:        do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
        !          8621:        seq1 = get_insns ();
        !          8622:        end_sequence ();
        !          8623: 
        !          8624:        old_cleanups = cleanups_this_call;
        !          8625:        start_sequence ();
        !          8626:        do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
        !          8627:        seq2 = get_insns ();
        !          8628:        end_sequence ();
        !          8629: 
        !          8630:        cleanups = defer_cleanups_to (old_cleanups);
        !          8631:        if (cleanups)
        !          8632:          {
        !          8633:            rtx flag = gen_reg_rtx (word_mode);
        !          8634:            tree new_cleanups;
        !          8635:            tree cond;
        !          8636: 
        !          8637:            /* Flag cleanups as not needed. */
        !          8638:            emit_move_insn (flag, const0_rtx);
        !          8639:            emit_insns (seq1);
        !          8640: 
        !          8641:            /* Flag cleanups as needed. */
        !          8642:            emit_move_insn (flag, const1_rtx);
        !          8643:            emit_insns (seq2);
        !          8644: 
        !          8645:            /* convert flag, which is an rtx, into a tree. */
        !          8646:            cond = make_node (RTL_EXPR);
        !          8647:            TREE_TYPE (cond) = integer_type_node;
        !          8648:            RTL_EXPR_RTL (cond) = flag;
        !          8649:            RTL_EXPR_SEQUENCE (cond) = NULL_RTX;
        !          8650: 
        !          8651:            new_cleanups = build (COND_EXPR, void_type_node,
        !          8652:                                  truthvalue_conversion (cond),
        !          8653:                                  cleanups, integer_zero_node);
        !          8654:            new_cleanups = fold (new_cleanups);
        !          8655: 
        !          8656:            /* Now add in the conditionalized cleanups. */
        !          8657:            cleanups_this_call
        !          8658:              = tree_cons (NULL_TREE, new_cleanups, cleanups_this_call);
        !          8659:            (*interim_eh_hook) (NULL_TREE);
        !          8660:          }
        !          8661:        else
        !          8662:          {
        !          8663:            emit_insns (seq1);
        !          8664:            emit_insns (seq2);
        !          8665:          }
        !          8666:       }
1.1.1.6   root     8667:       break;
1.1.1.5   root     8668: 
1.1.1.6   root     8669:     case TRUTH_ORIF_EXPR:
1.1.1.7 ! root     8670:       {
        !          8671:        rtx seq1, seq2;
        !          8672:        tree cleanups, old_cleanups;
        !          8673: 
        !          8674:        if (if_true_label == 0)
        !          8675:          if_true_label = drop_through_label = gen_label_rtx ();
        !          8676:        start_sequence ();
        !          8677:        do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
        !          8678:        seq1 = get_insns ();
        !          8679:        end_sequence ();
        !          8680: 
        !          8681:        old_cleanups = cleanups_this_call;
        !          8682:        start_sequence ();
        !          8683:        do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
        !          8684:        seq2 = get_insns ();
        !          8685:        end_sequence ();
        !          8686: 
        !          8687:        cleanups = defer_cleanups_to (old_cleanups);
        !          8688:        if (cleanups)
        !          8689:          {
        !          8690:            rtx flag = gen_reg_rtx (word_mode);
        !          8691:            tree new_cleanups;
        !          8692:            tree cond;
        !          8693: 
        !          8694:            /* Flag cleanups as not needed. */
        !          8695:            emit_move_insn (flag, const0_rtx);
        !          8696:            emit_insns (seq1);
        !          8697: 
        !          8698:            /* Flag cleanups as needed. */
        !          8699:            emit_move_insn (flag, const1_rtx);
        !          8700:            emit_insns (seq2);
        !          8701: 
        !          8702:            /* convert flag, which is an rtx, into a tree. */
        !          8703:            cond = make_node (RTL_EXPR);
        !          8704:            TREE_TYPE (cond) = integer_type_node;
        !          8705:            RTL_EXPR_RTL (cond) = flag;
        !          8706:            RTL_EXPR_SEQUENCE (cond) = NULL_RTX;
        !          8707: 
        !          8708:            new_cleanups = build (COND_EXPR, void_type_node,
        !          8709:                                  truthvalue_conversion (cond),
        !          8710:                                  cleanups, integer_zero_node);
        !          8711:            new_cleanups = fold (new_cleanups);
        !          8712: 
        !          8713:            /* Now add in the conditionalized cleanups. */
        !          8714:            cleanups_this_call
        !          8715:              = tree_cons (NULL_TREE, new_cleanups, cleanups_this_call);
        !          8716:            (*interim_eh_hook) (NULL_TREE);
        !          8717:          }
        !          8718:        else
        !          8719:          {
        !          8720:            emit_insns (seq1);
        !          8721:            emit_insns (seq2);
        !          8722:          }
        !          8723:       }
1.1.1.6   root     8724:       break;
1.1.1.5   root     8725: 
1.1.1.6   root     8726:     case COMPOUND_EXPR:
                   8727:       push_temp_slots ();
                   8728:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
                   8729:       free_temp_slots ();
                   8730:       pop_temp_slots ();
                   8731:       emit_queue ();
                   8732:       do_pending_stack_adjust ();
                   8733:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   8734:       break;
1.1.1.5   root     8735: 
1.1.1.6   root     8736:     case COMPONENT_REF:
                   8737:     case BIT_FIELD_REF:
                   8738:     case ARRAY_REF:
                   8739:       {
                   8740:        int bitsize, bitpos, unsignedp;
                   8741:        enum machine_mode mode;
                   8742:        tree type;
                   8743:        tree offset;
                   8744:        int volatilep = 0;
1.1.1.5   root     8745: 
1.1.1.6   root     8746:        /* Get description of this reference.  We don't actually care
                   8747:           about the underlying object here.  */
                   8748:        get_inner_reference (exp, &bitsize, &bitpos, &offset,
                   8749:                             &mode, &unsignedp, &volatilep);
                   8750: 
                   8751:        type = type_for_size (bitsize, unsignedp);
                   8752:        if (! SLOW_BYTE_ACCESS
                   8753:            && type != 0 && bitsize >= 0
                   8754:            && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
                   8755:            && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
                   8756:                != CODE_FOR_nothing))
1.1.1.5   root     8757:          {
1.1.1.6   root     8758:            do_jump (convert (type, exp), if_false_label, if_true_label);
                   8759:            break;
                   8760:          }
                   8761:        goto normal;
                   8762:       }
1.1.1.5   root     8763: 
1.1.1.6   root     8764:     case COND_EXPR:
                   8765:       /* Do (a ? 1 : 0) and (a ? 0 : 1) as special cases.  */
                   8766:       if (integer_onep (TREE_OPERAND (exp, 1))
                   8767:          && integer_zerop (TREE_OPERAND (exp, 2)))
                   8768:        do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
1.1.1.5   root     8769: 
1.1.1.6   root     8770:       else if (integer_zerop (TREE_OPERAND (exp, 1))
                   8771:               && integer_onep (TREE_OPERAND (exp, 2)))
                   8772:        do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
1.1.1.5   root     8773: 
1.1.1.6   root     8774:       else
                   8775:        {
                   8776:          register rtx label1 = gen_label_rtx ();
                   8777:          drop_through_label = gen_label_rtx ();
                   8778:          do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
                   8779:          /* Now the THEN-expression.  */
                   8780:          do_jump (TREE_OPERAND (exp, 1),
                   8781:                   if_false_label ? if_false_label : drop_through_label,
                   8782:                   if_true_label ? if_true_label : drop_through_label);
                   8783:          /* In case the do_jump just above never jumps.  */
                   8784:          do_pending_stack_adjust ();
                   8785:          emit_label (label1);
                   8786:          /* Now the ELSE-expression.  */
                   8787:          do_jump (TREE_OPERAND (exp, 2),
                   8788:                   if_false_label ? if_false_label : drop_through_label,
                   8789:                   if_true_label ? if_true_label : drop_through_label);
                   8790:        }
                   8791:       break;
1.1.1.5   root     8792: 
1.1.1.6   root     8793:     case EQ_EXPR:
                   8794:       if (integer_zerop (TREE_OPERAND (exp, 1)))
                   8795:        do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
                   8796:       else if (((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   8797:                 == MODE_INT)
                   8798:                && 
                   8799:                !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   8800:               || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_FLOAT
                   8801:               || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_INT)
                   8802:        do_jump_by_parts_equality (exp, if_false_label, if_true_label);
                   8803:       else
                   8804:        comparison = compare (exp, EQ, EQ);
                   8805:       break;
1.1.1.5   root     8806: 
1.1.1.6   root     8807:     case NE_EXPR:
                   8808:       if (integer_zerop (TREE_OPERAND (exp, 1)))
                   8809:        do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
                   8810:       else if (((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   8811:                 == MODE_INT)
                   8812:                && 
                   8813:                !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   8814:               || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_FLOAT
                   8815:               || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_INT)
                   8816:        do_jump_by_parts_equality (exp, if_true_label, if_false_label);
                   8817:       else
                   8818:        comparison = compare (exp, NE, NE);
                   8819:       break;
1.1.1.5   root     8820: 
1.1.1.6   root     8821:     case LT_EXPR:
                   8822:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   8823:           == MODE_INT)
                   8824:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   8825:        do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
                   8826:       else
                   8827:        comparison = compare (exp, LT, LTU);
                   8828:       break;
1.1.1.5   root     8829: 
1.1.1.6   root     8830:     case LE_EXPR:
                   8831:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   8832:           == MODE_INT)
                   8833:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   8834:        do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
                   8835:       else
                   8836:        comparison = compare (exp, LE, LEU);
                   8837:       break;
1.1.1.5   root     8838: 
1.1.1.6   root     8839:     case GT_EXPR:
                   8840:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   8841:           == MODE_INT)
                   8842:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   8843:        do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
                   8844:       else
                   8845:        comparison = compare (exp, GT, GTU);
                   8846:       break;
1.1.1.5   root     8847: 
1.1.1.6   root     8848:     case GE_EXPR:
                   8849:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   8850:           == MODE_INT)
                   8851:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   8852:        do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
                   8853:       else
                   8854:        comparison = compare (exp, GE, GEU);
                   8855:       break;
1.1.1.5   root     8856: 
1.1.1.6   root     8857:     default:
                   8858:     normal:
                   8859:       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
                   8860: #if 0
                   8861:       /* This is not needed any more and causes poor code since it causes
                   8862:         comparisons and tests from non-SI objects to have different code
                   8863:         sequences.  */
                   8864:       /* Copy to register to avoid generating bad insns by cse
                   8865:         from (set (mem ...) (arithop))  (set (cc0) (mem ...)).  */
                   8866:       if (!cse_not_expected && GET_CODE (temp) == MEM)
                   8867:        temp = copy_to_reg (temp);
                   8868: #endif
                   8869:       do_pending_stack_adjust ();
                   8870:       if (GET_CODE (temp) == CONST_INT)
                   8871:        comparison = (temp == const0_rtx ? const0_rtx : const_true_rtx);
                   8872:       else if (GET_CODE (temp) == LABEL_REF)
                   8873:        comparison = const_true_rtx;
                   8874:       else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
                   8875:               && !can_compare_p (GET_MODE (temp)))
                   8876:        /* Note swapping the labels gives us not-equal.  */
                   8877:        do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
                   8878:       else if (GET_MODE (temp) != VOIDmode)
                   8879:        comparison = compare_from_rtx (temp, CONST0_RTX (GET_MODE (temp)),
                   8880:                                       NE, TREE_UNSIGNED (TREE_TYPE (exp)),
                   8881:                                       GET_MODE (temp), NULL_RTX, 0);
                   8882:       else
                   8883:        abort ();
                   8884:     }
1.1.1.5   root     8885: 
1.1.1.6   root     8886:   /* Do any postincrements in the expression that was tested.  */
                   8887:   emit_queue ();
1.1.1.5   root     8888: 
1.1.1.6   root     8889:   /* If COMPARISON is nonzero here, it is an rtx that can be substituted
                   8890:      straight into a conditional jump instruction as the jump condition.
                   8891:      Otherwise, all the work has been done already.  */
1.1.1.5   root     8892: 
1.1.1.6   root     8893:   if (comparison == const_true_rtx)
1.1.1.5   root     8894:     {
1.1.1.6   root     8895:       if (if_true_label)
                   8896:        emit_jump (if_true_label);
1.1.1.5   root     8897:     }
1.1.1.6   root     8898:   else if (comparison == const0_rtx)
                   8899:     {
                   8900:       if (if_false_label)
                   8901:        emit_jump (if_false_label);
                   8902:     }
                   8903:   else if (comparison)
                   8904:     do_jump_for_compare (comparison, if_false_label, if_true_label);
1.1.1.5   root     8905: 
1.1.1.6   root     8906:   if (drop_through_label)
                   8907:     {
                   8908:       /* If do_jump produces code that might be jumped around,
                   8909:         do any stack adjusts from that code, before the place
                   8910:         where control merges in.  */
                   8911:       do_pending_stack_adjust ();
                   8912:       emit_label (drop_through_label);
                   8913:     }
1.1.1.5   root     8914: }
1.1.1.6   root     8915: 
                   8916: /* Given a comparison expression EXP for values too wide to be compared
                   8917:    with one insn, test the comparison and jump to the appropriate label.
                   8918:    The code of EXP is ignored; we always test GT if SWAP is 0,
                   8919:    and LT if SWAP is 1.  */
1.1.1.5   root     8920: 
1.1.1.6   root     8921: static void
                   8922: do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label)
                   8923:      tree exp;
                   8924:      int swap;
                   8925:      rtx if_false_label, if_true_label;
1.1.1.5   root     8926: {
1.1.1.6   root     8927:   rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0);
                   8928:   rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0);
                   8929:   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   8930:   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
                   8931:   rtx drop_through_label = 0;
                   8932:   int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   8933:   int i;
1.1.1.5   root     8934: 
1.1.1.6   root     8935:   if (! if_true_label || ! if_false_label)
                   8936:     drop_through_label = gen_label_rtx ();
                   8937:   if (! if_true_label)
                   8938:     if_true_label = drop_through_label;
                   8939:   if (! if_false_label)
                   8940:     if_false_label = drop_through_label;
1.1.1.5   root     8941: 
1.1.1.6   root     8942:   /* Compare a word at a time, high order first.  */
                   8943:   for (i = 0; i < nwords; i++)
                   8944:     {
                   8945:       rtx comp;
                   8946:       rtx op0_word, op1_word;
1.1.1.5   root     8947: 
1.1.1.6   root     8948:       if (WORDS_BIG_ENDIAN)
                   8949:        {
                   8950:          op0_word = operand_subword_force (op0, i, mode);
                   8951:          op1_word = operand_subword_force (op1, i, mode);
                   8952:        }
                   8953:       else
                   8954:        {
                   8955:          op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
                   8956:          op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
                   8957:        }
1.1.1.5   root     8958: 
1.1.1.6   root     8959:       /* All but high-order word must be compared as unsigned.  */
                   8960:       comp = compare_from_rtx (op0_word, op1_word,
                   8961:                               (unsignedp || i > 0) ? GTU : GT,
                   8962:                               unsignedp, word_mode, NULL_RTX, 0);
                   8963:       if (comp == const_true_rtx)
                   8964:        emit_jump (if_true_label);
                   8965:       else if (comp != const0_rtx)
                   8966:        do_jump_for_compare (comp, NULL_RTX, if_true_label);
1.1.1.5   root     8967: 
1.1.1.6   root     8968:       /* Consider lower words only if these are equal.  */
                   8969:       comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode,
                   8970:                               NULL_RTX, 0);
                   8971:       if (comp == const_true_rtx)
                   8972:        emit_jump (if_false_label);
                   8973:       else if (comp != const0_rtx)
                   8974:        do_jump_for_compare (comp, NULL_RTX, if_false_label);
                   8975:     }
1.1.1.5   root     8976: 
1.1.1.6   root     8977:   if (if_false_label)
                   8978:     emit_jump (if_false_label);
                   8979:   if (drop_through_label)
                   8980:     emit_label (drop_through_label);
                   8981: }
1.1.1.5   root     8982: 
1.1.1.6   root     8983: /* Compare OP0 with OP1, word at a time, in mode MODE.
                   8984:    UNSIGNEDP says to do unsigned comparison.
                   8985:    Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise.  */
1.1.1.5   root     8986: 
1.1.1.7 ! root     8987: void
1.1.1.6   root     8988: do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true_label)
                   8989:      enum machine_mode mode;
                   8990:      int unsignedp;
                   8991:      rtx op0, op1;
                   8992:      rtx if_false_label, if_true_label;
                   8993: {
                   8994:   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
                   8995:   rtx drop_through_label = 0;
                   8996:   int i;
1.1.1.5   root     8997: 
1.1.1.6   root     8998:   if (! if_true_label || ! if_false_label)
                   8999:     drop_through_label = gen_label_rtx ();
                   9000:   if (! if_true_label)
                   9001:     if_true_label = drop_through_label;
                   9002:   if (! if_false_label)
                   9003:     if_false_label = drop_through_label;
1.1.1.5   root     9004: 
1.1.1.6   root     9005:   /* Compare a word at a time, high order first.  */
                   9006:   for (i = 0; i < nwords; i++)
1.1.1.5   root     9007:     {
1.1.1.6   root     9008:       rtx comp;
                   9009:       rtx op0_word, op1_word;
                   9010: 
                   9011:       if (WORDS_BIG_ENDIAN)
1.1.1.5   root     9012:        {
1.1.1.6   root     9013:          op0_word = operand_subword_force (op0, i, mode);
                   9014:          op1_word = operand_subword_force (op1, i, mode);
                   9015:        }
                   9016:       else
                   9017:        {
                   9018:          op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
                   9019:          op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
1.1.1.5   root     9020:        }
                   9021: 
1.1.1.6   root     9022:       /* All but high-order word must be compared as unsigned.  */
                   9023:       comp = compare_from_rtx (op0_word, op1_word,
                   9024:                               (unsignedp || i > 0) ? GTU : GT,
                   9025:                               unsignedp, word_mode, NULL_RTX, 0);
                   9026:       if (comp == const_true_rtx)
                   9027:        emit_jump (if_true_label);
                   9028:       else if (comp != const0_rtx)
                   9029:        do_jump_for_compare (comp, NULL_RTX, if_true_label);
1.1.1.5   root     9030: 
1.1.1.6   root     9031:       /* Consider lower words only if these are equal.  */
                   9032:       comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode,
                   9033:                               NULL_RTX, 0);
                   9034:       if (comp == const_true_rtx)
                   9035:        emit_jump (if_false_label);
                   9036:       else if (comp != const0_rtx)
                   9037:        do_jump_for_compare (comp, NULL_RTX, if_false_label);
                   9038:     }
1.1.1.5   root     9039: 
1.1.1.6   root     9040:   if (if_false_label)
                   9041:     emit_jump (if_false_label);
                   9042:   if (drop_through_label)
                   9043:     emit_label (drop_through_label);
                   9044: }
1.1.1.5   root     9045: 
1.1.1.6   root     9046: /* Given an EQ_EXPR expression EXP for values too wide to be compared
                   9047:    with one insn, test the comparison and jump to the appropriate label.  */
1.1.1.5   root     9048: 
1.1.1.6   root     9049: static void
                   9050: do_jump_by_parts_equality (exp, if_false_label, if_true_label)
                   9051:      tree exp;
                   9052:      rtx if_false_label, if_true_label;
                   9053: {
                   9054:   rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
                   9055:   rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
                   9056:   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   9057:   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
                   9058:   int i;
                   9059:   rtx drop_through_label = 0;
1.1.1.5   root     9060: 
1.1.1.6   root     9061:   if (! if_false_label)
                   9062:     drop_through_label = if_false_label = gen_label_rtx ();
                   9063: 
                   9064:   for (i = 0; i < nwords; i++)
                   9065:     {
                   9066:       rtx comp = compare_from_rtx (operand_subword_force (op0, i, mode),
                   9067:                                   operand_subword_force (op1, i, mode),
                   9068:                                   EQ, TREE_UNSIGNED (TREE_TYPE (exp)),
                   9069:                                   word_mode, NULL_RTX, 0);
                   9070:       if (comp == const_true_rtx)
                   9071:        emit_jump (if_false_label);
                   9072:       else if (comp != const0_rtx)
                   9073:        do_jump_for_compare (comp, if_false_label, NULL_RTX);
1.1.1.5   root     9074:     }
                   9075: 
1.1.1.6   root     9076:   if (if_true_label)
                   9077:     emit_jump (if_true_label);
                   9078:   if (drop_through_label)
                   9079:     emit_label (drop_through_label);
                   9080: }
                   9081: 
                   9082: /* Jump according to whether OP0 is 0.
                   9083:    We assume that OP0 has an integer mode that is too wide
                   9084:    for the available compare insns.  */
1.1.1.5   root     9085: 
1.1.1.6   root     9086: static void
                   9087: do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
                   9088:      rtx op0;
                   9089:      rtx if_false_label, if_true_label;
                   9090: {
                   9091:   int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD;
                   9092:   int i;
                   9093:   rtx drop_through_label = 0;
1.1.1.5   root     9094: 
1.1.1.6   root     9095:   if (! if_false_label)
                   9096:     drop_through_label = if_false_label = gen_label_rtx ();
1.1.1.5   root     9097: 
1.1.1.6   root     9098:   for (i = 0; i < nwords; i++)
                   9099:     {
                   9100:       rtx comp = compare_from_rtx (operand_subword_force (op0, i,
                   9101:                                                          GET_MODE (op0)),
                   9102:                                   const0_rtx, EQ, 1, word_mode, NULL_RTX, 0);
                   9103:       if (comp == const_true_rtx)
                   9104:        emit_jump (if_false_label);
                   9105:       else if (comp != const0_rtx)
                   9106:        do_jump_for_compare (comp, if_false_label, NULL_RTX);
                   9107:     }
1.1.1.5   root     9108: 
1.1.1.6   root     9109:   if (if_true_label)
                   9110:     emit_jump (if_true_label);
                   9111:   if (drop_through_label)
                   9112:     emit_label (drop_through_label);
1.1.1.5   root     9113: }
                   9114: 
1.1.1.6   root     9115: /* Given a comparison expression in rtl form, output conditional branches to
                   9116:    IF_TRUE_LABEL, IF_FALSE_LABEL, or both.  */
                   9117: 
1.1.1.5   root     9118: static void
1.1.1.6   root     9119: do_jump_for_compare (comparison, if_false_label, if_true_label)
                   9120:      rtx comparison, if_false_label, if_true_label;
1.1.1.5   root     9121: {
1.1.1.6   root     9122:   if (if_true_label)
1.1.1.5   root     9123:     {
1.1.1.6   root     9124:       if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
                   9125:        emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_true_label));
                   9126:       else
                   9127:        abort ();
                   9128: 
                   9129:       if (if_false_label)
                   9130:        emit_jump (if_false_label);
1.1.1.5   root     9131:     }
1.1.1.6   root     9132:   else if (if_false_label)
                   9133:     {
                   9134:       rtx insn;
                   9135:       rtx prev = get_last_insn ();
                   9136:       rtx branch = 0;
1.1.1.5   root     9137: 
1.1.1.6   root     9138:       /* Output the branch with the opposite condition.  Then try to invert
                   9139:         what is generated.  If more than one insn is a branch, or if the
                   9140:         branch is not the last insn written, abort. If we can't invert
                   9141:         the branch, emit make a true label, redirect this jump to that,
                   9142:         emit a jump to the false label and define the true label.  */
1.1.1.5   root     9143: 
1.1.1.6   root     9144:       if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
1.1.1.7 ! root     9145:        emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)])(if_false_label));
1.1.1.6   root     9146:       else
                   9147:        abort ();
1.1.1.5   root     9148: 
1.1.1.7 ! root     9149:       /* Here we get the first insn that was just emitted.  It used to be  the
        !          9150:         case that, on some machines, emitting the branch would discard
        !          9151:         the previous compare insn and emit a replacement.  This isn't
        !          9152:         done anymore, but abort if we see that PREV is deleted.  */
        !          9153: 
1.1.1.6   root     9154:       if (prev == 0)
                   9155:        insn = get_insns ();
1.1.1.7 ! root     9156:       else if (INSN_DELETED_P (prev))
        !          9157:        abort ();
1.1.1.6   root     9158:       else
                   9159:        insn = NEXT_INSN (prev);
                   9160: 
1.1.1.7 ! root     9161:       for (; insn; insn = NEXT_INSN (insn))
1.1.1.6   root     9162:        if (GET_CODE (insn) == JUMP_INSN)
                   9163:          {
                   9164:            if (branch)
                   9165:              abort ();
                   9166:            branch = insn;
                   9167:          }
                   9168: 
                   9169:       if (branch != get_last_insn ())
                   9170:        abort ();
                   9171: 
1.1.1.7 ! root     9172:       JUMP_LABEL (branch) = if_false_label;
1.1.1.6   root     9173:       if (! invert_jump (branch, if_false_label))
                   9174:        {
                   9175:          if_true_label = gen_label_rtx ();
                   9176:          redirect_jump (branch, if_true_label);
                   9177:          emit_jump (if_false_label);
                   9178:          emit_label (if_true_label);
                   9179:        }
                   9180:     }
1.1.1.5   root     9181: }
                   9182: 
1.1.1.6   root     9183: /* Generate code for a comparison expression EXP
                   9184:    (including code to compute the values to be compared)
                   9185:    and set (CC0) according to the result.
                   9186:    SIGNED_CODE should be the rtx operation for this comparison for
                   9187:    signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
                   9188: 
                   9189:    We force a stack adjustment unless there are currently
                   9190:    things pushed on the stack that aren't yet used.  */
1.1       root     9191: 
                   9192: static rtx
1.1.1.6   root     9193: compare (exp, signed_code, unsigned_code)
1.1       root     9194:      register tree exp;
1.1.1.6   root     9195:      enum rtx_code signed_code, unsigned_code;
1.1       root     9196: {
1.1.1.6   root     9197:   register rtx op0
                   9198:     = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
                   9199:   register rtx op1
                   9200:     = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
                   9201:   register tree type = TREE_TYPE (TREE_OPERAND (exp, 0));
                   9202:   register enum machine_mode mode = TYPE_MODE (type);
                   9203:   int unsignedp = TREE_UNSIGNED (type);
                   9204:   enum rtx_code code = unsignedp ? unsigned_code : signed_code;
1.1.1.4   root     9205: 
1.1.1.6   root     9206:   return compare_from_rtx (op0, op1, code, unsignedp, mode,
                   9207:                           ((mode == BLKmode)
                   9208:                            ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
                   9209:                           TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   9210: }
1.1.1.4   root     9211: 
1.1.1.6   root     9212: /* Like compare but expects the values to compare as two rtx's.
                   9213:    The decision as to signed or unsigned comparison must be made by the caller.
1.1.1.4   root     9214: 
1.1.1.6   root     9215:    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
                   9216:    compared.
1.1.1.4   root     9217: 
1.1.1.6   root     9218:    If ALIGN is non-zero, it is the alignment of this type; if zero, the
                   9219:    size of MODE should be used.  */
1.1.1.4   root     9220: 
1.1.1.6   root     9221: rtx
                   9222: compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
                   9223:      register rtx op0, op1;
                   9224:      enum rtx_code code;
                   9225:      int unsignedp;
                   9226:      enum machine_mode mode;
                   9227:      rtx size;
                   9228:      int align;
                   9229: {
                   9230:   rtx tem;
1.1       root     9231: 
1.1.1.6   root     9232:   /* If one operand is constant, make it the second one.  Only do this
                   9233:      if the other operand is not constant as well.  */
1.1       root     9234: 
1.1.1.6   root     9235:   if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
                   9236:       || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
1.1       root     9237:     {
1.1.1.6   root     9238:       tem = op0;
                   9239:       op0 = op1;
                   9240:       op1 = tem;
                   9241:       code = swap_condition (code);
1.1       root     9242:     }
                   9243: 
1.1.1.6   root     9244:   if (flag_force_mem)
1.1       root     9245:     {
1.1.1.6   root     9246:       op0 = force_not_mem (op0);
                   9247:       op1 = force_not_mem (op1);
1.1       root     9248:     }
                   9249: 
1.1.1.6   root     9250:   do_pending_stack_adjust ();
1.1       root     9251: 
1.1.1.6   root     9252:   if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT
                   9253:       && (tem = simplify_relational_operation (code, mode, op0, op1)) != 0)
                   9254:     return tem;
1.1       root     9255: 
1.1.1.6   root     9256: #if 0
                   9257:   /* There's no need to do this now that combine.c can eliminate lots of
                   9258:      sign extensions.  This can be less efficient in certain cases on other
                   9259:      machines. */
1.1       root     9260: 
1.1.1.6   root     9261:   /* If this is a signed equality comparison, we can do it as an
                   9262:      unsigned comparison since zero-extension is cheaper than sign
                   9263:      extension and comparisons with zero are done as unsigned.  This is
                   9264:      the case even on machines that can do fast sign extension, since
                   9265:      zero-extension is easier to combine with other operations than
                   9266:      sign-extension is.  If we are comparing against a constant, we must
                   9267:      convert it to what it would look like unsigned.  */
                   9268:   if ((code == EQ || code == NE) && ! unsignedp
                   9269:       && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
                   9270:     {
                   9271:       if (GET_CODE (op1) == CONST_INT
                   9272:          && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
                   9273:        op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
                   9274:       unsignedp = 1;
1.1       root     9275:     }
1.1.1.6   root     9276: #endif
                   9277:        
                   9278:   emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align);
1.1       root     9279: 
1.1.1.6   root     9280:   return gen_rtx (code, VOIDmode, cc0_rtx, const0_rtx);
1.1       root     9281: }
                   9282: 
1.1.1.6   root     9283: /* Generate code to calculate EXP using a store-flag instruction
                   9284:    and return an rtx for the result.  EXP is either a comparison
                   9285:    or a TRUTH_NOT_EXPR whose operand is a comparison.
1.1       root     9286: 
1.1.1.6   root     9287:    If TARGET is nonzero, store the result there if convenient.
1.1       root     9288: 
1.1.1.6   root     9289:    If ONLY_CHEAP is non-zero, only do this if it is likely to be very
                   9290:    cheap.
1.1       root     9291: 
1.1.1.6   root     9292:    Return zero if there is no suitable set-flag instruction
                   9293:    available on this machine.
1.1       root     9294: 
1.1.1.6   root     9295:    Once expand_expr has been called on the arguments of the comparison,
                   9296:    we are committed to doing the store flag, since it is not safe to
                   9297:    re-evaluate the expression.  We emit the store-flag insn by calling
                   9298:    emit_store_flag, but only expand the arguments if we have a reason
                   9299:    to believe that emit_store_flag will be successful.  If we think that
                   9300:    it will, but it isn't, we have to simulate the store-flag with a
                   9301:    set/jump/set sequence.  */
1.1       root     9302: 
1.1.1.6   root     9303: static rtx
                   9304: do_store_flag (exp, target, mode, only_cheap)
                   9305:      tree exp;
                   9306:      rtx target;
                   9307:      enum machine_mode mode;
                   9308:      int only_cheap;
                   9309: {
                   9310:   enum rtx_code code;
                   9311:   tree arg0, arg1, type;
                   9312:   tree tem;
                   9313:   enum machine_mode operand_mode;
                   9314:   int invert = 0;
                   9315:   int unsignedp;
                   9316:   rtx op0, op1;
                   9317:   enum insn_code icode;
                   9318:   rtx subtarget = target;
                   9319:   rtx result, label, pattern, jump_pat;
1.1       root     9320: 
1.1.1.6   root     9321:   /* If this is a TRUTH_NOT_EXPR, set a flag indicating we must invert the
                   9322:      result at the end.  We can't simply invert the test since it would
                   9323:      have already been inverted if it were valid.  This case occurs for
                   9324:      some floating-point comparisons.  */
1.1       root     9325: 
1.1.1.6   root     9326:   if (TREE_CODE (exp) == TRUTH_NOT_EXPR)
                   9327:     invert = 1, exp = TREE_OPERAND (exp, 0);
1.1       root     9328: 
1.1.1.6   root     9329:   arg0 = TREE_OPERAND (exp, 0);
                   9330:   arg1 = TREE_OPERAND (exp, 1);
                   9331:   type = TREE_TYPE (arg0);
                   9332:   operand_mode = TYPE_MODE (type);
                   9333:   unsignedp = TREE_UNSIGNED (type);
1.1       root     9334: 
1.1.1.6   root     9335:   /* We won't bother with BLKmode store-flag operations because it would mean
                   9336:      passing a lot of information to emit_store_flag.  */
                   9337:   if (operand_mode == BLKmode)
                   9338:     return 0;
1.1       root     9339: 
1.1.1.6   root     9340:   STRIP_NOPS (arg0);
                   9341:   STRIP_NOPS (arg1);
1.1       root     9342: 
1.1.1.6   root     9343:   /* Get the rtx comparison code to use.  We know that EXP is a comparison
                   9344:      operation of some type.  Some comparisons against 1 and -1 can be
                   9345:      converted to comparisons with zero.  Do so here so that the tests
                   9346:      below will be aware that we have a comparison with zero.   These
                   9347:      tests will not catch constants in the first operand, but constants
                   9348:      are rarely passed as the first operand.  */
1.1       root     9349: 
1.1.1.6   root     9350:   switch (TREE_CODE (exp))
1.1       root     9351:     {
1.1.1.6   root     9352:     case EQ_EXPR:
                   9353:       code = EQ;
                   9354:       break;
                   9355:     case NE_EXPR:
                   9356:       code = NE;
                   9357:       break;
                   9358:     case LT_EXPR:
                   9359:       if (integer_onep (arg1))
                   9360:        arg1 = integer_zero_node, code = unsignedp ? LEU : LE;
                   9361:       else
                   9362:        code = unsignedp ? LTU : LT;
                   9363:       break;
                   9364:     case LE_EXPR:
                   9365:       if (! unsignedp && integer_all_onesp (arg1))
                   9366:        arg1 = integer_zero_node, code = LT;
                   9367:       else
                   9368:        code = unsignedp ? LEU : LE;
                   9369:       break;
                   9370:     case GT_EXPR:
                   9371:       if (! unsignedp && integer_all_onesp (arg1))
                   9372:        arg1 = integer_zero_node, code = GE;
                   9373:       else
                   9374:        code = unsignedp ? GTU : GT;
                   9375:       break;
                   9376:     case GE_EXPR:
                   9377:       if (integer_onep (arg1))
                   9378:        arg1 = integer_zero_node, code = unsignedp ? GTU : GT;
                   9379:       else
                   9380:        code = unsignedp ? GEU : GE;
                   9381:       break;
                   9382:     default:
                   9383:       abort ();
1.1       root     9384:     }
                   9385: 
1.1.1.6   root     9386:   /* Put a constant second.  */
                   9387:   if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST)
1.1       root     9388:     {
1.1.1.6   root     9389:       tem = arg0; arg0 = arg1; arg1 = tem;
                   9390:       code = swap_condition (code);
1.1       root     9391:     }
                   9392: 
1.1.1.6   root     9393:   /* If this is an equality or inequality test of a single bit, we can
                   9394:      do this by shifting the bit being tested to the low-order bit and
                   9395:      masking the result with the constant 1.  If the condition was EQ,
                   9396:      we xor it with 1.  This does not require an scc insn and is faster
                   9397:      than an scc insn even if we have it.  */
1.1       root     9398: 
1.1.1.6   root     9399:   if ((code == NE || code == EQ)
                   9400:       && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
                   9401:       && integer_pow2p (TREE_OPERAND (arg0, 1))
                   9402:       && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT)
                   9403:     {
                   9404:       tree inner = TREE_OPERAND (arg0, 0);
                   9405:       int bitnum = exact_log2 (INTVAL (expand_expr (TREE_OPERAND (arg0, 1),
                   9406:                                                    NULL_RTX, VOIDmode, 0)));
                   9407:       int ops_unsignedp;
1.1       root     9408: 
1.1.1.6   root     9409:       /* If INNER is a right shift of a constant and it plus BITNUM does
                   9410:         not overflow, adjust BITNUM and INNER.  */
1.1       root     9411: 
1.1.1.6   root     9412:       if (TREE_CODE (inner) == RSHIFT_EXPR
                   9413:          && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST
                   9414:          && TREE_INT_CST_HIGH (TREE_OPERAND (inner, 1)) == 0
                   9415:          && (bitnum + TREE_INT_CST_LOW (TREE_OPERAND (inner, 1))
                   9416:              < TYPE_PRECISION (type)))
                   9417:        {
                   9418:          bitnum +=TREE_INT_CST_LOW (TREE_OPERAND (inner, 1));
                   9419:          inner = TREE_OPERAND (inner, 0);
                   9420:        }
                   9421: 
                   9422:       /* If we are going to be able to omit the AND below, we must do our
                   9423:         operations as unsigned.  If we must use the AND, we have a choice.
                   9424:         Normally unsigned is faster, but for some machines signed is.  */
                   9425:       ops_unsignedp = (bitnum == TYPE_PRECISION (type) - 1 ? 1
                   9426: #ifdef LOAD_EXTEND_OP
                   9427:                       : (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1)
                   9428: #else
                   9429:                       : 1
                   9430: #endif
                   9431:                       );
1.1       root     9432: 
1.1.1.6   root     9433:       if (subtarget == 0 || GET_CODE (subtarget) != REG
                   9434:          || GET_MODE (subtarget) != operand_mode
                   9435:          || ! safe_from_p (subtarget, inner))
                   9436:        subtarget = 0;
1.1       root     9437: 
1.1.1.6   root     9438:       op0 = expand_expr (inner, subtarget, VOIDmode, 0);
1.1.1.3   root     9439: 
1.1.1.6   root     9440:       if (bitnum != 0)
                   9441:        op0 = expand_shift (RSHIFT_EXPR, GET_MODE (op0), op0,
                   9442:                            size_int (bitnum), subtarget, ops_unsignedp);
1.1       root     9443: 
1.1.1.6   root     9444:       if (GET_MODE (op0) != mode)
                   9445:        op0 = convert_to_mode (mode, op0, ops_unsignedp);
1.1       root     9446: 
1.1.1.6   root     9447:       if ((code == EQ && ! invert) || (code == NE && invert))
                   9448:        op0 = expand_binop (mode, xor_optab, op0, const1_rtx, subtarget,
                   9449:                            ops_unsignedp, OPTAB_LIB_WIDEN);
1.1       root     9450: 
1.1.1.6   root     9451:       /* Put the AND last so it can combine with more things.  */
                   9452:       if (bitnum != TYPE_PRECISION (type) - 1)
                   9453:        op0 = expand_and (op0, const1_rtx, subtarget);
                   9454: 
                   9455:       return op0;
                   9456:     }
                   9457: 
                   9458:   /* Now see if we are likely to be able to do this.  Return if not.  */
                   9459:   if (! can_compare_p (operand_mode))
                   9460:     return 0;
                   9461:   icode = setcc_gen_code[(int) code];
                   9462:   if (icode == CODE_FOR_nothing
                   9463:       || (only_cheap && insn_operand_mode[(int) icode][0] != mode))
1.1       root     9464:     {
1.1.1.6   root     9465:       /* We can only do this if it is one of the special cases that
                   9466:         can be handled without an scc insn.  */
                   9467:       if ((code == LT && integer_zerop (arg1))
                   9468:          || (! only_cheap && code == GE && integer_zerop (arg1)))
                   9469:        ;
                   9470:       else if (BRANCH_COST >= 0
                   9471:               && ! only_cheap && (code == NE || code == EQ)
                   9472:               && TREE_CODE (type) != REAL_TYPE
                   9473:               && ((abs_optab->handlers[(int) operand_mode].insn_code
                   9474:                    != CODE_FOR_nothing)
                   9475:                   || (ffs_optab->handlers[(int) operand_mode].insn_code
                   9476:                       != CODE_FOR_nothing)))
                   9477:        ;
                   9478:       else
                   9479:        return 0;
                   9480:     }
                   9481:       
                   9482:   preexpand_calls (exp);
                   9483:   if (subtarget == 0 || GET_CODE (subtarget) != REG
                   9484:       || GET_MODE (subtarget) != operand_mode
                   9485:       || ! safe_from_p (subtarget, arg1))
                   9486:     subtarget = 0;
1.1       root     9487: 
1.1.1.6   root     9488:   op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
                   9489:   op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
1.1       root     9490: 
1.1.1.6   root     9491:   if (target == 0)
                   9492:     target = gen_reg_rtx (mode);
1.1       root     9493: 
1.1.1.6   root     9494:   /* Pass copies of OP0 and OP1 in case they contain a QUEUED.  This is safe
                   9495:      because, if the emit_store_flag does anything it will succeed and
                   9496:      OP0 and OP1 will not be used subsequently.  */
1.1       root     9497: 
1.1.1.6   root     9498:   result = emit_store_flag (target, code,
                   9499:                            queued_subexp_p (op0) ? copy_rtx (op0) : op0,
                   9500:                            queued_subexp_p (op1) ? copy_rtx (op1) : op1,
                   9501:                            operand_mode, unsignedp, 1);
1.1       root     9502: 
1.1.1.6   root     9503:   if (result)
                   9504:     {
                   9505:       if (invert)
                   9506:        result = expand_binop (mode, xor_optab, result, const1_rtx,
                   9507:                               result, 0, OPTAB_LIB_WIDEN);
                   9508:       return result;
                   9509:     }
1.1       root     9510: 
1.1.1.6   root     9511:   /* If this failed, we have to do this with set/compare/jump/set code.  */
                   9512:   if (target == 0 || GET_CODE (target) != REG
                   9513:       || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
                   9514:     target = gen_reg_rtx (GET_MODE (target));
1.1       root     9515: 
1.1.1.6   root     9516:   emit_move_insn (target, invert ? const0_rtx : const1_rtx);
                   9517:   result = compare_from_rtx (op0, op1, code, unsignedp,
                   9518:                             operand_mode, NULL_RTX, 0);
                   9519:   if (GET_CODE (result) == CONST_INT)
                   9520:     return (((result == const0_rtx && ! invert)
                   9521:             || (result != const0_rtx && invert))
                   9522:            ? const0_rtx : const1_rtx);
1.1       root     9523: 
1.1.1.6   root     9524:   label = gen_label_rtx ();
                   9525:   if (bcc_gen_fctn[(int) code] == 0)
                   9526:     abort ();
1.1       root     9527: 
1.1.1.6   root     9528:   emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
                   9529:   emit_move_insn (target, invert ? const1_rtx : const0_rtx);
                   9530:   emit_label (label);
1.1       root     9531: 
1.1.1.6   root     9532:   return target;
                   9533: }
                   9534: 
                   9535: /* Generate a tablejump instruction (used for switch statements).  */
1.1       root     9536: 
1.1.1.6   root     9537: #ifdef HAVE_tablejump
1.1       root     9538: 
1.1.1.6   root     9539: /* INDEX is the value being switched on, with the lowest value
                   9540:    in the table already subtracted.
                   9541:    MODE is its expected mode (needed if INDEX is constant).
                   9542:    RANGE is the length of the jump table.
                   9543:    TABLE_LABEL is a CODE_LABEL rtx for the table itself.
1.1       root     9544: 
1.1.1.6   root     9545:    DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
                   9546:    index value is out of range.  */
1.1       root     9547: 
1.1.1.6   root     9548: void
                   9549: do_tablejump (index, mode, range, table_label, default_label)
                   9550:      rtx index, range, table_label, default_label;
                   9551:      enum machine_mode mode;
                   9552: {
                   9553:   register rtx temp, vector;
1.1       root     9554: 
1.1.1.6   root     9555:   /* Do an unsigned comparison (in the proper mode) between the index
                   9556:      expression and the value which represents the length of the range.
                   9557:      Since we just finished subtracting the lower bound of the range
                   9558:      from the index expression, this comparison allows us to simultaneously
                   9559:      check that the original index expression value is both greater than
                   9560:      or equal to the minimum value of the range and less than or equal to
                   9561:      the maximum value of the range.  */
1.1       root     9562: 
1.1.1.7 ! root     9563:   emit_cmp_insn (index, range, GTU, NULL_RTX, mode, 1, 0);
        !          9564:   emit_jump_insn (gen_bgtu (default_label));
1.1       root     9565: 
1.1.1.6   root     9566:   /* If index is in range, it must fit in Pmode.
                   9567:      Convert to Pmode so we can index with it.  */
                   9568:   if (mode != Pmode)
                   9569:     index = convert_to_mode (Pmode, index, 1);
1.1       root     9570: 
1.1.1.6   root     9571:   /* Don't let a MEM slip thru, because then INDEX that comes
                   9572:      out of PIC_CASE_VECTOR_ADDRESS won't be a valid address,
                   9573:      and break_out_memory_refs will go to work on it and mess it up.  */
                   9574: #ifdef PIC_CASE_VECTOR_ADDRESS
                   9575:   if (flag_pic && GET_CODE (index) != REG)
                   9576:     index = copy_to_mode_reg (Pmode, index);
                   9577: #endif
1.1       root     9578: 
1.1.1.6   root     9579:   /* If flag_force_addr were to affect this address
                   9580:      it could interfere with the tricky assumptions made
                   9581:      about addresses that contain label-refs,
                   9582:      which may be valid only very near the tablejump itself.  */
                   9583:   /* ??? The only correct use of CASE_VECTOR_MODE is the one inside the
                   9584:      GET_MODE_SIZE, because this indicates how large insns are.  The other
                   9585:      uses should all be Pmode, because they are addresses.  This code
                   9586:      could fail if addresses and insns are not the same size.  */
                   9587:   index = gen_rtx (PLUS, Pmode,
                   9588:                   gen_rtx (MULT, Pmode, index,
                   9589:                            GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))),
                   9590:                   gen_rtx (LABEL_REF, Pmode, table_label));
                   9591: #ifdef PIC_CASE_VECTOR_ADDRESS
                   9592:   if (flag_pic)
                   9593:     index = PIC_CASE_VECTOR_ADDRESS (index);
                   9594:   else
                   9595: #endif
                   9596:     index = memory_address_noforce (CASE_VECTOR_MODE, index);
                   9597:   temp = gen_reg_rtx (CASE_VECTOR_MODE);
                   9598:   vector = gen_rtx (MEM, CASE_VECTOR_MODE, index);
                   9599:   RTX_UNCHANGING_P (vector) = 1;
                   9600:   convert_move (temp, vector, 0);
1.1       root     9601: 
1.1.1.6   root     9602:   emit_jump_insn (gen_tablejump (temp, table_label));
1.1       root     9603: 
1.1.1.6   root     9604: #ifndef CASE_VECTOR_PC_RELATIVE
                   9605:   /* If we are generating PIC code or if the table is PC-relative, the
                   9606:      table and JUMP_INSN must be adjacent, so don't output a BARRIER.  */
                   9607:   if (! flag_pic)
                   9608:     emit_barrier ();
                   9609: #endif
                   9610: }
1.1       root     9611: 
1.1.1.6   root     9612: #endif /* HAVE_tablejump */
1.1       root     9613: 
                   9614: 
1.1.1.6   root     9615: /* Emit a suitable bytecode to load a value from memory, assuming a pointer
                   9616:    to that value is on the top of the stack. The resulting type is TYPE, and
                   9617:    the source declaration is DECL. */
                   9618: 
                   9619: void
                   9620: bc_load_memory (type, decl)
                   9621:      tree type, decl;
                   9622: {
                   9623:   enum bytecode_opcode opcode;
                   9624:   
                   9625:   
                   9626:   /* Bit fields are special.  We only know about signed and
                   9627:      unsigned ints, and enums.  The latter are treated as
                   9628:      signed integers. */
                   9629:   
                   9630:   if (DECL_BIT_FIELD (decl))
                   9631:     if (TREE_CODE (type) == ENUMERAL_TYPE
                   9632:        || TREE_CODE (type) == INTEGER_TYPE)
                   9633:       opcode = TREE_UNSIGNED (type) ? zxloadBI : sxloadBI;
                   9634:     else
                   9635:       abort ();
                   9636:   else
                   9637:     /* See corresponding comment in bc_store_memory(). */
                   9638:     if (TYPE_MODE (type) == BLKmode
                   9639:        || TYPE_MODE (type) == VOIDmode)
                   9640:       return;
                   9641:     else
                   9642:       opcode = mode_to_load_map [(int) TYPE_MODE (type)];
                   9643: 
                   9644:   if (opcode == neverneverland)
                   9645:     abort ();
                   9646:   
                   9647:   bc_emit_bytecode (opcode);
                   9648:   
                   9649: #ifdef DEBUG_PRINT_CODE
                   9650:   fputc ('\n', stderr);
1.1       root     9651: #endif
1.1.1.6   root     9652: }
1.1       root     9653: 
                   9654: 
1.1.1.6   root     9655: /* Store the contents of the second stack slot to the address in the
                   9656:    top stack slot.  DECL is the declaration of the destination and is used
                   9657:    to determine whether we're dealing with a bitfield. */
1.1       root     9658: 
1.1.1.6   root     9659: void
                   9660: bc_store_memory (type, decl)
                   9661:      tree type, decl;
                   9662: {
                   9663:   enum bytecode_opcode opcode;
                   9664:   
                   9665:   
                   9666:   if (DECL_BIT_FIELD (decl))
1.1       root     9667:     {
1.1.1.6   root     9668:       if (TREE_CODE (type) == ENUMERAL_TYPE
                   9669:          || TREE_CODE (type) == INTEGER_TYPE)
                   9670:        opcode = sstoreBI;
                   9671:       else
                   9672:        abort ();
1.1       root     9673:     }
1.1.1.6   root     9674:   else
                   9675:     if (TYPE_MODE (type) == BLKmode)
                   9676:       {
                   9677:        /* Copy structure.  This expands to a block copy instruction, storeBLK.
                   9678:           In addition to the arguments expected by the other store instructions,
                   9679:           it also expects a type size (SImode) on top of the stack, which is the
                   9680:           structure size in size units (usually bytes).  The two first arguments
                   9681:           are already on the stack; so we just put the size on level 1.  For some
                   9682:           other languages, the size may be variable, this is why we don't encode
                   9683:           it as a storeBLK literal, but rather treat it as a full-fledged expression. */
                   9684:        
                   9685:        bc_expand_expr (TYPE_SIZE (type));
                   9686:        opcode = storeBLK;
                   9687:       }
                   9688:     else
                   9689:       opcode = mode_to_store_map [(int) TYPE_MODE (type)];
1.1       root     9690: 
1.1.1.6   root     9691:   if (opcode == neverneverland)
                   9692:     abort ();
1.1       root     9693: 
1.1.1.6   root     9694:   bc_emit_bytecode (opcode);
                   9695:   
                   9696: #ifdef DEBUG_PRINT_CODE
                   9697:   fputc ('\n', stderr);
                   9698: #endif
1.1       root     9699: }
                   9700: 
1.1.1.6   root     9701: 
                   9702: /* Allocate local stack space sufficient to hold a value of the given
                   9703:    SIZE at alignment boundary ALIGNMENT bits.  ALIGNMENT must be an
                   9704:    integral power of 2.  A special case is locals of type VOID, which
                   9705:    have size 0 and alignment 1 - any "voidish" SIZE or ALIGNMENT is
                   9706:    remapped into the corresponding attribute of SI.  */
                   9707: 
                   9708: rtx
                   9709: bc_allocate_local (size, alignment)
                   9710:      int size, alignment;
1.1       root     9711: {
1.1.1.6   root     9712:   rtx retval;
                   9713:   int byte_alignment;
1.1       root     9714: 
1.1.1.6   root     9715:   if (size < 0)
                   9716:     abort ();
1.1       root     9717: 
1.1.1.6   root     9718:   /* Normalize size and alignment  */
                   9719:   if (!size)
                   9720:     size = UNITS_PER_WORD;
1.1       root     9721: 
1.1.1.6   root     9722:   if (alignment < BITS_PER_UNIT)
                   9723:     byte_alignment = 1 << (INT_ALIGN - 1);
                   9724:   else
                   9725:     /* Align */
                   9726:     byte_alignment = alignment / BITS_PER_UNIT;
1.1       root     9727: 
1.1.1.6   root     9728:   if (local_vars_size & (byte_alignment - 1))
                   9729:     local_vars_size += byte_alignment - (local_vars_size & (byte_alignment - 1));
1.1       root     9730: 
1.1.1.6   root     9731:   retval = bc_gen_rtx ((char *) 0, local_vars_size, (struct bc_label *) 0);
                   9732:   local_vars_size += size;
1.1       root     9733: 
1.1.1.6   root     9734:   return retval;
1.1       root     9735: }
                   9736: 
1.1.1.5   root     9737: 
1.1.1.6   root     9738: /* Allocate variable-sized local array. Variable-sized arrays are
                   9739:    actually pointers to the address in memory where they are stored. */
                   9740: 
                   9741: rtx
                   9742: bc_allocate_variable_array (size)
                   9743:      tree size;
1.1.1.5   root     9744: {
1.1.1.6   root     9745:   rtx retval;
                   9746:   const int ptralign = (1 << (PTR_ALIGN - 1));
1.1.1.5   root     9747: 
1.1.1.6   root     9748:   /* Align pointer */
                   9749:   if (local_vars_size & ptralign)
                   9750:     local_vars_size +=  ptralign - (local_vars_size & ptralign);
1.1.1.5   root     9751: 
1.1.1.6   root     9752:   /* Note down local space needed: pointer to block; also return
                   9753:      dummy rtx */
1.1.1.5   root     9754: 
1.1.1.6   root     9755:   retval = bc_gen_rtx ((char *) 0, local_vars_size, (struct bc_label *) 0);
                   9756:   local_vars_size += POINTER_SIZE / BITS_PER_UNIT;
                   9757:   return retval;
                   9758: }
1.1.1.5   root     9759: 
                   9760: 
1.1.1.6   root     9761: /* Push the machine address for the given external variable offset.  */
                   9762: void
                   9763: bc_load_externaddr (externaddr)
                   9764:      rtx externaddr;
                   9765: {
                   9766:   bc_emit_bytecode (constP);
                   9767:   bc_emit_code_labelref (BYTECODE_LABEL (externaddr),
                   9768:                         BYTECODE_BC_LABEL (externaddr)->offset);
1.1.1.5   root     9769: 
1.1.1.6   root     9770: #ifdef DEBUG_PRINT_CODE
                   9771:   fputc ('\n', stderr);
                   9772: #endif
1.1.1.5   root     9773: }
                   9774: 
1.1       root     9775: 
1.1.1.6   root     9776: static char *
                   9777: bc_strdup (s)
                   9778:     char *s;
1.1       root     9779: {
1.1.1.6   root     9780:   char *new = (char *) xmalloc ((strlen (s) + 1) * sizeof *s);
                   9781:   strcpy (new, s);
                   9782:   return new;
                   9783: }
1.1       root     9784: 
                   9785: 
1.1.1.6   root     9786: /* Like above, but expects an IDENTIFIER.  */
                   9787: void
                   9788: bc_load_externaddr_id (id, offset)
                   9789:      tree id;
                   9790:      int offset;
                   9791: {
                   9792:   if (!IDENTIFIER_POINTER (id))
                   9793:     abort ();
1.1       root     9794: 
1.1.1.6   root     9795:   bc_emit_bytecode (constP);
                   9796:   bc_emit_code_labelref (bc_xstrdup (IDENTIFIER_POINTER (id)), offset);
                   9797: 
                   9798: #ifdef DEBUG_PRINT_CODE
                   9799:   fputc ('\n', stderr);
                   9800: #endif
1.1       root     9801: }
                   9802: 
1.1.1.6   root     9803: 
                   9804: /* Push the machine address for the given local variable offset.  */
                   9805: void
                   9806: bc_load_localaddr (localaddr)
                   9807:      rtx localaddr;
1.1       root     9808: {
1.1.1.6   root     9809:   bc_emit_instruction (localP, (HOST_WIDE_INT) BYTECODE_BC_LABEL (localaddr)->offset);
                   9810: }
1.1       root     9811: 
                   9812: 
1.1.1.6   root     9813: /* Push the machine address for the given parameter offset.
                   9814:    NOTE: offset is in bits. */
                   9815: void
                   9816: bc_load_parmaddr (parmaddr)
                   9817:      rtx parmaddr;
                   9818: {
                   9819:   bc_emit_instruction (argP, ((HOST_WIDE_INT) BYTECODE_BC_LABEL (parmaddr)->offset
                   9820:                              / BITS_PER_UNIT));
                   9821: }
                   9822: 
                   9823: 
                   9824: /* Convert a[i] into *(a + i).  */
                   9825: tree
                   9826: bc_canonicalize_array_ref (exp)
                   9827:      tree exp;
                   9828: {
                   9829:   tree type = TREE_TYPE (exp);
                   9830:   tree array_adr = build1 (ADDR_EXPR, TYPE_POINTER_TO (type),
                   9831:                           TREE_OPERAND (exp, 0));
                   9832:   tree index = TREE_OPERAND (exp, 1);
1.1       root     9833: 
1.1.1.6   root     9834: 
                   9835:   /* Convert the integer argument to a type the same size as a pointer
                   9836:      so the multiply won't overflow spuriously.  */
                   9837: 
                   9838:   if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE)
                   9839:     index = convert (type_for_size (POINTER_SIZE, 0), index);
                   9840: 
                   9841:   /* The array address isn't volatile even if the array is.
                   9842:      (Of course this isn't terribly relevant since the bytecode
                   9843:      translator treats nearly everything as volatile anyway.)  */
                   9844:   TREE_THIS_VOLATILE (array_adr) = 0;
                   9845: 
                   9846:   return build1 (INDIRECT_REF, type,
                   9847:                 fold (build (PLUS_EXPR,
                   9848:                              TYPE_POINTER_TO (type),
                   9849:                              array_adr,
                   9850:                              fold (build (MULT_EXPR,
                   9851:                                           TYPE_POINTER_TO (type),
                   9852:                                           index,
                   9853:                                           size_in_bytes (type))))));
1.1       root     9854: }
                   9855: 
                   9856: 
1.1.1.6   root     9857: /* Load the address of the component referenced by the given
                   9858:    COMPONENT_REF expression.
                   9859: 
                   9860:    Returns innermost lvalue. */
                   9861: 
                   9862: tree
                   9863: bc_expand_component_address (exp)
                   9864:      tree exp;
1.1       root     9865: {
1.1.1.6   root     9866:   tree tem, chain;
                   9867:   enum machine_mode mode;
                   9868:   int bitpos = 0;
                   9869:   HOST_WIDE_INT SIval;
1.1       root     9870: 
                   9871: 
1.1.1.6   root     9872:   tem = TREE_OPERAND (exp, 1);
                   9873:   mode = DECL_MODE (tem);
1.1       root     9874: 
                   9875: 
1.1.1.6   root     9876:   /* Compute cumulative bit offset for nested component refs
                   9877:      and array refs, and find the ultimate containing object.  */
                   9878: 
                   9879:   for (tem = exp;; tem = TREE_OPERAND (tem, 0))
                   9880:     {
                   9881:       if (TREE_CODE (tem) == COMPONENT_REF)
                   9882:        bitpos += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (tem, 1)));
1.1       root     9883:       else
1.1.1.6   root     9884:        if (TREE_CODE (tem) == ARRAY_REF
                   9885:            && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
                   9886:            && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST)
1.1       root     9887: 
1.1.1.6   root     9888:          bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1))
                   9889:                     * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)))
                   9890:                     /* * TYPE_SIZE_UNIT (TREE_TYPE (tem)) */);
                   9891:        else
                   9892:          break;
                   9893:     }
1.1       root     9894: 
1.1.1.6   root     9895:   bc_expand_expr (tem);
1.1       root     9896: 
1.1.1.6   root     9897: 
                   9898:   /* For bitfields also push their offset and size */
                   9899:   if (DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
                   9900:     bc_push_offset_and_size (bitpos, /* DECL_SIZE_UNIT */ (TREE_OPERAND (exp, 1)));
                   9901:   else
                   9902:     if (SIval = bitpos / BITS_PER_UNIT)
                   9903:       bc_emit_instruction (addconstPSI, SIval);
                   9904: 
                   9905:   return (TREE_OPERAND (exp, 1));
1.1       root     9906: }
                   9907: 
                   9908: 
1.1.1.6   root     9909: /* Emit code to push two SI constants */
                   9910: void
                   9911: bc_push_offset_and_size (offset, size)
                   9912:      HOST_WIDE_INT offset, size;
1.1       root     9913: {
1.1.1.6   root     9914:   bc_emit_instruction (constSI, offset);
                   9915:   bc_emit_instruction (constSI, size);
1.1       root     9916: }
                   9917: 
                   9918: 
1.1.1.6   root     9919: /* Emit byte code to push the address of the given lvalue expression to
                   9920:    the stack.  If it's a bit field, we also push offset and size info.
1.1       root     9921: 
1.1.1.6   root     9922:    Returns innermost component, which allows us to determine not only
                   9923:    its type, but also whether it's a bitfield. */
1.1       root     9924: 
1.1.1.6   root     9925: tree
                   9926: bc_expand_address (exp)
                   9927:      tree exp;
1.1       root     9928: {
1.1.1.6   root     9929:   /* Safeguard */
                   9930:   if (!exp || TREE_CODE (exp) == ERROR_MARK)
                   9931:     return (exp);
1.1.1.5   root     9932: 
1.1       root     9933: 
1.1.1.6   root     9934:   switch (TREE_CODE (exp))
1.1       root     9935:     {
1.1.1.6   root     9936:     case ARRAY_REF:
1.1       root     9937: 
1.1.1.6   root     9938:       return (bc_expand_address (bc_canonicalize_array_ref (exp)));
1.1       root     9939: 
1.1.1.6   root     9940:     case COMPONENT_REF:
1.1       root     9941: 
1.1.1.6   root     9942:       return (bc_expand_component_address (exp));
1.1       root     9943: 
1.1.1.6   root     9944:     case INDIRECT_REF:
1.1.1.4   root     9945: 
1.1.1.6   root     9946:       bc_expand_expr (TREE_OPERAND (exp, 0));
1.1       root     9947: 
1.1.1.6   root     9948:       /* For variable-sized types: retrieve pointer.  Sometimes the
                   9949:         TYPE_SIZE tree is NULL.  Is this a bug or a feature?  Let's
                   9950:         also make sure we have an operand, just in case... */
                   9951: 
                   9952:       if (TREE_OPERAND (exp, 0)
                   9953:          && TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)))
                   9954:          && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)))) != INTEGER_CST)
                   9955:        bc_emit_instruction (loadP);
1.1.1.3   root     9956: 
1.1.1.6   root     9957:       /* If packed, also return offset and size */
                   9958:       if (DECL_BIT_FIELD (TREE_OPERAND (exp, 0)))
                   9959:        
                   9960:        bc_push_offset_and_size (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (exp, 0))),
                   9961:                                 TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (exp, 0))));
1.1       root     9962: 
1.1.1.6   root     9963:       return (TREE_OPERAND (exp, 0));
1.1       root     9964: 
1.1.1.6   root     9965:     case FUNCTION_DECL:
1.1       root     9966: 
1.1.1.6   root     9967:       bc_load_externaddr_id (DECL_ASSEMBLER_NAME (exp),
                   9968:                             BYTECODE_BC_LABEL (DECL_RTL (exp))->offset);
                   9969:       break;
1.1       root     9970: 
1.1.1.6   root     9971:     case PARM_DECL:
1.1       root     9972: 
1.1.1.6   root     9973:       bc_load_parmaddr (DECL_RTL (exp));
1.1.1.3   root     9974: 
1.1.1.6   root     9975:       /* For variable-sized types: retrieve pointer */
                   9976:       if (TYPE_SIZE (TREE_TYPE (exp))
                   9977:          && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST)
                   9978:        bc_emit_instruction (loadP);
                   9979: 
                   9980:       /* If packed, also return offset and size */
                   9981:       if (DECL_BIT_FIELD (exp))
                   9982:        bc_push_offset_and_size (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (exp)),
                   9983:                                 TREE_INT_CST_LOW (DECL_SIZE (exp)));
1.1.1.3   root     9984: 
1.1.1.6   root     9985:       break;
1.1.1.3   root     9986: 
1.1.1.6   root     9987:     case RESULT_DECL:
1.1       root     9988: 
1.1.1.6   root     9989:       bc_emit_instruction (returnP);
                   9990:       break;
1.1       root     9991: 
1.1.1.6   root     9992:     case VAR_DECL:
1.1       root     9993: 
1.1.1.6   root     9994: #if 0
                   9995:       if (BYTECODE_LABEL (DECL_RTL (exp)))
                   9996:        bc_load_externaddr (DECL_RTL (exp));
                   9997: #endif
                   9998: 
                   9999:       if (DECL_EXTERNAL (exp))
                   10000:        bc_load_externaddr_id (DECL_ASSEMBLER_NAME (exp),
                   10001:                               (BYTECODE_BC_LABEL (DECL_RTL (exp)))->offset);
1.1       root     10002:       else
1.1.1.6   root     10003:        bc_load_localaddr (DECL_RTL (exp));
                   10004: 
                   10005:       /* For variable-sized types: retrieve pointer */
                   10006:       if (TYPE_SIZE (TREE_TYPE (exp))
                   10007:          && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST)
                   10008:        bc_emit_instruction (loadP);
                   10009: 
                   10010:       /* If packed, also return offset and size */
                   10011:       if (DECL_BIT_FIELD (exp))
                   10012:        bc_push_offset_and_size (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (exp)),
                   10013:                                 TREE_INT_CST_LOW (DECL_SIZE (exp)));
                   10014:       
1.1       root     10015:       break;
1.1.1.6   root     10016: 
                   10017:     case STRING_CST:
                   10018:       {
                   10019:        rtx r;
                   10020:        
                   10021:        bc_emit_bytecode (constP);
                   10022:        r = output_constant_def (exp);
                   10023:        bc_emit_code_labelref (BYTECODE_LABEL (r), BYTECODE_BC_LABEL (r)->offset);
                   10024: 
                   10025: #ifdef DEBUG_PRINT_CODE
                   10026:        fputc ('\n', stderr);
                   10027: #endif
                   10028:       }
1.1       root     10029:       break;
1.1.1.6   root     10030: 
                   10031:     default:
                   10032: 
                   10033:       abort();
1.1       root     10034:       break;
1.1.1.6   root     10035:     }
                   10036: 
                   10037:   /* Most lvalues don't have components. */
                   10038:   return (exp);
                   10039: }
                   10040: 
                   10041: 
                   10042: /* Emit a type code to be used by the runtime support in handling
                   10043:    parameter passing.   The type code consists of the machine mode
                   10044:    plus the minimal alignment shifted left 8 bits.  */
                   10045: 
                   10046: tree
                   10047: bc_runtime_type_code (type)
                   10048:      tree type;
                   10049: {
                   10050:   int val;
                   10051: 
                   10052:   switch (TREE_CODE (type))
                   10053:     {
                   10054:     case VOID_TYPE:
                   10055:     case INTEGER_TYPE:
                   10056:     case REAL_TYPE:
                   10057:     case COMPLEX_TYPE:
                   10058:     case ENUMERAL_TYPE:
                   10059:     case POINTER_TYPE:
                   10060:     case RECORD_TYPE:
                   10061: 
                   10062:       val = (int) TYPE_MODE (type) | TYPE_ALIGN (type) << 8;
                   10063:       break;
                   10064: 
                   10065:     case ERROR_MARK:
                   10066: 
                   10067:       val = 0;
1.1       root     10068:       break;
1.1.1.6   root     10069: 
1.1       root     10070:     default:
1.1.1.6   root     10071: 
1.1       root     10072:       abort ();
                   10073:     }
1.1.1.6   root     10074:   return build_int_2 (val, 0);
                   10075: }
1.1       root     10076: 
1.1.1.2   root     10077: 
1.1.1.6   root     10078: /* Generate constructor label */
                   10079: char *
                   10080: bc_gen_constr_label ()
                   10081: {
                   10082:   static int label_counter;
                   10083:   static char label[20];
1.1       root     10084: 
1.1.1.6   root     10085:   sprintf (label, "*LR%d", label_counter++);
1.1       root     10086: 
1.1.1.6   root     10087:   return (obstack_copy0 (&permanent_obstack, label, strlen (label)));
                   10088: }
1.1       root     10089: 
                   10090: 
1.1.1.6   root     10091: /* Evaluate constructor CONSTR and return pointer to it on level one.  We
                   10092:    expand the constructor data as static data, and push a pointer to it.
                   10093:    The pointer is put in the pointer table and is retrieved by a constP
                   10094:    bytecode instruction.  We then loop and store each constructor member in
                   10095:    the corresponding component.  Finally, we return the original pointer on
                   10096:    the stack. */
1.1       root     10097: 
1.1.1.6   root     10098: void
                   10099: bc_expand_constructor (constr)
                   10100:      tree constr;
                   10101: {
                   10102:   char *l;
                   10103:   HOST_WIDE_INT ptroffs;
                   10104:   rtx constr_rtx;
1.1       root     10105: 
1.1.1.6   root     10106:   
                   10107:   /* Literal constructors are handled as constants, whereas
                   10108:      non-literals are evaluated and stored element by element
                   10109:      into the data segment. */
                   10110:   
                   10111:   /* Allocate space in proper segment and push pointer to space on stack.
                   10112:    */
1.1       root     10113: 
1.1.1.6   root     10114:   l = bc_gen_constr_label ();
1.1       root     10115: 
1.1.1.6   root     10116:   if (TREE_CONSTANT (constr))
                   10117:     {
                   10118:       text_section ();
1.1       root     10119: 
1.1.1.6   root     10120:       bc_emit_const_labeldef (l);
                   10121:       bc_output_constructor (constr, int_size_in_bytes (TREE_TYPE (constr)));
                   10122:     }
                   10123:   else
1.1       root     10124:     {
1.1.1.6   root     10125:       data_section ();
                   10126: 
                   10127:       bc_emit_data_labeldef (l);
                   10128:       bc_output_data_constructor (constr);
1.1       root     10129:     }
                   10130: 
1.1.1.6   root     10131:   
                   10132:   /* Add reference to pointer table and recall pointer to stack;
                   10133:      this code is common for both types of constructors: literals
                   10134:      and non-literals. */
1.1       root     10135: 
1.1.1.6   root     10136:   ptroffs = bc_define_pointer (l);
                   10137:   bc_emit_instruction (constP, ptroffs);
1.1       root     10138: 
1.1.1.6   root     10139:   /* This is all that has to be done if it's a literal. */
                   10140:   if (TREE_CONSTANT (constr))
                   10141:     return;
1.1.1.4   root     10142: 
1.1       root     10143: 
1.1.1.6   root     10144:   /* At this point, we have the pointer to the structure on top of the stack.
                   10145:      Generate sequences of store_memory calls for the constructor. */
                   10146:   
                   10147:   /* constructor type is structure */
                   10148:   if (TREE_CODE (TREE_TYPE (constr)) == RECORD_TYPE)
1.1.1.3   root     10149:     {
1.1.1.6   root     10150:       register tree elt;
                   10151:       
                   10152:       /* If the constructor has fewer fields than the structure,
                   10153:         clear the whole structure first.  */
                   10154:       
                   10155:       if (list_length (CONSTRUCTOR_ELTS (constr))
                   10156:          != list_length (TYPE_FIELDS (TREE_TYPE (constr))))
                   10157:        {
                   10158:          bc_emit_instruction (duplicate);
                   10159:          bc_emit_instruction (constSI, (HOST_WIDE_INT) int_size_in_bytes (TREE_TYPE (constr)));
                   10160:          bc_emit_instruction (clearBLK);
                   10161:        }
                   10162:       
                   10163:       /* Store each element of the constructor into the corresponding
                   10164:         field of TARGET.  */
                   10165:       
                   10166:       for (elt = CONSTRUCTOR_ELTS (constr); elt; elt = TREE_CHAIN (elt))
                   10167:        {
                   10168:          register tree field = TREE_PURPOSE (elt);
                   10169:          register enum machine_mode mode;
                   10170:          int bitsize;
                   10171:          int bitpos;
                   10172:          int unsignedp;
                   10173:          
                   10174:          bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) /* * DECL_SIZE_UNIT (field) */;
                   10175:          mode = DECL_MODE (field);
                   10176:          unsignedp = TREE_UNSIGNED (field);
                   10177: 
                   10178:          bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
                   10179:          
                   10180:          bc_store_field (elt, bitsize, bitpos, mode, TREE_VALUE (elt), TREE_TYPE (TREE_VALUE (elt)),
                   10181:                          /* The alignment of TARGET is
                   10182:                             at least what its type requires.  */
                   10183:                          VOIDmode, 0,
                   10184:                          TYPE_ALIGN (TREE_TYPE (constr)) / BITS_PER_UNIT,
                   10185:                          int_size_in_bytes (TREE_TYPE (constr)));
                   10186:        }
1.1.1.3   root     10187:     }
1.1.1.6   root     10188:   else
                   10189:     
                   10190:     /* Constructor type is array */
                   10191:     if (TREE_CODE (TREE_TYPE (constr)) == ARRAY_TYPE)
                   10192:       {
                   10193:        register tree elt;
                   10194:        register int i;
                   10195:        tree domain = TYPE_DOMAIN (TREE_TYPE (constr));
                   10196:        int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
                   10197:        int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
                   10198:        tree elttype = TREE_TYPE (TREE_TYPE (constr));
                   10199:        
                   10200:        /* If the constructor has fewer fields than the structure,
                   10201:           clear the whole structure first.  */
                   10202:        
                   10203:        if (list_length (CONSTRUCTOR_ELTS (constr)) < maxelt - minelt + 1)
                   10204:          {
                   10205:            bc_emit_instruction (duplicate);
                   10206:            bc_emit_instruction (constSI, (HOST_WIDE_INT) int_size_in_bytes (TREE_TYPE (constr)));
                   10207:            bc_emit_instruction (clearBLK);
                   10208:          }
                   10209:        
                   10210:        
                   10211:        /* Store each element of the constructor into the corresponding
                   10212:           element of TARGET, determined by counting the elements. */
                   10213:        
                   10214:        for (elt = CONSTRUCTOR_ELTS (constr), i = 0;
                   10215:             elt;
                   10216:             elt = TREE_CHAIN (elt), i++)
                   10217:          {
                   10218:            register enum machine_mode mode;
                   10219:            int bitsize;
                   10220:            int bitpos;
                   10221:            int unsignedp;
                   10222:            
                   10223:            mode = TYPE_MODE (elttype);
                   10224:            bitsize = GET_MODE_BITSIZE (mode);
                   10225:            unsignedp = TREE_UNSIGNED (elttype);
                   10226:            
                   10227:            bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype))
                   10228:                      /* * TYPE_SIZE_UNIT (elttype) */ );
                   10229:            
                   10230:            bc_store_field (elt, bitsize, bitpos, mode,
                   10231:                            TREE_VALUE (elt), TREE_TYPE (TREE_VALUE (elt)),
                   10232:                            /* The alignment of TARGET is
                   10233:                               at least what its type requires.  */
                   10234:                            VOIDmode, 0,
                   10235:                            TYPE_ALIGN (TREE_TYPE (constr)) / BITS_PER_UNIT,
                   10236:                            int_size_in_bytes (TREE_TYPE (constr)));
                   10237:          }
                   10238:   
                   10239:       }
                   10240: }
1.1       root     10241: 
                   10242: 
1.1.1.6   root     10243: /* Store the value of EXP (an expression tree) into member FIELD of
                   10244:    structure at address on stack, which has type TYPE, mode MODE and
                   10245:    occupies BITSIZE bits, starting BITPOS bits from the beginning of the
                   10246:    structure.
1.1       root     10247: 
1.1.1.6   root     10248:    ALIGN is the alignment that TARGET is known to have, measured in bytes.
                   10249:    TOTAL_SIZE is its size in bytes, or -1 if variable.  */
1.1       root     10250: 
1.1.1.6   root     10251: void
                   10252: bc_store_field (field, bitsize, bitpos, mode, exp, type,
                   10253:                value_mode, unsignedp, align, total_size)
                   10254:      int bitsize, bitpos;
                   10255:      enum machine_mode mode;
                   10256:      tree field, exp, type;
                   10257:      enum machine_mode value_mode;
                   10258:      int unsignedp;
                   10259:      int align;
                   10260:      int total_size;
                   10261: {
1.1       root     10262: 
1.1.1.6   root     10263:   /* Expand expression and copy pointer */
                   10264:   bc_expand_expr (exp);
                   10265:   bc_emit_instruction (over);
1.1       root     10266: 
                   10267: 
1.1.1.6   root     10268:   /* If the component is a bit field, we cannot use addressing to access
                   10269:      it.  Use bit-field techniques to store in it.  */
1.1       root     10270: 
1.1.1.6   root     10271:   if (DECL_BIT_FIELD (field))
                   10272:     {
                   10273:       bc_store_bit_field (bitpos, bitsize, unsignedp);
                   10274:       return;
                   10275:     }
                   10276:   else
                   10277:     /* Not bit field */
                   10278:     {
                   10279:       HOST_WIDE_INT offset = bitpos / BITS_PER_UNIT;
                   10280: 
                   10281:       /* Advance pointer to the desired member */
                   10282:       if (offset)
                   10283:        bc_emit_instruction (addconstPSI, offset);
                   10284: 
                   10285:       /* Store */
                   10286:       bc_store_memory (type, field);
                   10287:     }
                   10288: }
1.1       root     10289: 
1.1.1.6   root     10290: 
                   10291: /* Store SI/SU in bitfield */
1.1       root     10292: void
1.1.1.6   root     10293: bc_store_bit_field (offset, size, unsignedp)
                   10294:      int offset, size, unsignedp;
1.1       root     10295: {
1.1.1.6   root     10296:   /* Push bitfield offset and size */
                   10297:   bc_push_offset_and_size (offset, size);
1.1       root     10298: 
1.1.1.6   root     10299:   /* Store */
                   10300:   bc_emit_instruction (sstoreBI);
                   10301: }
1.1.1.2   root     10302: 
1.1.1.3   root     10303: 
1.1.1.6   root     10304: /* Load SI/SU from bitfield */
                   10305: void
                   10306: bc_load_bit_field (offset, size, unsignedp)
                   10307:      int offset, size, unsignedp;
                   10308: {
                   10309:   /* Push bitfield offset and size */
                   10310:   bc_push_offset_and_size (offset, size);
1.1.1.3   root     10311: 
1.1.1.6   root     10312:   /* Load: sign-extend if signed, else zero-extend */
                   10313:   bc_emit_instruction (unsignedp ? zxloadBI : sxloadBI);
                   10314: }  
1.1       root     10315: 
                   10316: 
1.1.1.6   root     10317: /* Adjust interpreter stack by NLEVELS.  Positive means drop NLEVELS
                   10318:    (adjust stack pointer upwards), negative means add that number of
                   10319:    levels (adjust the stack pointer downwards).  Only positive values
                   10320:    normally make sense. */
                   10321: 
                   10322: void
                   10323: bc_adjust_stack (nlevels)
                   10324:      int nlevels;
                   10325: {
                   10326:   switch (nlevels)
                   10327:     {
                   10328:     case 0:
                   10329:       break;
                   10330:       
                   10331:     case 2:
                   10332:       bc_emit_instruction (drop);
                   10333:       
                   10334:     case 1:
                   10335:       bc_emit_instruction (drop);
                   10336:       break;
                   10337:       
                   10338:     default:
                   10339:       
                   10340:       bc_emit_instruction (adjstackSI, (HOST_WIDE_INT) nlevels);
                   10341:       stack_depth -= nlevels;
                   10342:     }
                   10343: 
                   10344: #if defined (VALIDATE_STACK_FOR_BC)
                   10345:   VALIDATE_STACK_FOR_BC ();
1.1       root     10346: #endif
                   10347: }

unix.superglobalmegacorp.com

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