OSDN Git Service

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