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