Annotation of GNUtools/cc/expr.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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