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