Annotation of gcc/expr.c, revision 1.1.1.8

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

unix.superglobalmegacorp.com

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