|
|
1.1 root 1: /* Convert tree expression to rtl instructions, for GNU compiler.
1.1.1.2 root 2: Copyright (C) 1988 Free Software Foundation, Inc.
1.1 root 3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include "config.h"
23: #include "rtl.h"
24: #include "tree.h"
1.1.1.2 root 25: #include "flags.h"
1.1 root 26: #include "insn-flags.h"
27: #include "insn-codes.h"
28: #include "expr.h"
1.1.1.2 root 29: #include "insn-config.h"
30: #include "recog.h"
31: #include "varargs.h"
32:
33: /* Decide whether a function's arguments should be processed
34: from first to last or from last to first. */
35:
36: #ifdef STACK_GROWS_DOWNWARD
37: #ifdef PUSH_ROUNDING
38: #define PUSH_ARGS_REVERSED /* If it's last to first */
39: #endif
40: #endif
41:
42: /* Like STACK_BOUNDARY but in units of bytes, not bits. */
43: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
1.1 root 44:
45: /* If this is nonzero, we do not bother generating VOLATILE
46: around volatile memory references, and we are willing to
47: output indirect addresses. If cse is to follow, we reject
48: indirect addresses so a useful potential cse is generated;
49: if it is used only once, instruction combination will produce
50: the same indirect address eventually. */
51: int cse_not_expected;
52:
53: /* Nonzero to generate code for all the subroutines within an
54: expression before generating the upper levels of the expression.
55: Nowadays this is never zero. */
56: int do_preexpand_calls = 1;
57:
58: /* Number of units that we should eventually pop off the stack.
59: These are the arguments to function calls that have already returned. */
60: int pending_stack_adjust;
61:
62: /* Total size of arguments already pushed for function calls that
1.1.1.6 root 63: have not happened yet. When this is nonzero,
1.1 root 64: args passed to function calls must be popped right away
1.1.1.6 root 65: to ensure contiguity of argument lists for future calls.
66:
67: This can also be temporarily incremented for various other reasons
68: to inhibit deferring of pops. */
1.1.1.2 root 69: static int current_args_size;
1.1 root 70:
1.1.1.6 root 71: #define NO_DEFER_POP current_args_size += 1
72: #define OK_DEFER_POP current_args_size -= 1
73:
1.1.1.2 root 74: /* Nonzero means current function may call alloca. */
75: int may_call_alloca;
76:
77: rtx store_expr ();
78: static void store_constructor ();
79: static rtx store_field ();
1.1 root 80: static rtx expand_call ();
1.1.1.2 root 81: static void emit_call_1 ();
82: static rtx prepare_call_address ();
83: static rtx expand_builtin ();
1.1 root 84: static rtx compare ();
1.1.1.2 root 85: static rtx compare_constants ();
1.1 root 86: static rtx compare1 ();
87: static rtx do_store_flag ();
88: static void preexpand_calls ();
1.1.1.2 root 89: static rtx expand_increment ();
90: static void move_by_pieces_1 ();
1.1.1.4 root 91: static int move_by_pieces_ninsns ();
1.1.1.2 root 92: static void init_queue ();
93:
94: void do_pending_stack_adjust ();
1.1 root 95:
96: /* MOVE_RATIO is the number of move instructions that is better than
97: a block move. */
98:
99: #if defined (HAVE_movstrhi) || defined (HAVE_movstrsi)
100: #define MOVE_RATIO 2
101: #else
102: #define MOVE_RATIO 6
103: #endif
104:
105: /* Table indexed by tree code giving 1 if the code is for a
106: comparison operation, or anything that is most easily
107: computed with a conditional branch.
108:
109: We include tree.def to give it the proper length.
110: The contents thus created are irrelevant.
111: The real contents are initialized in init_comparisons. */
112:
1.1.1.2 root 113: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) 0,
1.1 root 114:
115: static char comparison_code[] = {
116: #include "tree.def"
117: };
118: #undef DEFTREECODE
119:
1.1.1.2 root 120: /* This is run once per compilation. */
121:
122: void
1.1 root 123: init_comparisons ()
124: {
125: comparison_code[(int) EQ_EXPR] = 1;
126: comparison_code[(int) NE_EXPR] = 1;
127: comparison_code[(int) LT_EXPR] = 1;
128: comparison_code[(int) GT_EXPR] = 1;
129: comparison_code[(int) LE_EXPR] = 1;
130: comparison_code[(int) GE_EXPR] = 1;
131: }
1.1.1.2 root 132:
133: /* This is run at the start of compiling a function. */
134:
135: void
136: init_expr ()
137: {
138: init_queue ();
139: may_call_alloca = 0;
140: }
1.1 root 141:
142: /* Manage the queue of increment instructions to be output
143: for POSTINCREMENT_EXPR expressions, etc. */
144:
145: static rtx pending_chain;
146:
147: /* Queue up to increment (or change) VAR later. BODY says how:
148: BODY should be the same thing you would pass to emit_insn
149: to increment right away. It will go to emit_insn later on.
150:
151: The value is a QUEUED expression to be used in place of VAR
1.1.1.2 root 152: where you want to guarantee the pre-incrementation value of VAR. */
1.1 root 153:
154: static rtx
155: enqueue_insn (var, body)
156: rtx var, body;
157: {
158: pending_chain = gen_rtx (QUEUED, GET_MODE (var),
159: var, 0, 0, body, pending_chain);
160: return pending_chain;
161: }
162:
163: /* Use protect_from_queue to convert a QUEUED expression
164: into something that you can put immediately into an instruction.
165: If the queued incrementation has not happened yet,
166: protect_from_queue returns the variable itself.
167: If the incrementation has happened, protect_from_queue returns a temp
168: that contains a copy of the old value of the variable.
169:
170: Any time an rtx which might possibly be a QUEUED is to be put
171: into an instruction, it must be passed through protect_from_queue first.
172: QUEUED expressions are not meaningful in instructions.
173:
174: Do not pass a value through protect_from_queue and then hold
175: on to it for a while before putting it in an instruction!
176: If the queue is flushed in between, incorrect code will result. */
177:
178: rtx
179: protect_from_queue (x, modify)
180: register rtx x;
181: int modify;
182: {
183: register RTX_CODE code = GET_CODE (x);
184: if (code != QUEUED)
185: {
186: /* A special hack for read access to (MEM (QUEUED ...))
187: to facilitate use of autoincrement.
188: Make a copy of the contents of the memory location
189: rather than a copy of the address. */
190: if (code == MEM && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
191: {
192: register rtx y = XEXP (x, 0);
193: XEXP (x, 0) = QUEUED_VAR (y);
194: if (QUEUED_INSN (y))
195: {
196: register rtx temp = gen_reg_rtx (GET_MODE (x));
197: emit_insn_before (gen_move_insn (temp, x),
198: QUEUED_INSN (y));
199: return temp;
200: }
201: return x;
202: }
203: /* Otherwise, recursively protect the subexpressions of all
204: the kinds of rtx's that can contain a QUEUED. */
205: if (code == MEM)
206: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
207: else if (code == PLUS || code == MULT)
208: {
209: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
210: XEXP (x, 1) = protect_from_queue (XEXP (x, 1), 0);
211: }
212: return x;
213: }
214: /* If the increment has not happened, use the variable itself. */
215: if (QUEUED_INSN (x) == 0)
216: return QUEUED_VAR (x);
217: /* If the increment has happened and a pre-increment copy exists,
218: use that copy. */
219: if (QUEUED_COPY (x) != 0)
220: return QUEUED_COPY (x);
221: /* The increment has happened but we haven't set up a pre-increment copy.
222: Set one up now, and use it. */
223: QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
224: emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
225: QUEUED_INSN (x));
226: return QUEUED_COPY (x);
227: }
228:
1.1.1.2 root 229: /* Return nonzero if X contains a QUEUED expression:
230: if it contains anything that will be altered by a queued increment. */
231:
232: static int
233: queued_subexp_p (x)
234: rtx x;
235: {
236: register enum rtx_code code = GET_CODE (x);
237: switch (code)
238: {
239: case QUEUED:
240: return 1;
241: case MEM:
242: return queued_subexp_p (XEXP (x, 0));
243: case MULT:
244: case PLUS:
245: case MINUS:
246: return queued_subexp_p (XEXP (x, 0))
247: || queued_subexp_p (XEXP (x, 1));
248: }
249: return 0;
250: }
251:
252: /* Perform all the pending incrementations. */
1.1 root 253:
254: void
255: emit_queue ()
256: {
257: register rtx p;
258: while (p = pending_chain)
259: {
260: QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p));
261: pending_chain = QUEUED_NEXT (p);
262: }
263: }
264:
1.1.1.2 root 265: static void
1.1 root 266: init_queue ()
267: {
268: if (pending_chain)
269: abort ();
270: }
271:
272: /* Copy data from FROM to TO, where the machine modes are not the same.
273: Both modes may be integer, or both may be floating.
274: UNSIGNEDP should be nonzero if FROM is an unsigned type.
275: This causes zero-extension instead of sign-extension. */
276:
277: void
278: convert_move (to, from, unsignedp)
279: register rtx to, from;
280: int unsignedp;
281: {
282: enum machine_mode to_mode = GET_MODE (to);
283: enum machine_mode from_mode = GET_MODE (from);
284: int to_real = to_mode == SFmode || to_mode == DFmode;
285: int from_real = from_mode == SFmode || from_mode == DFmode;
286: int extending = (int) to_mode > (int) from_mode;
287:
288: to = protect_from_queue (to, 1);
289: from = protect_from_queue (from, 0);
290:
291: if (to_real != from_real)
292: abort ();
293:
1.1.1.2 root 294: if (to_mode == from_mode
295: || (from_mode == VOIDmode && CONSTANT_P (from)))
1.1 root 296: {
297: emit_move_insn (to, from);
298: return;
299: }
300:
301: if (to_real)
302: {
303: #ifdef HAVE_extendsfdf2
304: if (HAVE_extendsfdf2 && extending)
305: {
1.1.1.2 root 306: emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN);
1.1 root 307: return;
308: }
309: #endif
310: #ifdef HAVE_truncdfsf2
311: if (HAVE_truncdfsf2 && ! extending)
312: {
1.1.1.2 root 313: emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
1.1 root 314: return;
315: }
316: #endif
317: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, (extending
1.1.1.2 root 318: ? "_extendsfdf2"
319: : "_truncdfsf2")),
320: GET_MODE (to), 1,
321: from, (extending ? SFmode : DFmode));
322: emit_move_insn (to, hard_libcall_value (GET_MODE (to)));
1.1 root 323: return;
324: }
325:
1.1.1.2 root 326: /* Now both modes are integers. */
327:
1.1 root 328: if (to_mode == DImode)
329: {
330: if (unsignedp)
331: {
1.1.1.5 root 332: emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
1.1 root 333: convert_move (gen_lowpart (SImode, to), from, unsignedp);
334: emit_clr_insn (gen_highpart (SImode, to));
335: }
1.1.1.5 root 336: #ifdef HAVE_extendsidi2
337: else if (HAVE_extendsidi2)
338: emit_insn (gen_extendsidi2 (to, from));
339: #endif
1.1.1.2 root 340: #ifdef HAVE_slt
341: else if (HAVE_slt && insn_operand_mode[(int) CODE_FOR_slt][0] == SImode)
1.1 root 342: {
1.1.1.5 root 343: emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
1.1 root 344: convert_move (gen_lowpart (SImode, to), from, unsignedp);
1.1.1.2 root 345: emit_insn (gen_slt (gen_highpart (SImode, to)));
1.1 root 346: }
347: #endif
348: else
349: {
350: register rtx label = gen_label_rtx ();
351:
1.1.1.5 root 352: emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
1.1 root 353: emit_clr_insn (gen_highpart (SImode, to));
354: convert_move (gen_lowpart (SImode, to), from, unsignedp);
355: emit_cmp_insn (gen_lowpart (SImode, to),
356: gen_rtx (CONST_INT, VOIDmode, 0),
357: 0, 0);
1.1.1.6 root 358: NO_DEFER_POP;
1.1 root 359: emit_jump_insn (gen_bge (label));
360: expand_unop (SImode, one_cmpl_optab,
361: gen_highpart (SImode, to), gen_highpart (SImode, to),
362: 1);
363: emit_label (label);
1.1.1.6 root 364: OK_DEFER_POP;
1.1 root 365: }
366: return;
367: }
368:
369: if (from_mode == DImode)
370: {
371: convert_move (to, gen_lowpart (SImode, from), 0);
372: return;
373: }
374:
375: /* Now follow all the conversions between integers
376: no more than a word long. */
377:
1.1.1.2 root 378: /* For truncation, usually we can just refer to FROM in a narrower mode. */
379: if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
380: && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
381: GET_MODE_BITSIZE (from_mode))
382: && ((GET_CODE (from) == MEM
383: && ! mode_dependent_address_p (XEXP (from, 0)))
384: || GET_CODE (from) == REG))
385: {
386: emit_move_insn (to, gen_lowpart (to_mode, from));
387: return;
388: }
389:
1.1 root 390: if (to_mode == SImode && from_mode == HImode)
391: {
392: if (unsignedp)
393: {
394: #ifdef HAVE_zero_extendhisi2
395: if (HAVE_zero_extendhisi2)
1.1.1.2 root 396: emit_unop_insn (CODE_FOR_zero_extendhisi2, to, from, ZERO_EXTEND);
1.1 root 397: else
398: #endif
399: abort ();
400: }
401: else
402: {
403: #ifdef HAVE_extendhisi2
404: if (HAVE_extendhisi2)
1.1.1.2 root 405: emit_unop_insn (CODE_FOR_extendhisi2, to, from, SIGN_EXTEND);
1.1 root 406: else
407: #endif
408: abort ();
409: }
410: return;
411: }
412:
413: if (to_mode == SImode && from_mode == QImode)
414: {
415: if (unsignedp)
416: {
417: #ifdef HAVE_zero_extendqisi2
418: if (HAVE_zero_extendqisi2)
419: {
1.1.1.2 root 420: emit_unop_insn (CODE_FOR_zero_extendqisi2, to, from, ZERO_EXTEND);
1.1 root 421: return;
422: }
423: #endif
424: #if defined (HAVE_zero_extendqihi2) && defined (HAVE_extendhisi2)
425: if (HAVE_zero_extendqihi2 && HAVE_extendhisi2)
426: {
427: register rtx temp = gen_reg_rtx (HImode);
1.1.1.2 root 428: emit_unop_insn (CODE_FOR_zero_extendqihi2, temp, from, ZERO_EXTEND);
429: emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND);
1.1 root 430: return;
431: }
432: #endif
433: }
434: else
435: {
436: #ifdef HAVE_extendqisi2
437: if (HAVE_extendqisi2)
438: {
1.1.1.2 root 439: emit_unop_insn (CODE_FOR_extendqisi2, to, from, SIGN_EXTEND);
1.1 root 440: return;
441: }
442: #endif
443: #if defined (HAVE_extendqihi2) && defined (HAVE_extendhisi2)
444: if (HAVE_extendqihi2 && HAVE_extendhisi2)
445: {
446: register rtx temp = gen_reg_rtx (HImode);
1.1.1.2 root 447: emit_unop_insn (CODE_FOR_extendqihi2, temp, from, SIGN_EXTEND);
448: emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND);
1.1 root 449: return;
450: }
451: #endif
452: }
453: abort ();
454: }
455:
456: if (to_mode == HImode && from_mode == QImode)
457: {
458: if (unsignedp)
459: {
460: #ifdef HAVE_zero_extendqihi2
461: if (HAVE_zero_extendqihi2)
462: {
1.1.1.2 root 463: emit_unop_insn (CODE_FOR_zero_extendqihi2, to, from, ZERO_EXTEND);
1.1 root 464: return;
465: }
466: #endif
467: }
468: else
469: {
470: #ifdef HAVE_extendqihi2
471: if (HAVE_extendqihi2)
472: {
1.1.1.2 root 473: emit_unop_insn (CODE_FOR_extendqihi2, to, from, SIGN_EXTEND);
1.1 root 474: return;
475: }
476: #endif
477: }
478: abort ();
479: }
480:
481: /* Now we are truncating an integer to a smaller one.
482: If the result is a temporary, we might as well just copy it,
483: since only the low-order part of the result needs to be valid
484: and it is valid with no change. */
485:
486: if (GET_CODE (to) == REG)
487: {
488: if (GET_CODE (from) == REG)
489: {
490: emit_move_insn (to, gen_lowpart (GET_MODE (to), from));
491: return;
492: }
1.1.1.2 root 493: else if (GET_CODE (from) == SUBREG)
494: {
495: from = copy_rtx (from);
496: /* This is safe since FROM is not more than one word. */
497: PUT_MODE (from, GET_MODE (to));
498: emit_move_insn (to, from);
499: return;
500: }
1.1 root 501: #ifndef BYTES_BIG_ENDIAN
502: else if (GET_CODE (from) == MEM)
503: {
504: register rtx addr = XEXP (from, 0);
1.1.1.2 root 505: if (memory_address_p (GET_MODE (to), addr))
1.1 root 506: {
507: emit_move_insn (to, gen_rtx (MEM, GET_MODE (to), addr));
508: return;
509: }
510: }
511: #endif /* not BYTES_BIG_ENDIAN */
512: }
513:
514: if (from_mode == SImode && to_mode == HImode)
515: {
516: #ifdef HAVE_truncsihi2
517: if (HAVE_truncsihi2)
518: {
1.1.1.2 root 519: emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
1.1 root 520: return;
521: }
522: #endif
523: abort ();
524: }
525:
526: if (from_mode == SImode && to_mode == QImode)
527: {
528: #ifdef HAVE_truncsiqi2
529: if (HAVE_truncsiqi2)
530: {
1.1.1.2 root 531: emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
1.1 root 532: return;
533: }
534: #endif
535: abort ();
536: }
537:
538: if (from_mode == HImode && to_mode == QImode)
539: {
540: #ifdef HAVE_trunchiqi2
541: if (HAVE_trunchiqi2)
542: {
1.1.1.2 root 543: emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
1.1 root 544: return;
545: }
546: #endif
547: abort ();
548: }
1.1.1.2 root 549:
550: /* Mode combination is not recognized. */
551: abort ();
1.1 root 552: }
553:
554: /* Return an rtx for a value that would result
555: from converting X to mode MODE.
556: Both X and MODE may be floating, or both integer.
557: UNSIGNEDP is nonzero if X is an unsigned value.
558: This can be done by referring to a part of X in place
559: or by copying to a new temporary with conversion. */
560:
561: rtx
562: convert_to_mode (mode, x, unsignedp)
563: enum machine_mode mode;
564: rtx x;
565: int unsignedp;
566: {
567: register rtx temp;
568: if (mode == GET_MODE (x))
569: return x;
1.1.1.2 root 570: if (integer_mode_p (mode)
571: && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x)))
1.1 root 572: return gen_lowpart (mode, x);
573: temp = gen_reg_rtx (mode);
574: convert_move (temp, x, unsignedp);
575: return temp;
576: }
1.1.1.2 root 577:
578: int
579: integer_mode_p (mode)
580: enum machine_mode mode;
581: {
582: return (int) mode > (int) VOIDmode && (int) mode <= (int) TImode;
583: }
1.1 root 584:
585: /* Generate several move instructions to copy LEN bytes
1.1.1.2 root 586: from block FROM to block TO. (These are MEM rtx's with BLKmode).
587: The caller must pass FROM and TO
1.1 root 588: through protect_from_queue before calling.
589: ALIGN (in bytes) is maximum alignment we can assume. */
590:
591: struct move_by_pieces
592: {
593: rtx to;
1.1.1.2 root 594: rtx to_addr;
1.1 root 595: int autinc_to;
596: int explicit_inc_to;
597: rtx from;
1.1.1.2 root 598: rtx from_addr;
1.1 root 599: int autinc_from;
600: int explicit_inc_from;
601: int len;
602: int offset;
603: int reverse;
604: };
605:
606: static void
1.1.1.2 root 607: move_by_pieces (to, from, len, align)
1.1 root 608: rtx to, from;
609: int len, align;
610: {
611: struct move_by_pieces data;
1.1.1.2 root 612: rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
1.1 root 613:
614: data.offset = 0;
1.1.1.2 root 615: data.to_addr = to_addr;
616: data.from_addr = from_addr;
1.1 root 617: data.to = to;
618: data.from = from;
1.1.1.2 root 619: data.autinc_to
620: = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
621: || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
622: data.autinc_from
623: = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
624: || GET_CODE (from_addr) == POST_INC
625: || GET_CODE (from_addr) == POST_DEC);
1.1 root 626:
627: data.explicit_inc_from = 0;
628: data.explicit_inc_to = 0;
1.1.1.2 root 629: data.reverse
630: = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
1.1 root 631: if (data.reverse) data.offset = len;
632: data.len = len;
633:
634: /* If copying requires more than two move insns,
635: copy addresses to registers (to make displacements shorter)
636: and use post-increment if available. */
637: if (!(data.autinc_from && data.autinc_to)
638: && move_by_pieces_ninsns (len, align) > 2)
639: {
640: #ifdef HAVE_PRE_DECREMENT
641: if (data.reverse && ! data.autinc_from)
642: {
1.1.1.2 root 643: data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
1.1 root 644: data.autinc_from = 1;
645: data.explicit_inc_from = -1;
646: }
647: #endif
648: #ifdef HAVE_POST_INCREMENT
649: if (! data.autinc_from)
650: {
1.1.1.2 root 651: data.from_addr = copy_addr_to_reg (from_addr);
1.1 root 652: data.autinc_from = 1;
653: data.explicit_inc_from = 1;
654: }
655: #endif
1.1.1.2 root 656: if (!data.autinc_from && CONSTANT_P (from_addr))
657: data.from_addr = copy_addr_to_reg (from_addr);
1.1 root 658: #ifdef HAVE_PRE_DECREMENT
659: if (data.reverse && ! data.autinc_to)
660: {
1.1.1.2 root 661: data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
1.1 root 662: data.autinc_to = 1;
663: data.explicit_inc_to = -1;
664: }
665: #endif
666: #ifdef HAVE_POST_INCREMENT
667: if (! data.reverse && ! data.autinc_to)
668: {
1.1.1.2 root 669: data.to_addr = copy_addr_to_reg (to_addr);
1.1 root 670: data.autinc_to = 1;
671: data.explicit_inc_to = 1;
672: }
673: #endif
1.1.1.2 root 674: if (!data.autinc_to && CONSTANT_P (to_addr))
675: data.to_addr = copy_addr_to_reg (to_addr);
1.1 root 676: }
677:
678: #ifdef STRICT_ALIGNMENT
1.1.1.2 root 679: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1 root 680: align = MOVE_MAX;
681: #else
682: align = MOVE_MAX;
683: #endif
684:
685: #ifdef HAVE_movti
686: if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
687: move_by_pieces_1 (gen_movti, TImode, &data);
688: #endif
689: #ifdef HAVE_movdi
690: if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
691: move_by_pieces_1 (gen_movdi, DImode, &data);
692: #endif
1.1.1.2 root 693: #ifdef HAVE_movsi
1.1 root 694: if (align >= GET_MODE_SIZE (SImode))
695: move_by_pieces_1 (gen_movsi, SImode, &data);
1.1.1.2 root 696: #endif
697: #ifdef HAVE_movhi
698: if (HAVE_movhi && align >= GET_MODE_SIZE (HImode))
1.1 root 699: move_by_pieces_1 (gen_movhi, HImode, &data);
1.1.1.2 root 700: #endif
701: #ifdef HAVE_movqi
1.1 root 702: move_by_pieces_1 (gen_movqi, QImode, &data);
1.1.1.2 root 703: #else
704: movqi instruction required in machine description
705: #endif
1.1 root 706: }
707:
708: /* Return number of insns required to move L bytes by pieces.
709: ALIGN (in bytes) is maximum alignment we can assume. */
710:
1.1.1.2 root 711: static int
1.1 root 712: move_by_pieces_ninsns (l, align)
713: unsigned int l;
714: int align;
715: {
716: register int n_insns = 0;
717:
718: #ifdef STRICT_ALIGNMENT
1.1.1.2 root 719: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1 root 720: align = MOVE_MAX;
721: #else
722: align = MOVE_MAX;
723: #endif
724:
725: #ifdef HAVE_movti
726: if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
727: n_insns += l / GET_MODE_SIZE (TImode), l %= GET_MODE_SIZE (TImode);
728: #endif
729: #ifdef HAVE_movdi
730: if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
731: n_insns += l / GET_MODE_SIZE (DImode), l %= GET_MODE_SIZE (DImode);
732: #endif
1.1.1.2 root 733: #ifdef HAVE_movsi
1.1 root 734: if (HAVE_movsi && align >= GET_MODE_SIZE (SImode))
735: n_insns += l / GET_MODE_SIZE (SImode), l %= GET_MODE_SIZE (SImode);
1.1.1.2 root 736: #endif
737: #ifdef HAVE_movhi
1.1 root 738: if (HAVE_movhi && align >= GET_MODE_SIZE (HImode))
739: n_insns += l / GET_MODE_SIZE (HImode), l %= GET_MODE_SIZE (HImode);
1.1.1.2 root 740: #endif
1.1 root 741: n_insns += l;
742:
743: return n_insns;
744: }
745:
746: /* Subroutine of move_by_pieces. Move as many bytes as appropriate
747: with move instructions for mode MODE. GENFUN is the gen_... function
748: to make a move insn for that mode. DATA has all the other info. */
749:
1.1.1.2 root 750: static void
1.1 root 751: move_by_pieces_1 (genfun, mode, data)
752: rtx (*genfun) ();
753: enum machine_mode mode;
754: struct move_by_pieces *data;
755: {
756: register int size = GET_MODE_SIZE (mode);
757: register rtx to1, from1;
758:
1.1.1.2 root 759: #define add_offset(FLAG,X) \
760: (FLAG ? (X) : plus_constant ((X), data->offset))
1.1 root 761:
762: while (data->len >= size)
763: {
1.1.1.2 root 764: if (data->reverse) data->offset -= size;
1.1 root 765:
1.1.1.2 root 766: to1 = change_address (data->to, mode,
767: add_offset (data->autinc_to, data->to_addr));
768: from1 = change_address (data->from, mode,
769: add_offset (data->autinc_from, data->from_addr));
1.1 root 770:
771: #ifdef HAVE_PRE_DECREMENT
772: if (data->explicit_inc_to < 0)
1.1.1.2 root 773: emit_insn (gen_sub2_insn (data->to_addr,
1.1 root 774: gen_rtx (CONST_INT, VOIDmode, size)));
775: if (data->explicit_inc_from < 0)
1.1.1.2 root 776: emit_insn (gen_sub2_insn (data->from_addr,
1.1 root 777: gen_rtx (CONST_INT, VOIDmode, size)));
778: #endif
779:
1.1.1.5 root 780: emit_insn ((*genfun) (to1, from1));
1.1 root 781: #ifdef HAVE_POST_INCREMENT
782: if (data->explicit_inc_to > 0)
1.1.1.2 root 783: emit_insn (gen_add2_insn (data->to_addr,
1.1 root 784: gen_rtx (CONST_INT, VOIDmode, size)));
785: if (data->explicit_inc_from > 0)
1.1.1.2 root 786: emit_insn (gen_add2_insn (data->from_addr,
1.1 root 787: gen_rtx (CONST_INT, VOIDmode, size)));
788: #endif
789:
790: if (! data->reverse) data->offset += size;
1.1.1.2 root 791:
1.1 root 792: data->len -= size;
793: }
794: }
795:
796: /* Emit code to move a block Y to a block X.
797: This may be done with string-move instructions,
798: with multiple scalar move instructions, or with a library call.
799:
800: Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
801: with mode BLKmode.
802: SIZE is an rtx that says how long they are.
803: ALIGN is the maximum alignment we can assume they have,
804: measured in bytes. */
805:
806: static void
807: emit_block_move (x, y, size, align)
808: rtx x, y;
809: rtx size;
810: int align;
811: {
812: if (GET_MODE (x) != BLKmode)
813: abort ();
814:
815: if (GET_MODE (y) != BLKmode)
816: abort ();
817:
818: x = protect_from_queue (x, 1);
819: y = protect_from_queue (y, 0);
820:
1.1.1.2 root 821: if (GET_CODE (x) != MEM)
1.1 root 822: abort ();
1.1.1.2 root 823: if (GET_CODE (y) != MEM)
1.1 root 824: abort ();
825: if (size == 0)
826: abort ();
827:
828: if (GET_CODE (size) == CONST_INT
829: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
830: < MOVE_RATIO))
1.1.1.2 root 831: move_by_pieces (x, y, INTVAL (size), align);
1.1 root 832: else
833: {
834: #ifdef HAVE_movstrsi
835: if (HAVE_movstrsi)
836: {
837: emit_insn (gen_movstrsi (x, y, size));
838: return;
839: }
840: #endif
841: #ifdef HAVE_movstrhi
842: if (HAVE_movstrhi
843: && GET_CODE (size) == CONST_INT
844: && ((unsigned) INTVAL (size)
1.1.1.5 root 845: < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
1.1 root 846: {
847: emit_insn (gen_movstrhi (x, y, size));
848: return;
849: }
850: #endif
1.1.1.5 root 851: #ifdef HAVE_movstrqi
852: if (HAVE_movstrqi
853: && GET_CODE (size) == CONST_INT
854: && ((unsigned) INTVAL (size)
855: < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
856: {
857: emit_insn (gen_movstrqi (x, y, size));
858: return;
859: }
860: #endif
1.1.1.2 root 861:
862: #ifdef TARGET_MEM_FUNCTIONS
863: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"),
864: VOIDmode, 3, XEXP (x, 0), Pmode,
865: XEXP (y, 0), Pmode,
866: size, Pmode);
867: #else
1.1 root 868: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
1.1.1.2 root 869: VOIDmode, 3, XEXP (y, 0), Pmode,
870: XEXP (x, 0), Pmode,
1.1 root 871: size, Pmode);
1.1.1.2 root 872: #endif
873: }
874: }
875:
876: /* Copy all or part of a BLKmode value X into registers starting at REGNO.
877: The number of registers to be filled is NREGS. */
878:
879: static void
880: move_block_to_reg (regno, x, nregs)
881: int regno;
882: rtx x;
883: int nregs;
884: {
885: int i;
886: if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx)
887: x = force_const_double_mem (x);
888: for (i = 0; i < nregs; i++)
889: {
890: if (GET_CODE (x) == REG)
891: emit_move_insn (gen_rtx (REG, SImode, regno + i),
892: gen_rtx (SUBREG, SImode, x, i));
893: else if (x == dconst0_rtx)
894: emit_move_insn (gen_rtx (REG, SImode, regno + i),
895: const0_rtx);
896: else
897: emit_move_insn (gen_rtx (REG, SImode, regno + i),
898: gen_rtx (MEM, SImode,
899: plus_constant (XEXP (x, 0),
900: i * GET_MODE_SIZE (SImode))));
901: }
902: }
903:
904: /* Copy all or part of a BLKmode value X out of registers starting at REGNO.
905: The number of registers to be filled is NREGS. */
906:
907: void
908: move_block_from_reg (regno, x, nregs)
909: int regno;
910: rtx x;
911: int nregs;
912: {
913: int i;
914: for (i = 0; i < nregs; i++)
915: {
916: if (GET_CODE (x) == REG)
917: emit_move_insn (gen_rtx (SUBREG, SImode, x, i),
918: gen_rtx (REG, SImode, regno + i));
919: else
920: emit_move_insn (gen_rtx (MEM, SImode,
921: plus_constant (XEXP (x, 0),
922: i * GET_MODE_SIZE (SImode))),
923: gen_rtx (REG, SImode, regno + i));
1.1 root 924: }
925: }
1.1.1.2 root 926:
927: /* Mark NREGS consecutive regs, starting at REGNO, as being live now. */
928:
929: static void
930: use_regs (regno, nregs)
931: int regno;
932: int nregs;
933: {
934: int i;
935: for (i = 0; i < nregs; i++)
936: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, regno + i)));
937: }
1.1 root 938:
1.1.1.2 root 939: /* Write zeros through the storage of OBJECT.
940: If OBJECT has BLKmode, SIZE is its length in bytes. */
941:
942: void
943: clear_storage (object, size)
944: rtx object;
945: int size;
946: {
947: if (GET_MODE (object) == BLKmode)
948: {
949: #ifdef TARGET_MEM_FUNCTIONS
950: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memset"),
951: VOIDmode, 3,
952: XEXP (object, 0), Pmode, const0_rtx, Pmode,
953: gen_rtx (CONST_INT, VOIDmode, size), Pmode);
954: #else
955: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bzero"),
956: VOIDmode, 2,
957: XEXP (object, 0), Pmode,
958: gen_rtx (CONST_INT, VOIDmode, size), Pmode);
959: #endif
960: }
961: else
962: emit_move_insn (object, const0_rtx, 0);
963: }
964:
1.1 root 965: /* Generate code to copy Y into X.
966: Both Y and X must have the same mode, except that
967: Y can be a constant with VOIDmode.
1.1.1.2 root 968: This mode cannot be BLKmode; use emit_block_move for that.
1.1 root 969:
1.1.1.2 root 970: Return the last instruction emitted. */
971:
972: rtx
1.1 root 973: emit_move_insn (x, y)
974: rtx x, y;
975: {
976: enum machine_mode mode = GET_MODE (x);
977: x = protect_from_queue (x, 1);
978: y = protect_from_queue (y, 0);
979:
1.1.1.3 root 980: if ((CONSTANT_P (y) || GET_CODE (y) == CONST_DOUBLE)
981: && ! LEGITIMATE_CONSTANT_P (y))
1.1.1.2 root 982: y = force_const_mem (mode, y);
983:
1.1 root 984: if (mode == BLKmode)
985: abort ();
1.1.1.2 root 986: if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1.1.1.6 root 987: return
1.1.1.2 root 988: emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
989: #if 0
990: /* It turns out you get much better optimization (in cse and flow)
991: if you define movdi and movdf instruction patterns
992: even if they must turn into multiple assembler instructions. */
1.1 root 993: else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (SImode))
994: {
995: register int count = GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode);
996: register int i;
1.1.1.2 root 997: if (GET_CODE (y) == CONST_DOUBLE && y != dconst0_rtx)
998: y = force_const_double_mem (y);
1.1 root 999: for (i = 0; i < count; i++)
1000: {
1001: rtx x1, y1;
1002: if (GET_CODE (x) == REG)
1003: x1 = gen_rtx (SUBREG, SImode, x, i);
1004: else
1005: x1 = gen_rtx (MEM, SImode,
1006: memory_address (SImode,
1007: plus_constant (XEXP (x, 0),
1008: i * GET_MODE_SIZE (SImode))));
1009: if (GET_CODE (y) == REG)
1010: y1 = gen_rtx (SUBREG, SImode, y, i);
1.1.1.2 root 1011: else if (y == dconst0_rtx)
1012: y1 = const0_rtx;
1.1 root 1013: else
1014: y1 = gen_rtx (MEM, SImode,
1015: memory_address (SImode,
1016: plus_constant (XEXP (y, 0),
1017: i * GET_MODE_SIZE (SImode))));
1018: emit_insn (gen_movsi (protect_from_queue (x1, 1), protect_from_queue (y1, 0)));
1019: }
1020: }
1.1.1.2 root 1021: #endif
1.1 root 1022: else
1023: abort ();
1024: }
1025:
1026: /* Pushing data onto the stack. */
1027:
1028: /* Push a block of length SIZE (perhaps variable)
1029: and return an rtx to address the beginning of the block.
1.1.1.4 root 1030: Note that it is not possible for the value returned to be a QUEUED.
1031: The value may be stack_pointer_rtx.
1032:
1.1.1.7 ! root 1033: The value we return does take account of STACK_POINTER_OFFSET. */
1.1 root 1034:
1.1.1.7 ! root 1035: rtx
1.1 root 1036: push_block (size)
1037: rtx size;
1038: {
1039: register rtx temp;
1.1.1.2 root 1040: if (CONSTANT_P (size) || GET_CODE (size) == REG)
1041: anti_adjust_stack (size);
1042: else
1043: anti_adjust_stack (copy_to_mode_reg (Pmode, size));
1.1.1.6 root 1044:
1.1 root 1045: #ifdef STACK_GROWS_DOWNWARD
1.1.1.2 root 1046: temp = stack_pointer_rtx;
1.1 root 1047: #else
1048: temp = gen_rtx (PLUS, Pmode,
1.1.1.2 root 1049: stack_pointer_rtx,
1.1.1.7 ! root 1050: negate_rtx (size));
1.1 root 1051: if (GET_CODE (size) != CONST_INT)
1052: temp = force_operand (temp, 0);
1053: #endif
1.1.1.7 ! root 1054:
! 1055: #ifdef STACK_POINTER_OFFSET
! 1056: temp = plus_constant (temp, STACK_POINTER_OFFSET);
! 1057: #endif /* STACK_POINTER_OFFSET */
! 1058:
1.1 root 1059: return memory_address (QImode, temp);
1060: }
1061:
1062: static rtx
1063: gen_push_operand ()
1064: {
1065: return gen_rtx (
1066: #ifdef STACK_GROWS_DOWNWARD
1067: PRE_DEC,
1068: #else
1069: PRE_INC,
1070: #endif
1071: Pmode,
1.1.1.2 root 1072: stack_pointer_rtx);
1.1 root 1073: }
1074:
1075: /* Generate code to push X onto the stack, assuming it has mode MODE.
1076: MODE is redundant except when X is a CONST_INT (since they don't
1077: carry mode info).
1078: SIZE is an rtx for the size of data to be copied (in bytes),
1079: needed only if X is BLKmode.
1.1.1.2 root 1080: ALIGN (in bytes) is maximum alignment we can assume.
1081:
1082: If PARTIAL is nonzero, then copy that many of the first words
1083: of X into registers starting with REG, and push the rest of X.
1084: The amount of space pushed is decreased by PARTIAL words,
1085: rounded *down* to a multiple of PARM_BOUNDARY.
1086: REG must be a hard register in this case.
1087:
1088: EXTRA is the amount in bytes of extra space to leave next to this arg.
1089:
1090: On a machine that lacks real push insns, ARGS_ADDR is the address of
1091: the bottom of the argument block for this call. We use indexing off there
1092: to store the arg. On machines with push insns, ARGS_ADDR is 0.
1093:
1094: ARGS_SO_FAR is the size of args previously pushed for this call. */
1.1 root 1095:
1096: static void
1.1.1.2 root 1097: emit_push_insn (x, mode, size, align, partial, reg, extra, args_addr, args_so_far)
1.1 root 1098: register rtx x;
1099: enum machine_mode mode;
1100: rtx size;
1101: int align;
1.1.1.2 root 1102: int partial;
1103: rtx reg;
1104: int extra;
1105: rtx args_addr;
1106: rtx args_so_far;
1.1 root 1107: {
1108: rtx xinner;
1.1.1.6 root 1109: enum direction stack_direction
1110: #ifdef STACK_GROWS_DOWNWARD
1111: = downward;
1112: #else
1113: = upward;
1114: #endif
1115:
1116: /* Decide where to pad the argument: `downward' for below,
1117: `upward' for above, or `none' for don't pad it.
1118: Default is below for small data on big-endian machines; else above. */
1119: enum direction where_pad = FUNCTION_ARG_PADDING (mode, size);
1.1 root 1120:
1121: xinner = x = protect_from_queue (x, 0);
1122:
1.1.1.2 root 1123: /* If part should go in registers, copy that part
1124: into the appropriate registers. */
1125: if (partial > 0)
1126: move_block_to_reg (REGNO (reg), x, partial);
1127:
1.1.1.6 root 1128: if (extra)
1129: {
1130: if (args_addr == 0)
1131: {
1132: /* Push padding now if padding above and stack grows down,
1133: or if padding below and stack grows up. */
1134: if (where_pad != none && where_pad != stack_direction)
1135: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra));
1136: }
1137: else
1138: {
1139: /* If space already allocated, just adjust the address we use. */
1140: if (where_pad == downward)
1141: args_so_far = plus_constant (args_so_far, extra);
1142: }
1143: }
1.1 root 1144:
1145: if (mode == BLKmode)
1146: {
1147: register rtx temp;
1.1.1.2 root 1148: int used = partial * UNITS_PER_WORD;
1149: int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
1150:
1151: used -= used % (PARM_BOUNDARY / BITS_PER_UNIT);
1152:
1.1 root 1153: if (size == 0)
1154: abort ();
1155:
1.1.1.2 root 1156: if (partial != 0)
1157: xinner = change_address (xinner, BLKmode,
1158: plus_constant (XEXP (xinner, 0), used));
1159:
1160: #ifdef PUSH_ROUNDING
1161: /* Do it with several push insns if that doesn't take lots of insns
1162: and if there is no difficulty with push insns that skip bytes
1163: on the stack for alignment purposes. */
1164: if (args_addr == 0
1165: && GET_CODE (size) == CONST_INT
1166: && args_addr == 0
1167: && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align)
1168: < MOVE_RATIO)
1169: && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
1170: move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner,
1171: INTVAL (size) - used, align);
1.1 root 1172: else
1.1.1.2 root 1173: #endif /* PUSH_ROUNDING */
1.1 root 1174: {
1.1.1.2 root 1175: /* Otherwise make space on the stack and copy the data
1176: to the address of that space. */
1177:
1178: /* First deduct part put into registers from the size we need. */
1179: if (partial != 0)
1180: {
1181: if (GET_CODE (size) == CONST_INT)
1182: size = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - used);
1183: else
1184: size = expand_binop (GET_MODE (size), sub_optab, size,
1185: gen_rtx (CONST_INT, VOIDmode, used),
1186: 0, 0, OPTAB_LIB_WIDEN);
1187: }
1188:
1189: /* Get the address of the stack space. */
1190: if (! args_addr)
1191: temp = push_block (size);
1192: else if (GET_CODE (args_so_far) == CONST_INT)
1193: temp = memory_address (BLKmode,
1194: plus_constant (args_addr,
1195: offset + INTVAL (args_so_far)));
1196: else
1197: temp = memory_address (BLKmode,
1198: plus_constant (gen_rtx (PLUS, Pmode,
1199: args_addr, args_so_far),
1200: offset));
1201:
1202:
1203: /* TEMP is the address of the block. Copy the data there. */
1204: if (GET_CODE (size) == CONST_INT
1205: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
1206: < MOVE_RATIO))
1207: {
1208: move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner,
1209: INTVAL (size), align);
1210: return;
1211: }
1.1 root 1212: #ifdef HAVE_movstrsi
1213: if (HAVE_movstrsi)
1214: {
1215: emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), x, size));
1216: return;
1217: }
1218: #endif
1219: #ifdef HAVE_movstrhi
1220: if (HAVE_movstrhi
1221: && GET_CODE (size) == CONST_INT
1222: && ((unsigned) INTVAL (size)
1.1.1.5 root 1223: < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
1.1 root 1224: {
1225: emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp),
1226: x, size));
1227: return;
1228: }
1229: #endif
1.1.1.5 root 1230: #ifdef HAVE_movstrqi
1231: if (HAVE_movstrqi
1232: && GET_CODE (size) == CONST_INT
1233: && ((unsigned) INTVAL (size)
1234: < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
1235: {
1236: emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp),
1237: x, size));
1238: return;
1239: }
1240: #endif
1.1.1.2 root 1241:
1242: if (reg_mentioned_p (stack_pointer_rtx, temp))
1243: {
1244: /* Correct TEMP so it holds what will be a description of
1245: the address to copy to, valid after one arg is pushed. */
1.1.1.5 root 1246: int xsize = GET_MODE_SIZE (Pmode);
1247: #ifdef PUSH_ROUNDING
1248: xsize = PUSH_ROUNDING (xsize);
1249: #endif
1250: xsize = ((xsize + PARM_BOUNDARY / BITS_PER_UNIT - 1)
1251: / (PARM_BOUNDARY / BITS_PER_UNIT)
1252: * (PARM_BOUNDARY / BITS_PER_UNIT));
1.1 root 1253: #ifdef STACK_GROWS_DOWNWARD
1.1.1.4 root 1254: temp = plus_constant (temp, xsize);
1.1 root 1255: #else
1.1.1.6 root 1256: temp = plus_constant (temp, -xsize);
1.1 root 1257: #endif
1.1.1.2 root 1258: }
1259:
1260: /* Make current_args_size nonzero around the library call
1261: to force it to pop the bcopy-arguments right away. */
1262: current_args_size += 1;
1263: #ifdef TARGET_MEM_FUNCTIONS
1264: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"),
1265: VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
1266: size, Pmode);
1267: #else
1.1 root 1268: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
1.1.1.2 root 1269: VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
1.1 root 1270: size, Pmode);
1.1.1.2 root 1271: #endif
1272: current_args_size -= 1;
1.1 root 1273: }
1274: }
1.1.1.2 root 1275: else if (partial > 0)
1.1 root 1276: {
1.1.1.2 root 1277: int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
1278: int i;
1279: int used = partial * UNITS_PER_WORD;
1.1.1.6 root 1280: /* # words of start of argument
1.1.1.2 root 1281: that we must make space for but need not store. */
1282: int skip = partial % (PARM_BOUNDARY / BITS_PER_WORD);
1283: int args_offset = INTVAL (args_so_far);
1284:
1285: /* If we make space by pushing it, we might as well push
1286: the real data. Otherwise, we can leave SKIP nonzero
1287: and leave the space uninitialized. */
1288: if (args_addr == 0)
1289: skip = 0;
1290:
1291: /* Deduct all the rest of PARTIAL words from SIZE in any case.
1292: This is space that we don't even allocate in the stack. */
1293: used -= used % (PARM_BOUNDARY / BITS_PER_UNIT);
1294: size -= used / UNITS_PER_WORD;
1295:
1296: if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx)
1297: x = force_const_double_mem (x);
1298:
1299: #ifndef PUSH_ARGS_REVERSED
1300: for (i = skip; i < size; i++)
1301: #else
1302: for (i = size - 1; i >= skip; i--)
1303: #endif
1304: if (GET_CODE (x) == MEM)
1305: emit_push_insn (gen_rtx (MEM, SImode,
1306: plus_constant (XEXP (x, 0),
1307: i * UNITS_PER_WORD)),
1308: SImode, 0, align, 0, 0, 0, args_addr,
1309: gen_rtx (CONST_INT, VOIDmode,
1310: args_offset + i * UNITS_PER_WORD));
1311: else if (GET_CODE (x) == REG)
1312: emit_push_insn (gen_rtx (SUBREG, SImode, x, i),
1313: SImode, 0, align, 0, 0, 0, args_addr,
1314: gen_rtx (CONST_INT, VOIDmode,
1315: args_offset + i * UNITS_PER_WORD));
1316: else if (x == dconst0_rtx)
1317: emit_push_insn (const0_rtx,
1318: SImode, 0, align, 0, 0, 0, args_addr,
1319: gen_rtx (CONST_INT, VOIDmode,
1320: args_offset + i * UNITS_PER_WORD));
1321: else
1322: abort ();
1.1 root 1323: }
1324: else
1.1.1.2 root 1325: {
1326: rtx addr;
1327: #ifdef PUSH_ROUNDING
1328: if (args_addr == 0)
1329: addr = gen_push_operand ();
1330: else
1331: #endif
1332: if (GET_CODE (args_so_far) == CONST_INT)
1333: addr
1334: = memory_address (mode,
1335: plus_constant (args_addr, INTVAL (args_so_far)));
1336: else
1337: addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr,
1338: args_so_far));
1339:
1340: emit_move_insn (gen_rtx (MEM, mode, addr), x);
1341: }
1342:
1.1.1.6 root 1343: if (extra && args_addr == 0 && where_pad == stack_direction)
1.1.1.2 root 1344: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra));
1.1 root 1345: }
1346:
1347: /* Output a library call to function FUN (a SYMBOL_REF rtx)
1.1.1.2 root 1348: for a value of mode OUTMODE
1.1 root 1349: with NARGS different arguments, passed as alternating rtx values
1350: and machine_modes to convert them to.
1351: The rtx values should have been passed through protect_from_queue already. */
1352:
1353: void
1.1.1.2 root 1354: emit_library_call (va_alist)
1355: va_dcl
1.1 root 1356: {
1.1.1.2 root 1357: register va_list p;
1.1 root 1358: register int args_size = 0;
1359: register int argnum;
1.1.1.2 root 1360: enum machine_mode outmode;
1361: int nargs;
1362: rtx fun;
1363: rtx orgfun;
1364: int inc;
1365: int count;
1366: rtx *regvec;
1367: rtx argblock = 0;
1368: CUMULATIVE_ARGS args_so_far;
1369: struct arg { rtx value; enum machine_mode mode; };
1370: struct arg *argvec;
1371: int old_args_size = current_args_size;
1372:
1373: va_start (p);
1374: orgfun = fun = va_arg (p, rtx);
1375: outmode = va_arg (p, enum machine_mode);
1376: nargs = va_arg (p, int);
1377:
1378: regvec = (rtx *) alloca (nargs * sizeof (rtx));
1379:
1380: /* Copy all the libcall-arguments out of the varargs data
1381: and into a vector ARGVEC. */
1382: argvec = (struct arg *) alloca (nargs * sizeof (struct arg));
1383: for (count = 0; count < nargs; count++)
1384: {
1385: argvec[count].value = va_arg (p, rtx);
1386: argvec[count].mode = va_arg (p, enum machine_mode);
1387: }
1388: va_end (p);
1389:
1390: /* If we have no actual push instructions, make space for all the args
1391: right now. */
1392: #ifndef PUSH_ROUNDING
1393: INIT_CUMULATIVE_ARGS (args_so_far, (tree)0);
1394: for (count = 0; count < nargs; count++)
1395: {
1396: register enum machine_mode mode = argvec[count].mode;
1397: register rtx reg;
1398: register int partial;
1399:
1400: reg = FUNCTION_ARG (args_so_far, mode, 0, 1);
1401: #ifdef FUNCTION_ARG_PARTIAL_NREGS
1402: partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1);
1403: #else
1404: partial = 0;
1405: #endif
1406: if (reg == 0 || partial != 0)
1407: args_size += GET_MODE_SIZE (mode);
1408: if (partial != 0)
1409: args_size -= partial * GET_MODE_SIZE (SImode);
1410: FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1);
1411: }
1412:
1413: if (args_size != 0)
1414: argblock
1415: = push_block (round_push (gen_rtx (CONST_INT, VOIDmode, args_size)));
1416: #endif
1417:
1418: INIT_CUMULATIVE_ARGS (args_so_far, (tree)0);
1419:
1420: #ifdef PUSH_ARGS_REVERSED
1421: inc = -1;
1422: argnum = nargs - 1;
1.1 root 1423: #else
1.1.1.2 root 1424: inc = 1;
1425: argnum = 0;
1.1 root 1426: #endif
1.1.1.2 root 1427: args_size = 0;
1428:
1429: for (count = 0; count < nargs; count++, argnum += inc)
1.1 root 1430: {
1.1.1.2 root 1431: register enum machine_mode mode = argvec[argnum].mode;
1432: register rtx val = argvec[argnum].value;
1433: rtx reg;
1434: int partial;
1435: int arg_size;
1436:
1.1 root 1437: /* Convert the arg value to the mode the library wants. */
1438: /* ??? It is wrong to do it here; must do it earlier
1439: where we know the signedness of the arg. */
1440: if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
1441: {
1442: val = gen_reg_rtx (mode);
1.1.1.2 root 1443: convert_move (val, argvec[argnum].value, 0);
1.1 root 1444: }
1.1.1.2 root 1445: reg = FUNCTION_ARG (args_so_far, mode, 0, 1);
1446: regvec[argnum] = reg;
1447: #ifdef FUNCTION_ARG_PARTIAL_NREGS
1448: partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1);
1449: #else
1450: partial = 0;
1451: #endif
1452:
1453: if (reg != 0 && partial == 0)
1454: emit_move_insn (reg, val);
1455: else
1456: emit_push_insn (val, mode, 0, 0, partial, reg, 0, argblock,
1457: gen_rtx (CONST_INT, VOIDmode, args_size));
1458:
1459: /* Compute size of stack space used by this argument. */
1460: if (reg == 0 || partial != 0)
1461: arg_size = GET_MODE_SIZE (mode);
1462: else
1463: arg_size = 0;
1464: if (partial != 0)
1465: arg_size
1466: -= ((partial * UNITS_PER_WORD)
1467: / (PARM_BOUNDARY / BITS_PER_UNIT)
1468: * (PARM_BOUNDARY / BITS_PER_UNIT));
1469:
1470: args_size += arg_size;
1471: current_args_size += arg_size;
1472: FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1);
1.1 root 1473: }
1474:
1475: emit_queue ();
1.1.1.2 root 1476:
1477: fun = prepare_call_address (fun, 0);
1478:
1479: /* Any regs containing parms remain in use through the call.
1480: ??? This is not quite correct, since it doesn't indicate
1481: that they are in use immediately before the call insn.
1482: Currently that doesn't matter since explicitly-used regs
1483: won't be used for reloading. But if the reloader becomes smarter,
1484: this will have to change somehow. */
1485: for (count = 0; count < nargs; count++)
1486: if (regvec[count] != 0)
1487: emit_insn (gen_rtx (USE, VOIDmode, regvec[count]));
1488:
1489: #ifdef STACK_BOUNDARY
1490: args_size = (args_size + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES;
1491: #endif
1492:
1.1.1.3 root 1493: /* Don't allow popping to be deferred, since then
1494: cse'ing of library calls could delete a call and leave the pop. */
1.1.1.2 root 1495: current_args_size += 1;
1496: emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size,
1497: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
1498: outmode != VOIDmode ? hard_libcall_value (outmode) : 0,
1.1.1.3 root 1499: old_args_size + 1);
1500: current_args_size -= 1;
1.1 root 1501: }
1502:
1503: /* Expand an assignment that stores the value of FROM into TO.
1.1.1.2 root 1504: If WANT_VALUE is nonzero, return an rtx for the value of TO.
1505: (This may contain a QUEUED rtx.)
1506: Otherwise, the returned value is not meaningful.
1507:
1508: SUGGEST_REG is no longer actually used.
1509: It used to mean, copy the value through a register
1510: and return that register, if that is possible.
1511: But now we do this if WANT_VALUE.
1512:
1513: If the value stored is a constant, we return the constant. */
1.1 root 1514:
1515: rtx
1.1.1.2 root 1516: expand_assignment (to, from, want_value, suggest_reg)
1.1 root 1517: tree to, from;
1.1.1.2 root 1518: int want_value;
1519: int suggest_reg;
1.1 root 1520: {
1521: register rtx to_rtx = 0;
1522:
1523: /* Don't crash if the lhs of the assignment was erroneous. */
1524:
1525: if (TREE_CODE (to) == ERROR_MARK)
1526: return expand_expr (from, 0, VOIDmode, 0);
1527:
1528: /* Assignment of a structure component needs special treatment
1.1.1.2 root 1529: if the structure component's rtx is not simply a MEM.
1530: Assignment of an array element at a constant index
1531: has the same problem. */
1532:
1533: if (TREE_CODE (to) == COMPONENT_REF
1534: || (TREE_CODE (to) == ARRAY_REF
1535: && TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST
1536: && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST))
1.1 root 1537: {
1.1.1.2 root 1538: register enum machine_mode mode1;
1539: int bitsize;
1.1 root 1540: int volstruct = 0;
1.1.1.2 root 1541: tree tem = to;
1542: int bitpos = 0;
1543: int unsignedp;
1.1 root 1544:
1.1.1.2 root 1545: if (TREE_CODE (to) == COMPONENT_REF)
1.1 root 1546: {
1547: tree field = TREE_OPERAND (to, 1);
1.1.1.2 root 1548: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
1549: mode1 = DECL_MODE (TREE_OPERAND (to, 1));
1550: unsignedp = TREE_UNSIGNED (field);
1.1 root 1551: }
1.1.1.2 root 1552: else
1.1 root 1553: {
1.1.1.2 root 1554: mode1 = TYPE_MODE (TREE_TYPE (to));
1555: bitsize = GET_MODE_BITSIZE (mode1);
1556: unsignedp = TREE_UNSIGNED (TREE_TYPE (to));
1.1 root 1557: }
1558:
1.1.1.2 root 1559: /* Compute cumulative bit-offset for nested component-refs
1560: and array-refs, and find the ultimate containing object. */
1.1 root 1561:
1.1.1.2 root 1562: while (1)
1.1 root 1563: {
1.1.1.2 root 1564: if (TREE_CODE (tem) == COMPONENT_REF)
1565: {
1566: bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1));
1567: if (TREE_THIS_VOLATILE (tem))
1568: volstruct = 1;
1569: }
1570: else if (TREE_CODE (tem) == ARRAY_REF
1571: && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
1572: && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST)
1573: {
1574: bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1))
1575: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)))
1576: * TYPE_SIZE_UNIT (TREE_TYPE (tem)));
1577: }
1578: else
1579: break;
1580: tem = TREE_OPERAND (tem, 0);
1.1 root 1581: }
1582:
1.1.1.2 root 1583: /* If we are going to use store_bit_field and extract_bit_field,
1584: make sure to_rtx will be safe for multiple use. */
1585: if (mode1 == BImode && want_value)
1586: tem = stabilize_reference (tem);
1.1 root 1587:
1.1.1.2 root 1588: to_rtx = expand_expr (tem, 0, VOIDmode, 0);
1589:
1590: return store_field (to_rtx, bitsize, bitpos, mode1, from,
1591: want_value ? TYPE_MODE (TREE_TYPE (to)) : VOIDmode,
1592: unsignedp);
1.1 root 1593: }
1594:
1595: /* Ordinary treatment. Expand TO to get a REG or MEM rtx.
1596: Don't re-expand if it was expanded already (in COMPONENT_REF case). */
1597:
1598: if (to_rtx == 0)
1599: to_rtx = expand_expr (to, 0, VOIDmode, 0);
1600:
1601: /* Compute FROM and store the value in the rtx we got. */
1602:
1.1.1.2 root 1603: return store_expr (from, to_rtx, want_value);
1.1 root 1604: }
1605:
1606: /* Generate code for computing expression EXP,
1.1.1.2 root 1607: and storing the value into TARGET.
1608: Returns TARGET or an equivalent value.
1609: TARGET may contain a QUEUED rtx.
1.1 root 1610:
1.1.1.2 root 1611: If SUGGEST_REG is nonzero, copy the value through a register
1612: and return that register, if that is possible.
1613:
1614: If the value stored is a constant, we return the constant. */
1615:
1616: rtx
1617: store_expr (exp, target, suggest_reg)
1.1 root 1618: register tree exp;
1619: register rtx target;
1.1.1.2 root 1620: int suggest_reg;
1.1 root 1621: {
1.1.1.2 root 1622: register rtx temp;
1623: int dont_return_target = 0;
1624:
1625: /* Copying a non-constant CONSTRUCTOR needs special treatment. */
1626:
1627: if (TREE_CODE (exp) == CONSTRUCTOR && ! TREE_LITERAL (exp))
1628: {
1629: store_constructor (exp, target);
1630: return target;
1631: }
1632:
1633: if (suggest_reg && GET_CODE (target) == MEM && GET_MODE (target) != BLKmode)
1634: /* If target is in memory and caller wants value in a register instead,
1635: arrange that. Pass TARGET as target for expand_expr so that,
1636: if EXP is another assignment, SUGGEST_REG will be nonzero for it.
1637: We know expand_expr will not use the target in that case. */
1638: {
1639: temp = expand_expr (exp, cse_not_expected ? 0 : target,
1640: GET_MODE (target), 0);
1641: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
1642: temp = copy_to_reg (temp);
1643: dont_return_target = 1;
1644: }
1645: else if (queued_subexp_p (target))
1646: /* If target contains a postincrement, it is not safe
1647: to use as the returned value. It would access the wrong
1648: place by the time the queued increment gets output.
1649: So copy the value through a temporary and use that temp
1650: as the result. */
1651: {
1652: temp = expand_expr (exp, 0, GET_MODE (target), 0);
1653: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
1654: temp = copy_to_reg (temp);
1655: dont_return_target = 1;
1656: }
1657: else
1658: {
1659: temp = expand_expr (exp, target, GET_MODE (target), 0);
1660: /* DO return TARGET if it's a specified hardware register.
1661: expand_return relies on this. */
1662: if (!(target && GET_CODE (target) == REG
1663: && REGNO (target) < FIRST_PSEUDO_REGISTER)
1664: && (CONSTANT_P (temp) || GET_CODE (temp) == CONST_DOUBLE))
1665: dont_return_target = 1;
1666: }
1667:
1668: /* If value was not generated in the target, store it there. */
1669:
1.1 root 1670: if (temp != target && TREE_CODE (exp) != ERROR_MARK)
1671: {
1672: target = protect_from_queue (target, 1);
1673: if (GET_MODE (temp) != GET_MODE (target)
1674: && GET_MODE (temp) != VOIDmode)
1.1.1.2 root 1675: {
1676: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
1677: if (dont_return_target)
1678: temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
1679: else
1680: convert_move (target, temp, unsignedp);
1681: }
1682:
1.1 root 1683: else if (GET_MODE (temp) == BLKmode)
1684: emit_block_move (target, temp, expr_size (exp),
1685: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
1686: else
1687: emit_move_insn (target, temp);
1688: }
1.1.1.2 root 1689: if (dont_return_target)
1690: return temp;
1.1 root 1691: return target;
1692: }
1693:
1.1.1.2 root 1694: /* Store the value of constructor EXP into the rtx TARGET.
1695: TARGET is either a REG or a MEM. */
1.1 root 1696:
1.1.1.2 root 1697: static void
1698: store_constructor (exp, target)
1699: tree exp;
1700: rtx target;
1.1 root 1701: {
1.1.1.7 ! root 1702: /* Don't try copying piece by piece into a hard register
! 1703: since that is vulnerable to being clobbered by EXP.
! 1704: Instead, construct in a pseudo register and then copy it all. */
! 1705: if (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
! 1706: {
! 1707: rtx temp = gen_reg_rtx (GET_MODE (target));
! 1708: store_constructor (exp, temp);
! 1709: emit_move_insn (target, temp);
! 1710: return;
! 1711: }
! 1712:
1.1.1.2 root 1713: if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
1.1 root 1714: {
1.1.1.2 root 1715: register tree elt;
1.1 root 1716:
1.1.1.2 root 1717: /* If the constructor has fewer fields than the structure,
1718: clear the whole structure first. */
1.1 root 1719:
1.1.1.2 root 1720: if (list_length (CONSTRUCTOR_ELTS (exp))
1721: != list_length (TYPE_FIELDS (TREE_TYPE (exp))))
1722: clear_storage (target, int_size_in_bytes (TREE_TYPE (exp)));
1723: else
1724: /* Inform later passes that the old value is dead. */
1725: emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1726:
1727: /* Store each element of the constructor into
1728: the corresponding field of TARGET. */
1729:
1730: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
1731: {
1732: register tree field = TREE_PURPOSE (elt);
1733: register enum machine_mode mode;
1734: int bitsize;
1735: int bitpos;
1736: int unsignedp;
1737:
1738: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
1739: mode = DECL_MODE (field);
1740: unsignedp = TREE_UNSIGNED (field);
1741:
1742: bitpos = DECL_OFFSET (field);
1743:
1744: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
1745: VOIDmode, 0);
1746: }
1747: }
1748: else if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
1749: {
1750: register tree elt;
1751: register int i;
1752: tree domain = TYPE_DOMAIN (TREE_TYPE (exp));
1753: int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
1754: int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
1755: tree elttype = TREE_TYPE (TREE_TYPE (exp));
1756:
1757: /* If the constructor has fewer fields than the structure,
1758: clear the whole structure first. */
1759:
1760: if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1)
1761: clear_storage (target, maxelt - minelt + 1);
1762: else
1763: /* Inform later passes that the old value is dead. */
1764: emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1765:
1766: /* Store each element of the constructor into
1767: the corresponding element of TARGET, determined
1768: by counting the elements. */
1769: for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
1770: elt;
1771: elt = TREE_CHAIN (elt), i++)
1772: {
1773: register enum machine_mode mode;
1774: int bitsize;
1775: int bitpos;
1776: int unsignedp;
1777:
1778: mode = TYPE_MODE (elttype);
1779: bitsize = GET_MODE_BITSIZE (mode);
1780: unsignedp = TREE_UNSIGNED (elttype);
1781:
1782: bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype))
1783: * TYPE_SIZE_UNIT (elttype));
1784:
1785: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
1786: VOIDmode, 0);
1787: }
1788: }
1789: }
1790:
1791: /* Store the value of EXP (an expression tree)
1792: into a subfield of TARGET which has mode MODE and occupies
1793: BITSIZE bits, starting BITPOS bits from the start of TARGET.
1794:
1795: If VALUE_MODE is VOIDmode, return nothing in particular.
1796: UNSIGNEDP is not used in this case.
1797:
1798: Otherwise, return an rtx for the value stored. This rtx
1799: has mode VALUE_MODE if that is convenient to do.
1800: In this case, UNSIGNEDP must be nonzero if the value is an unsigned type. */
1801:
1802: static rtx
1803: store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp)
1804: rtx target;
1805: int bitsize, bitpos;
1806: enum machine_mode mode;
1807: tree exp;
1808: enum machine_mode value_mode;
1809: int unsignedp;
1810: {
1811: /* If the structure is in a register or if the component
1812: is a bit field, we cannot use addressing to access it.
1813: Use bit-field techniques or SUBREG to store in it. */
1814:
1815: if (mode == BImode || GET_CODE (target) == REG
1816: || GET_CODE (target) == SUBREG)
1817: {
1818: store_bit_field (target, bitsize, bitpos,
1819: mode,
1820: expand_expr (exp, 0, VOIDmode, 0));
1821: if (value_mode != VOIDmode)
1822: return extract_bit_field (target, bitsize, bitpos, unsignedp,
1823: 0, value_mode, 0);
1824: return const0_rtx;
1825: }
1826: else
1827: {
1828: rtx addr = XEXP (target, 0);
1829: rtx to_rtx;
1830:
1831: /* If a value is wanted, it must be the lhs;
1832: so make the address stable for multiple use. */
1833:
1834: if (value_mode != VOIDmode && GET_CODE (addr) != REG
1835: && ! CONSTANT_ADDRESS_P (addr))
1836: addr = copy_to_reg (addr);
1837:
1838: /* Now build a reference to just the desired component. */
1839:
1840: to_rtx = change_address (target, mode,
1841: plus_constant (addr,
1842: (bitpos / BITS_PER_UNIT)));
1843: to_rtx->in_struct = 1;
1844:
1845: return store_expr (exp, to_rtx, value_mode != VOIDmode);
1846: }
1847: }
1848:
1849: /* Given an rtx VALUE that may contain additions and multiplications,
1850: return an equivalent value that just refers to a register or memory.
1851: This is done by generating instructions to perform the arithmetic
1852: and returning a pseudo-register containing the value. */
1853:
1854: rtx
1855: force_operand (value, target)
1856: rtx value, target;
1857: {
1858: register optab binoptab = 0;
1859: register rtx op2;
1860: /* Use subtarget as the target for operand 0 of a binary operation. */
1861: register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
1862:
1863: if (GET_CODE (value) == PLUS)
1864: binoptab = add_optab;
1865: else if (GET_CODE (value) == MINUS)
1866: binoptab = sub_optab;
1867: else if (GET_CODE (value) == MULT)
1868: {
1869: op2 = XEXP (value, 1);
1870: if (!CONSTANT_P (op2)
1871: && !(GET_CODE (op2) == REG && op2 != subtarget))
1872: subtarget = 0;
1873: return expand_mult (GET_MODE (value),
1874: force_operand (XEXP (value, 0), subtarget),
1875: force_operand (op2, 0),
1876: target, 0);
1877: }
1878:
1879: if (binoptab)
1880: {
1881: op2 = XEXP (value, 1);
1882: if (!CONSTANT_P (op2)
1883: && !(GET_CODE (op2) == REG && op2 != subtarget))
1884: subtarget = 0;
1885: if (binoptab == sub_optab
1886: && GET_CODE (op2) == CONST_INT && INTVAL (op2) < 0)
1887: {
1888: binoptab = add_optab;
1889: op2 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op2));
1890: }
1891: return expand_binop (GET_MODE (value), binoptab,
1892: force_operand (XEXP (value, 0), subtarget),
1893: force_operand (op2, 0),
1894: target, 0, OPTAB_LIB_WIDEN);
1895: /* We give UNSIGNEP = 0 to expand_binop
1896: because the only operations we are expanding here are signed ones. */
1897: }
1898: return value;
1899: }
1900:
1901: /* expand_expr: generate code for computing expression EXP.
1902: An rtx for the computed value is returned.
1903:
1904: The value may be stored in TARGET if TARGET is nonzero.
1.1 root 1905: TARGET is just a suggestion; callers must assume that
1906: the rtx returned may not be the same as TARGET.
1907:
1.1.1.2 root 1908: If TARGET is CONST0_RTX, it means that the value will be ignored.
1909:
1.1 root 1910: If TMODE is not VOIDmode, it suggests generating the
1911: result in mode TMODE. But this is done only when convenient.
1912: Otherwise, TMODE is ignored and the value generated in its natural mode.
1913: TMODE is just a suggestion; callers must assume that
1914: the rtx returned may not have mode TMODE.
1915:
1.1.1.2 root 1916: If MODIFIER is EXPAND_SUM then when EXP is an addition
1.1 root 1917: we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
1918: or a nest of (PLUS ...) and (MINUS ...) where the terms are
1919: products as above, or REG or MEM, or constant.
1.1.1.2 root 1920: Ordinarily in such cases we would output mul or add instructions
1921: and then return a pseudo reg containing the sum.
1922:
1923: If MODIFIER is EXPAND_CONST_ADDRESS then it is ok to return
1924: a MEM rtx whose address is a constant that isn't a legitimate address. */
1.1 root 1925:
1926: /* Subroutine of expand_expr:
1927: return the target to use when recursively expanding
1928: the first operand of an arithmetic operation. */
1929:
1930: static rtx
1931: validate_subtarget (subtarget, otherop)
1932: rtx subtarget;
1933: tree otherop;
1934: {
1935: if (TREE_LITERAL (otherop))
1936: return subtarget;
1937: if (TREE_CODE (otherop) == VAR_DECL
1938: && DECL_RTL (otherop) != subtarget)
1939: return subtarget;
1940: return 0;
1941: }
1942:
1943: rtx
1.1.1.2 root 1944: expand_expr (exp, target, tmode, modifier)
1.1 root 1945: register tree exp;
1946: rtx target;
1947: enum machine_mode tmode;
1.1.1.2 root 1948: enum expand_modifier modifier;
1.1 root 1949: {
1950: register rtx op0, op1, temp;
1951: tree type = TREE_TYPE (exp);
1952: register enum machine_mode mode = TYPE_MODE (type);
1953: register enum tree_code code = TREE_CODE (exp);
1.1.1.2 root 1954: optab this_optab;
1.1 root 1955: int negate_1;
1956: /* Use subtarget as the target for operand 0 of a binary operation. */
1957: rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
1.1.1.2 root 1958: rtx original_target = target;
1959: int ignore = target == const0_rtx;
1960:
1.1.1.7 ! root 1961: /* Don't use hard regs as subtargets, because the combiner
! 1962: can only handle pseudo regs. */
! 1963: if (subtarget && REGNO (subtarget) < FIRST_PSEUDO_REGISTER)
! 1964: subtarget = 0;
! 1965:
1.1.1.2 root 1966: if (ignore) target = 0, original_target = 0;
1.1 root 1967:
1968: /* If will do cse, generate all results into registers
1969: since 1) that allows cse to find more things
1970: and 2) otherwise cse could produce an insn the machine
1971: cannot support. */
1972:
1973: if (! cse_not_expected && mode != BLKmode)
1974: target = subtarget;
1975:
1.1.1.2 root 1976: /* No sense saving up arithmetic to be done
1977: if it's all in the wrong mode to form part of an address.
1978: And force_operand won't know whether to sign-extend or zero-extend. */
1979:
1980: if (mode != Pmode && modifier == EXPAND_SUM)
1.1.1.6 root 1981: modifier = EXPAND_NORMAL;
1.1.1.2 root 1982:
1.1 root 1983: switch (code)
1984: {
1.1.1.4 root 1985: case PARM_DECL:
1986: if (DECL_RTL (exp) == 0)
1987: {
1988: error_with_decl (exp, "prior parameter's size depends on `%s'");
1989: return const0_rtx;
1990: }
1991:
1.1 root 1992: case FUNCTION_DECL:
1993: case VAR_DECL:
1994: case RESULT_DECL:
1995: if (DECL_RTL (exp) == 0)
1996: abort ();
1997: if (GET_CODE (DECL_RTL (exp)) == SYMBOL_REF)
1998: abort ();
1.1.1.2 root 1999: if (GET_CODE (DECL_RTL (exp)) == MEM
2000: && modifier != EXPAND_CONST_ADDRESS)
2001: {
2002: /* DECL_RTL probably contains a constant address.
2003: On RISC machines where a constant address isn't valid,
2004: make some insns to get that address into a register. */
1.1.1.7 ! root 2005: if (!memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0))
! 2006: || (flag_force_addr
! 2007: && CONSTANT_ADDRESS_P (XEXP (DECL_RTL (exp), 0))))
1.1.1.2 root 2008: return change_address (DECL_RTL (exp), VOIDmode,
2009: copy_rtx (XEXP (DECL_RTL (exp), 0)));
2010: }
1.1 root 2011: return DECL_RTL (exp);
2012:
2013: case INTEGER_CST:
1.1.1.7 ! root 2014: if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT)
! 2015: return gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (exp));
! 2016: /* If optimized, generate immediate CONST_DOUBLE
! 2017: which will be turned into memory by reload if necessary. */
! 2018: if (!cse_not_expected)
! 2019: return immed_double_const (TREE_INT_CST_LOW (exp),
! 2020: TREE_INT_CST_HIGH (exp),
! 2021: mode);
! 2022: output_constant_def (exp);
! 2023: return TREE_CST_RTL (exp);
1.1 root 2024:
2025: case CONST_DECL:
2026: return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
2027:
2028: case REAL_CST:
2029: if (TREE_CST_RTL (exp))
2030: return TREE_CST_RTL (exp);
1.1.1.7 ! root 2031: /* If optimized, generate immediate CONST_DOUBLE
! 2032: which will be turned into memory by reload if necessary. */
1.1 root 2033: if (!cse_not_expected)
2034: return immed_real_const (exp);
2035: output_constant_def (exp);
2036: return TREE_CST_RTL (exp);
2037:
2038: case COMPLEX_CST:
2039: case STRING_CST:
2040: if (TREE_CST_RTL (exp))
2041: return TREE_CST_RTL (exp);
2042: output_constant_def (exp);
2043: return TREE_CST_RTL (exp);
2044:
2045: case SAVE_EXPR:
2046: if (SAVE_EXPR_RTL (exp) == 0)
2047: {
1.1.1.5 root 2048: rtx reg = gen_reg_rtx (mode);
2049: SAVE_EXPR_RTL (exp) = reg;
2050: store_expr (TREE_OPERAND (exp, 0), reg, 0);
2051: if (!optimize)
2052: save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, reg,
2053: save_expr_regs);
1.1 root 2054: }
1.1.1.2 root 2055: /* Don't let the same rtl node appear in two places. */
1.1 root 2056: return SAVE_EXPR_RTL (exp);
2057:
1.1.1.2 root 2058: case RTL_EXPR:
2059: emit_insn (RTL_EXPR_SEQUENCE (exp));
2060: return RTL_EXPR_RTL (exp);
2061:
2062: case CONSTRUCTOR:
2063: /* All elts simple constants => refer to a constant in memory. */
2064: if (TREE_STATIC (exp))
2065: /* For aggregate types with non-BLKmode modes,
2066: this should ideally construct a CONST_INT. */
2067: return output_constant_def (exp);
2068:
2069: if (ignore)
2070: {
2071: tree elt;
2072: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
2073: expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
2074: return const0_rtx;
2075: }
2076: else
2077: {
2078: if (target == 0)
2079: target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
2080: get_structure_value_addr (expr_size (exp)));
2081: store_expr (exp, target, 0);
2082: return target;
2083: }
2084:
1.1 root 2085: case INDIRECT_REF:
2086: {
2087: tree exp1 = TREE_OPERAND (exp, 0);
2088: tree exp2;
2089:
2090: /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated
2091: for *PTR += ANYTHING where PTR is put inside the SAVE_EXPR.
2092: This code has the same general effect as simply doing
2093: expand_expr on the save expr, except that the expression PTR
2094: is computed for use as a memory address. This means different
2095: code, suitable for indexing, may be generated. */
2096: if (TREE_CODE (exp1) == SAVE_EXPR
2097: && SAVE_EXPR_RTL (exp1) == 0
2098: && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK
2099: && TYPE_MODE (TREE_TYPE (exp1)) == Pmode
2100: && TYPE_MODE (TREE_TYPE (exp2)) == Pmode)
2101: {
1.1.1.2 root 2102: temp = expand_expr (TREE_OPERAND (exp1, 0), 0, VOIDmode, EXPAND_SUM);
1.1 root 2103: op0 = memory_address (mode, temp);
2104: op0 = copy_all_regs (op0);
2105: SAVE_EXPR_RTL (exp1) = op0;
2106: }
2107: else
2108: {
1.1.1.2 root 2109: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, EXPAND_SUM);
1.1 root 2110: op0 = memory_address (mode, op0);
2111: }
2112: }
2113: temp = gen_rtx (MEM, mode, op0);
1.1.1.2 root 2114: /* If address was computed by addition,
2115: mark this as an element of an aggregate. */
2116: if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
2117: || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR
2118: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR))
2119: temp->in_struct = 1;
1.1.1.7 ! root 2120: temp->volatil = TREE_THIS_VOLATILE (exp);
1.1.1.2 root 2121: temp->unchanging = TREE_READONLY (exp);
2122: return temp;
2123:
2124: case ARRAY_REF:
2125: if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
2126: || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST)
2127: {
2128: /* Nonconstant array index or nonconstant element size.
2129: Generate the tree for *(&array+index) and expand that,
2130: except do it in a language-independent way
2131: and don't complain about non-lvalue arrays.
2132: `mark_addressable' should already have been called
2133: for any array for which this case will be reached. */
2134:
2135: tree array_adr = build (ADDR_EXPR, TYPE_POINTER_TO (type),
2136: TREE_OPERAND (exp, 0));
2137: tree index = TREE_OPERAND (exp, 1);
2138: tree elt;
2139:
2140: /* Convert the integer argument to a type the same size as a pointer
2141: so the multiply won't overflow spuriously. */
2142: if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE)
2143: index = convert (type_for_size (POINTER_SIZE, 0), index);
2144:
2145: /* The array address isn't volatile even if the array is. */
2146: TREE_VOLATILE (array_adr) = 0;
2147:
2148: elt = build (INDIRECT_REF, type,
2149: fold (build (PLUS_EXPR, TYPE_POINTER_TO (type),
2150: array_adr,
2151: fold (build (MULT_EXPR,
2152: TYPE_POINTER_TO (type),
2153: index, size_in_bytes (type))))));
2154:
2155: return expand_expr (elt, target, tmode, modifier);
2156: }
2157: /* Treat array-ref with constant index as a component-ref. */
1.1 root 2158:
2159: case COMPONENT_REF:
2160: {
1.1.1.2 root 2161: register enum machine_mode mode1;
1.1 root 2162: int volstruct = 0;
2163: tree dbg1 = TREE_OPERAND (exp, 0); /* For debugging */
1.1.1.2 root 2164: int bitsize;
2165: tree tem = exp;
2166: int bitpos = 0;
2167: int unsignedp;
1.1 root 2168:
1.1.1.2 root 2169: if (TREE_CODE (exp) == COMPONENT_REF)
1.1 root 2170: {
2171: tree field = TREE_OPERAND (exp, 1);
1.1.1.2 root 2172: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
2173: mode1 = DECL_MODE (TREE_OPERAND (exp, 1));
2174: unsignedp = TREE_UNSIGNED (field);
1.1 root 2175: }
1.1.1.2 root 2176: else
1.1 root 2177: {
1.1.1.2 root 2178: mode1 = TYPE_MODE (TREE_TYPE (exp));
2179: bitsize = GET_MODE_BITSIZE (mode1);
2180: unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
1.1 root 2181: }
2182:
1.1.1.2 root 2183: /* Compute cumulative bit-offset for nested component-refs
2184: and array-refs, and find the ultimate containing object. */
2185:
2186: while (1)
1.1 root 2187: {
1.1.1.2 root 2188: if (TREE_CODE (tem) == COMPONENT_REF)
2189: {
2190: bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1));
2191: if (TREE_THIS_VOLATILE (tem))
2192: volstruct = 1;
2193: }
2194: else if (TREE_CODE (tem) == ARRAY_REF
2195: && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
2196: && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST)
2197: {
2198: bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1))
2199: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)))
2200: * TYPE_SIZE_UNIT (TREE_TYPE (tem)));
2201: }
2202: else
2203: break;
2204: tem = TREE_OPERAND (tem, 0);
1.1 root 2205: }
2206:
1.1.1.2 root 2207: op0 = expand_expr (tem, 0, VOIDmode,
2208: (modifier == EXPAND_CONST_ADDRESS
2209: ? modifier : EXPAND_NORMAL));
1.1 root 2210:
1.1.1.2 root 2211: if (mode1 == BImode || GET_CODE (op0) == REG
2212: || GET_CODE (op0) == SUBREG)
2213: {
2214: return extract_bit_field (op0, bitsize, bitpos, unsignedp,
2215: target, mode, tmode);
2216: }
2217: /* Get a reference to just this component. */
2218: if (modifier == EXPAND_CONST_ADDRESS)
2219: op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0),
2220: (bitpos / BITS_PER_UNIT)));
2221: else
2222: op0 = change_address (op0, mode1,
2223: plus_constant (XEXP (op0, 0),
2224: (bitpos / BITS_PER_UNIT)));
2225: op0->in_struct = 1;
2226: op0->volatil = volstruct;
2227: /* If OP0 is in the shared structure-value stack slot,
2228: and it is not BLKmode, copy it into a register.
2229: The shared slot may be clobbered at any time by another call.
2230: BLKmode is safe because our caller will either copy the value away
2231: or take another component and come back here. */
2232: if (mode != BLKmode
2233: && TREE_CODE (TREE_OPERAND (exp, 0)) == CALL_EXPR
2234: && TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == BLKmode)
2235: op0 = copy_to_reg (op0);
2236: if (mode == mode1 || mode1 == BLKmode || mode1 == tmode)
2237: return op0;
2238: if (target == 0)
2239: target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
2240: convert_move (target, op0, unsignedp);
2241: return target;
1.1 root 2242: }
2243:
2244: /* Intended for a reference to a buffer of a file-object in Pascal.
2245: But it's not certain that a special tree code will really be
2246: necessary for these. INDIRECT_REF might work for them. */
2247: case BUFFER_REF:
2248: abort ();
2249:
2250: case CALL_EXPR:
1.1.1.2 root 2251: /* Check for a built-in function. */
2252: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
2253: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL
1.1.1.5 root 2254: && (DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
2255: != NOT_BUILT_IN))
1.1.1.2 root 2256: return expand_builtin (exp, target, subtarget, tmode);
1.1 root 2257: /* If this call was expanded already by preexpand_calls,
2258: just return the result we got. */
2259: if (CALL_EXPR_RTL (exp) != 0)
2260: return CALL_EXPR_RTL (exp);
1.1.1.2 root 2261: return expand_call (exp, target, ignore);
1.1 root 2262:
2263: case NOP_EXPR:
2264: case CONVERT_EXPR:
1.1.1.7 ! root 2265: case REFERENCE_EXPR:
1.1.1.2 root 2266: if (TREE_CODE (type) == VOID_TYPE || ignore)
1.1 root 2267: {
1.1.1.2 root 2268: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
1.1 root 2269: return const0_rtx;
2270: }
2271: if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
1.1.1.2 root 2272: return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier);
1.1 root 2273: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, mode, 0);
1.1.1.2 root 2274: if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode)
1.1 root 2275: return op0;
1.1.1.2 root 2276: if (flag_force_mem && GET_CODE (op0) == MEM)
2277: op0 = copy_to_reg (op0);
1.1 root 2278: if (target == 0)
2279: target = gen_reg_rtx (mode);
1.1.1.2 root 2280: convert_move (target, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
1.1 root 2281: return target;
2282:
2283: case PLUS_EXPR:
2284: preexpand_calls (exp);
1.1.1.2 root 2285: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
2286: && modifier == EXPAND_SUM)
1.1 root 2287: {
1.1.1.2 root 2288: op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode, EXPAND_SUM);
1.1 root 2289: op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)));
1.1.1.2 root 2290: return op1;
1.1 root 2291: }
2292: negate_1 = 1;
2293: plus_minus:
1.1.1.2 root 2294: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
2295: && modifier == EXPAND_SUM)
1.1 root 2296: {
1.1.1.2 root 2297: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
1.1 root 2298: op0 = plus_constant (op0,
2299: negate_1 * TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
1.1.1.2 root 2300: return op0;
1.1 root 2301: }
2302: this_optab = add_optab;
1.1.1.2 root 2303: if (modifier != EXPAND_SUM) goto binop;
1.1 root 2304: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
1.1.1.2 root 2305: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
2306: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, EXPAND_SUM);
1.1 root 2307: /* Put a sum last, to simplify what follows. */
2308: #ifdef OLD_INDEXING
2309: if (GET_CODE (op1) == MULT)
2310: {
2311: temp = op0;
2312: op0 = op1;
2313: op1 = temp;
2314: }
2315: #endif
2316: #ifndef OLD_INDEXING
2317: /* Make sure any term that's a sum with a constant comes last. */
2318: if (GET_CODE (op0) == PLUS
1.1.1.2 root 2319: && CONSTANT_P (XEXP (op0, 1)))
1.1 root 2320: {
2321: temp = op0;
2322: op0 = op1;
2323: op1 = temp;
2324: }
2325: /* If adding to a sum including a constant,
2326: associate it to put the constant outside. */
2327: if (GET_CODE (op1) == PLUS
1.1.1.2 root 2328: && CONSTANT_P (XEXP (op1, 1)))
1.1 root 2329: {
2330: op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0);
2331: if (GET_CODE (XEXP (op1, 1)) == CONST_INT)
2332: return plus_constant (op0, INTVAL (XEXP (op1, 1)));
2333: else
2334: return gen_rtx (PLUS, mode, op0, XEXP (op1, 1));
2335: }
2336: #endif
2337: return gen_rtx (PLUS, mode, op0, op1);
2338:
2339: case MINUS_EXPR:
2340: preexpand_calls (exp);
2341: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
2342: {
1.1.1.2 root 2343: if (modifier == EXPAND_SUM)
2344: {
2345: negate_1 = -1;
2346: goto plus_minus;
2347: }
2348: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2349: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2350: op1 = gen_rtx (CONST_INT, VOIDmode,
2351: - TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
2352: this_optab = add_optab;
2353: goto binop2;
1.1 root 2354: }
2355: this_optab = sub_optab;
2356: goto binop;
2357:
2358: case MULT_EXPR:
2359: preexpand_calls (exp);
2360: /* If first operand is constant, swap them.
2361: Thus the following special case checks need only
2362: check the second operand. */
2363: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
2364: {
2365: register tree t1 = TREE_OPERAND (exp, 0);
2366: TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
2367: TREE_OPERAND (exp, 1) = t1;
2368: }
2369:
2370: /* Attempt to return something suitable for generating an
2371: indexed address, for machines that support that. */
2372:
1.1.1.2 root 2373: if (modifier == EXPAND_SUM
1.1.1.6 root 2374: && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
1.1 root 2375: {
1.1.1.2 root 2376: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
2377:
2378: /* Apply distributive law if OP0 is x+c. */
2379: if (GET_CODE (op0) == PLUS
2380: && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2381: return gen_rtx (PLUS, mode,
2382: gen_rtx (MULT, mode, XEXP (op0, 0),
2383: gen_rtx (CONST_INT, VOIDmode,
2384: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))),
2385: gen_rtx (CONST_INT, VOIDmode,
2386: (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
2387: * INTVAL (XEXP (op0, 1)))));
2388:
1.1 root 2389: if (GET_CODE (op0) != REG)
1.1.1.2 root 2390: op0 = force_operand (op0, 0);
2391: if (GET_CODE (op0) != REG)
2392: op0 = copy_to_mode_reg (mode, op0);
2393:
1.1.1.6 root 2394: return gen_rtx (MULT, mode, op0,
1.1 root 2395: gen_rtx (CONST_INT, VOIDmode,
2396: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))));
2397: }
2398: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2399: /* Check for multiplying things that have been extended
2400: from a narrower type. If this machine supports multiplying
2401: in that narrower type with a result in the desired type,
2402: do it that way, and avoid the explicit type-conversion. */
2403: if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
2404: && TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE
2405: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
2406: < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
2407: && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
2408: && int_fits_type_p (TREE_OPERAND (exp, 1),
1.1.1.2 root 2409: TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
2410: /* Don't use a widening multiply if a shift will do. */
2411: && exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)
1.1 root 2412: ||
2413: (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
2414: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
2415: ==
1.1.1.2 root 2416: TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
2417: /* If both operands are extended, they must either both
2418: be zero-extended or both be sign-extended. */
2419: && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
2420: ==
2421: TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
1.1 root 2422: {
2423: enum machine_mode innermode
2424: = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
1.1.1.2 root 2425: this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1.1 root 2426: ? umul_widen_optab : smul_widen_optab);
2427: if ((int) innermode + 1 == (int) mode
1.1.1.2 root 2428: && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1.1 root 2429: {
2430: op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
2431: 0, VOIDmode, 0);
2432: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
2433: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2434: else
2435: op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
2436: 0, VOIDmode, 0);
2437: goto binop2;
2438: }
2439: }
2440: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2441: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
1.1.1.2 root 2442: return expand_mult (mode, op0, op1, target, TREE_UNSIGNED (type));
1.1 root 2443:
2444: case TRUNC_DIV_EXPR:
2445: case FLOOR_DIV_EXPR:
2446: case CEIL_DIV_EXPR:
2447: case ROUND_DIV_EXPR:
2448: preexpand_calls (exp);
2449: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
1.1.1.2 root 2450: /* Possible optimization: compute the dividend with EXPAND_SUM
1.1 root 2451: then if the divisor is constant can optimize the case
2452: where some terms of the dividend have coeffs divisible by it. */
2453: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2454: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2455: return expand_divmod (0, code, mode, op0, op1, target,
1.1.1.2 root 2456: TREE_UNSIGNED (type));
1.1 root 2457:
2458: case RDIV_EXPR:
2459: preexpand_calls (exp);
2460: this_optab = flodiv_optab;
2461: goto binop;
2462:
2463: case TRUNC_MOD_EXPR:
2464: case FLOOR_MOD_EXPR:
2465: case CEIL_MOD_EXPR:
2466: case ROUND_MOD_EXPR:
2467: preexpand_calls (exp);
2468: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2469: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2470: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2471: return expand_divmod (1, code, mode, op0, op1, target,
1.1.1.2 root 2472: TREE_UNSIGNED (type));
1.1 root 2473: #if 0
2474: #ifdef HAVE_divmoddisi4
2475: if (GET_MODE (op0) != DImode)
2476: {
2477: temp = gen_reg_rtx (DImode);
2478: convert_move (temp, op0, 0);
2479: op0 = temp;
2480: if (GET_MODE (op1) != SImode && GET_CODE (op1) != CONST_INT)
2481: {
2482: temp = gen_reg_rtx (SImode);
2483: convert_move (temp, op1, 0);
2484: op1 = temp;
2485: }
2486: temp = gen_reg_rtx (SImode);
2487: if (target == 0)
2488: target = gen_reg_rtx (SImode);
2489: emit_insn (gen_divmoddisi4 (temp, protect_from_queue (op0, 0),
2490: protect_from_queue (op1, 0),
2491: protect_from_queue (target, 1)));
2492: return target;
2493: }
2494: #endif
2495: #endif
2496:
2497: case FIX_ROUND_EXPR:
2498: case FIX_FLOOR_EXPR:
2499: case FIX_CEIL_EXPR:
2500: abort (); /* Not used for C. */
2501:
2502: case FIX_TRUNC_EXPR:
2503: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
2504: if (target == 0)
2505: target = gen_reg_rtx (mode);
1.1.1.2 root 2506: {
2507: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
2508: if (mode == HImode || mode == QImode)
2509: {
2510: register rtx temp = gen_reg_rtx (SImode);
1.1.1.6 root 2511: expand_fix (temp, op0, 0);
2512: convert_move (target, temp, 0);
1.1.1.2 root 2513: }
2514: else
2515: expand_fix (target, op0, unsignedp);
2516: }
1.1 root 2517: return target;
2518:
2519: case FLOAT_EXPR:
2520: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
2521: if (target == 0)
2522: target = gen_reg_rtx (mode);
1.1.1.2 root 2523: {
2524: int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
2525: if (GET_MODE (op0) == HImode
2526: || GET_MODE (op0) == QImode)
2527: {
2528: register rtx temp = gen_reg_rtx (SImode);
2529: convert_move (temp, op0, unsignedp);
2530: expand_float (target, temp, 0);
2531: }
2532: else
2533: expand_float (target, op0, unsignedp);
2534: }
1.1 root 2535: return target;
2536:
2537: case NEGATE_EXPR:
2538: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
2539: temp = expand_unop (mode, neg_optab, op0, target, 0);
2540: if (temp == 0)
2541: abort ();
2542: return temp;
2543:
2544: case ABS_EXPR:
2545: /* First try to do it with a special abs instruction.
2546: If that does not win, use conditional jump and negate. */
1.1.1.2 root 2547: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1 root 2548: temp = expand_unop (mode, abs_optab, op0, target, 0);
2549: if (temp != 0)
2550: return temp;
2551: temp = gen_label_rtx ();
2552: if (target == 0 || GET_CODE (target) != REG)
1.1.1.2 root 2553: target = gen_reg_rtx (mode);
1.1 root 2554: emit_move_insn (target, op0);
1.1.1.2 root 2555: emit_cmp_insn (target,
2556: expand_expr (convert (TREE_TYPE (exp), integer_zero_node),
2557: 0, VOIDmode, 0),
2558: 0, 0);
1.1.1.6 root 2559: NO_DEFER_POP;
1.1 root 2560: emit_jump_insn (gen_bge (temp));
2561: op0 = expand_unop (mode, neg_optab, target, target, 0);
2562: if (op0 != target)
2563: emit_move_insn (target, op0);
2564: emit_label (temp);
1.1.1.6 root 2565: OK_DEFER_POP;
1.1 root 2566: return target;
2567:
2568: case MAX_EXPR:
2569: case MIN_EXPR:
1.1.1.2 root 2570: mode = TYPE_MODE (TREE_OPERAND (exp, 1));
1.1 root 2571: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2572: if (target == 0 || GET_CODE (target) != REG || target == op1)
1.1.1.2 root 2573: target = gen_reg_rtx (mode);
1.1 root 2574: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
2575: if (target != op0)
2576: emit_move_insn (target, op0);
2577: op0 = gen_label_rtx ();
2578: if (code == MAX_EXPR)
1.1.1.2 root 2579: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
2580: ? compare1 (target, op1, GEU, LEU, 1, mode)
2581: : compare1 (target, op1, GE, LE, 0, mode));
2582: else
2583: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
2584: ? compare1 (target, op1, LEU, GEU, 1, mode)
2585: : compare1 (target, op1, LE, GE, 0, mode));
2586: if (temp == const0_rtx)
2587: emit_move_insn (target, op1);
2588: else if (temp != const1_rtx)
2589: {
2590: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
2591: gen_rtx (IF_THEN_ELSE, VOIDmode,
2592: temp,
2593: gen_rtx (LABEL_REF, VOIDmode, op0),
2594: pc_rtx)));
2595: emit_move_insn (target, op1);
2596: }
2597: emit_label (op0);
1.1 root 2598: return target;
2599:
2600: /* ??? Can optimize when the operand of this is a bitwise operation,
2601: by using a different bitwise operation. */
2602: case BIT_NOT_EXPR:
2603: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2604: temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
2605: if (temp == 0)
2606: abort ();
2607: return temp;
2608:
1.1.1.2 root 2609: case FFS_EXPR:
2610: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2611: temp = expand_unop (mode, ffs_optab, op0, target, 1);
2612: if (temp == 0)
2613: abort ();
2614: return temp;
2615:
1.1 root 2616: /* ??? Can optimize bitwise operations with one arg constant.
2617: Pastel optimizes (a bitwise1 n) bitwise2 (a bitwise3 b)
2618: and (a bitwise1 b) bitwise2 b (etc)
2619: but that is probably not worth while. */
2620:
1.1.1.2 root 2621: /* BIT_AND_EXPR is for bitwise anding.
1.1 root 2622: TRUTH_AND_EXPR is for anding two boolean values
2623: when we want in all cases to compute both of them.
2624: In general it is fastest to do TRUTH_AND_EXPR by
2625: computing both operands as actual zero-or-1 values
2626: and then bitwise anding. In cases where there cannot
2627: be any side effects, better code would be made by
2628: treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR;
2629: but the question is how to recognize those cases. */
2630:
2631: case TRUTH_AND_EXPR:
2632: case BIT_AND_EXPR:
2633: preexpand_calls (exp);
2634: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2635: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2636: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2637: return expand_bit_and (mode, op0, op1, target);
2638:
2639: /* See comment above about TRUTH_AND_EXPR; it applies here too. */
2640: case TRUTH_OR_EXPR:
2641: case BIT_IOR_EXPR:
2642: preexpand_calls (exp);
2643: this_optab = ior_optab;
2644: goto binop;
2645:
2646: case BIT_XOR_EXPR:
2647: preexpand_calls (exp);
2648: this_optab = xor_optab;
2649: goto binop;
2650:
2651: case LSHIFT_EXPR:
2652: case RSHIFT_EXPR:
2653: case LROTATE_EXPR:
2654: case RROTATE_EXPR:
2655: preexpand_calls (exp);
2656: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2657: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2658: return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
1.1.1.2 root 2659: TREE_UNSIGNED (type));
1.1 root 2660:
2661: /* ??? cv's were used to effect here to combine additive constants
2662: and to determine the answer when only additive constants differ.
2663: Also, the addition of one can be handled by changing the condition. */
2664: case LT_EXPR:
2665: case LE_EXPR:
2666: case GT_EXPR:
2667: case GE_EXPR:
2668: case EQ_EXPR:
2669: case NE_EXPR:
2670: preexpand_calls (exp);
1.1.1.2 root 2671: temp = do_store_flag (exp, target, mode);
1.1 root 2672: if (temp != 0)
2673: return temp;
1.1.1.2 root 2674: /* For foo != 0, load foo, and if it is nonzero load 1 instead. */
2675: if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
2676: && subtarget
2677: && (GET_MODE (subtarget)
2678: == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
1.1 root 2679: {
2680: temp = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2681: if (temp != subtarget)
2682: temp = copy_to_reg (temp);
2683: op1 = gen_label_rtx ();
1.1.1.2 root 2684: emit_cmp_insn (temp, const0_rtx, 0, TREE_UNSIGNED (type));
1.1 root 2685: emit_jump_insn (gen_beq (op1));
2686: emit_move_insn (temp, const1_rtx);
2687: emit_label (op1);
2688: return temp;
2689: }
2690: /* If no set-flag instruction, must generate a conditional
2691: store into a temporary variable. Drop through
2692: and handle this like && and ||. */
2693:
2694: case TRUTH_ANDIF_EXPR:
2695: case TRUTH_ORIF_EXPR:
2696: temp = gen_reg_rtx (mode);
2697: emit_clr_insn (temp);
2698: op1 = gen_label_rtx ();
2699: jumpifnot (exp, op1);
2700: emit_0_to_1_insn (temp);
2701: emit_label (op1);
2702: return temp;
2703:
2704: case TRUTH_NOT_EXPR:
2705: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
2706: /* The parser is careful to generate TRUTH_NOT_EXPR
2707: only with operands that are always zero or one. */
2708: temp = expand_binop (mode, xor_optab, op0,
2709: gen_rtx (CONST_INT, mode, 1),
2710: target, 1, OPTAB_LIB_WIDEN);
2711: if (temp == 0)
2712: abort ();
2713: return temp;
2714:
2715: case COMPOUND_EXPR:
1.1.1.2 root 2716: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
1.1 root 2717: emit_queue ();
2718: return expand_expr (TREE_OPERAND (exp, 1), target, VOIDmode, 0);
2719:
2720: case COND_EXPR:
2721: /* Note that COND_EXPRs whose type is a structure or union
2722: are required to be constructed to contain assignments of
2723: a temporary variable, so that we can evaluate them here
2724: for side effect only. If type is void, we must do likewise. */
2725: op0 = gen_label_rtx ();
2726: op1 = gen_label_rtx ();
2727:
1.1.1.2 root 2728: if (mode == VOIDmode || ignore)
1.1 root 2729: temp = 0;
2730: else if (target)
2731: temp = target;
1.1.1.2 root 2732: else if (mode == BLKmode)
2733: {
2734: if (TYPE_SIZE (type) == 0 || ! TREE_LITERAL (TYPE_SIZE (type)))
2735: abort ();
2736: temp = assign_stack_local (BLKmode,
2737: (TREE_INT_CST_LOW (TYPE_SIZE (type))
2738: * TYPE_SIZE_UNIT (type)
2739: + BITS_PER_UNIT - 1)
2740: / BITS_PER_UNIT);
2741: }
1.1 root 2742: else
2743: temp = gen_reg_rtx (mode);
2744:
2745: jumpifnot (TREE_OPERAND (exp, 0), op0);
1.1.1.6 root 2746: NO_DEFER_POP;
1.1 root 2747: if (temp != 0)
1.1.1.2 root 2748: store_expr (TREE_OPERAND (exp, 1), temp, 0);
1.1 root 2749: else
1.1.1.2 root 2750: expand_expr (TREE_OPERAND (exp, 1), ignore ? const0_rtx : 0,
2751: VOIDmode, 0);
1.1 root 2752: emit_queue ();
2753: emit_jump_insn (gen_jump (op1));
2754: emit_barrier ();
2755: emit_label (op0);
2756: if (temp != 0)
1.1.1.2 root 2757: store_expr (TREE_OPERAND (exp, 2), temp, 0);
1.1 root 2758: else
1.1.1.2 root 2759: expand_expr (TREE_OPERAND (exp, 2), ignore ? const0_rtx : 0,
2760: VOIDmode, 0);
1.1 root 2761: emit_queue ();
2762: emit_label (op1);
1.1.1.6 root 2763: OK_DEFER_POP;
1.1 root 2764: return temp;
2765:
1.1.1.7 ! root 2766: case INIT_EXPR:
! 2767: {
! 2768: tree lhs = TREE_OPERAND (exp, 0);
! 2769: tree rhs = TREE_OPERAND (exp, 1);
! 2770: tree type = TREE_TYPE (lhs);
! 2771:
! 2772: /* We are initializing via bitwise copy. After doing that,
! 2773: if we cannot be sure of the virtual function table pointer
! 2774: that is returned, store it by hand. */
! 2775:
! 2776: temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
! 2777: #if 0
! 2778: if (TREE_VIRTUAL (type)
! 2779: && (type != TYPE_MAIN_VARIANT (TREE_TYPE (rhs))
! 2780: || TREE_CODE (rhs) != PARM_DECL
! 2781: || TREE_CODE (rhs) != VAR_DECL
! 2782: || TREE_CODE (rhs) != CALL_EXPR))
! 2783: {
! 2784: extern tree build_component_ref ();
! 2785: expand_assignment (build_component_ref (lhs, get_vfield_name (type), 0),
! 2786: build_unary_op (ADDR_EXPR, lookup_name (get_vtable_name (type)), 0),
! 2787: 0, 0);
! 2788: }
! 2789: #endif
! 2790: return temp;
! 2791: }
! 2792:
1.1 root 2793: case MODIFY_EXPR:
1.1.1.7 ! root 2794: {
! 2795: /* If lhs is complex, expand calls in rhs before computing it.
! 2796: That's so we don't compute a pointer and save it over a call.
! 2797: If lhs is simple, compute it first so we can give it as a
! 2798: target if the rhs is just a call. This avoids an extra temp and copy
! 2799: and that prevents a partial-subsumption which makes bad code.
! 2800: Actually we could treat component_ref's of vars like vars. */
! 2801:
! 2802: tree lhs = TREE_OPERAND (exp, 0);
! 2803: tree rhs = TREE_OPERAND (exp, 1);
! 2804: tree type = TREE_TYPE (lhs);
! 2805: temp = 0;
! 2806:
! 2807: if (TREE_CODE (lhs) != VAR_DECL
! 2808: && TREE_CODE (lhs) != RESULT_DECL
! 2809: && TREE_CODE (lhs) != PARM_DECL)
! 2810: preexpand_calls (exp);
! 2811:
! 2812: #if 0
! 2813: if (TREE_VIRTUAL (type)
! 2814: && (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (TREE_TYPE (rhs))
! 2815: || (TREE_CODE (rhs) != VAR_DECL
! 2816: && TREE_CODE (rhs) != PARM_DECL
! 2817: && TREE_CODE (rhs) != RESULT_DECL)))
! 2818: {
! 2819: /* We are performing structure assignment. If the
! 2820: types of the structures are different, or if the
! 2821: RHS is not "pure" (i.e., a VAR_DECL, PARM_DECLs are
! 2822: too hard right now), then we must preserve the purity
! 2823: of the LHS, by queueing the assignment of
! 2824: it virtual function table pointer to itself. */
! 2825: extern tree build_component_ref ();
! 2826: tree vptr = build_component_ref (lhs, get_vfield_name (type), 0);
! 2827: enum machine_mode mode = TYPE_MODE (TREE_TYPE (vptr));
! 2828: int icode = (int) mov_optab->handlers[(int) mode].insn_code;
! 2829: rtx vptr_rtx = stabilize (expand_expr (vptr, 0, Pmode, 0));
! 2830: rtx vptr_tmp = copy_to_reg (vptr_rtx);
! 2831:
! 2832: if (icode == (int)CODE_FOR_nothing)
! 2833: abort ();
! 2834:
! 2835: temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
! 2836: enqueue_insn (temp, GEN_FCN (icode) (vptr_rtx, vptr_tmp));
! 2837: }
! 2838: else
! 2839: {
! 2840: #endif
! 2841: /* ??? Original code */
! 2842: temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
! 2843: }
1.1 root 2844: return temp;
2845:
2846: case PREINCREMENT_EXPR:
2847: case PREDECREMENT_EXPR:
1.1.1.2 root 2848: return expand_increment (exp, 0);
1.1 root 2849:
2850: case POSTINCREMENT_EXPR:
2851: case POSTDECREMENT_EXPR:
1.1.1.2 root 2852: return expand_increment (exp, 1);
1.1 root 2853:
2854: case ADDR_EXPR:
1.1.1.2 root 2855: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode,
2856: EXPAND_CONST_ADDRESS);
1.1 root 2857: if (GET_CODE (op0) != MEM)
2858: abort ();
1.1.1.2 root 2859: if (modifier == EXPAND_SUM)
1.1 root 2860: return XEXP (op0, 0);
1.1.1.2 root 2861: op0 = force_operand (XEXP (op0, 0), target);
2862: if (flag_force_addr && GET_CODE (op0) != REG)
2863: return force_reg (Pmode, op0);
2864: return op0;
1.1 root 2865:
2866: case ENTRY_VALUE_EXPR:
2867: abort ();
2868:
2869: case ERROR_MARK:
1.1.1.2 root 2870: return const0_rtx;
1.1 root 2871:
2872: default:
2873: abort ();
2874: }
2875:
2876: /* Here to do an ordinary binary operator, generating an instruction
2877: from the optab already placed in `this_optab'. */
2878: binop:
2879: /* Detect things like x = y | (a == b)
2880: and do them as (x = y), (a == b ? x |= 1 : 0), x. */
2881: /* First, get the comparison or conditional into the second arg. */
2882: if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 0))]
2883: || (TREE_CODE (TREE_OPERAND (exp, 0)) == COND_EXPR
2884: && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
2885: || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 2)))))
2886: {
2887: if (this_optab == ior_optab || this_optab == add_optab
2888: || this_optab == xor_optab)
2889: {
2890: tree exch = TREE_OPERAND (exp, 1);
2891: TREE_OPERAND (exp, 1) = TREE_OPERAND (exp, 0);
2892: TREE_OPERAND (exp, 0) = exch;
2893: }
2894: }
1.1.1.3 root 2895: /* Optimize X + (Y ? Z : 0) by computing X and maybe adding Z. */
1.1 root 2896: if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 1))]
2897: || (TREE_CODE (TREE_OPERAND (exp, 1)) == COND_EXPR
2898: && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 1))
2899: || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))))
2900: {
2901: if (this_optab == ior_optab || this_optab == add_optab
2902: || this_optab == xor_optab || this_optab == sub_optab
2903: || this_optab == lshl_optab || this_optab == ashl_optab
2904: || this_optab == lshr_optab || this_optab == ashr_optab
2905: || this_optab == rotl_optab || this_optab == rotr_optab)
2906: {
1.1.1.2 root 2907: tree thenexp;
1.1 root 2908: rtx thenv = 0;
2909:
1.1.1.7 ! root 2910: #if 1
! 2911: /* We can't risk storing in the supplied target
! 2912: since it might be used in operand 1. */
! 2913: target = gen_reg_rtx (mode);
! 2914: #else
1.1.1.3 root 2915: /* Don't store intermediate results in a fixed register. */
2916: if (target != 0 && GET_CODE (target) == REG
2917: && REGNO (target) < FIRST_PSEUDO_REGISTER)
2918: target = 0;
1.1 root 2919: if (target == 0) target = gen_reg_rtx (mode);
1.1.1.7 ! root 2920: #endif
1.1.1.3 root 2921:
2922: /* Compute X into the target. */
1.1.1.2 root 2923: store_expr (TREE_OPERAND (exp, 0), target, 0);
1.1 root 2924: op0 = gen_label_rtx ();
2925:
1.1.1.3 root 2926: /* If other operand is a comparison COMP, treat it as COMP ? 1 : 0 */
1.1 root 2927: if (TREE_CODE (TREE_OPERAND (exp, 1)) != COND_EXPR)
2928: {
2929: do_jump (TREE_OPERAND (exp, 1), op0, 0);
2930: thenv = const1_rtx;
2931: }
2932: else if (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))
2933: {
2934: do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), op0, 0);
2935: thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 1);
2936: }
2937: else
2938: {
2939: do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0, op0);
2940: thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 2);
2941: }
2942:
2943: if (thenv == 0)
2944: thenv = expand_expr (thenexp, 0, VOIDmode, 0);
2945:
1.1.1.3 root 2946: /* THENV is now Z, the value to operate on, as an rtx.
2947: We have already tested that Y isn't zero, so do the operation. */
2948:
1.1 root 2949: if (this_optab == rotl_optab || this_optab == rotr_optab)
2950: temp = expand_binop (mode, this_optab, target, thenv, target,
2951: -1, OPTAB_LIB);
2952: else if (this_optab == lshl_optab || this_optab == lshr_optab)
2953: temp = expand_binop (mode, this_optab, target, thenv, target,
2954: 1, OPTAB_LIB_WIDEN);
2955: else
2956: temp = expand_binop (mode, this_optab, target, thenv, target,
2957: 0, OPTAB_LIB_WIDEN);
2958: if (target != temp)
2959: emit_move_insn (target, temp);
2960:
1.1.1.6 root 2961: do_pending_stack_adjust ();
1.1 root 2962: emit_label (op0);
2963: return target;
2964: }
2965: }
2966: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2967: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2968: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2969: binop2:
2970: temp = expand_binop (mode, this_optab, op0, op1, target,
1.1.1.2 root 2971: TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
1.1 root 2972: binop1:
2973: if (temp == 0)
2974: abort ();
2975: return temp;
2976: }
2977:
1.1.1.2 root 2978: /* Expand an expression EXP that calls a built-in function,
2979: with result going to TARGET if that's convenient
2980: (and in mode MODE if that's convenient).
2981: SUBTARGET may be used as the target for computing one of EXP's operands. */
2982:
2983: static rtx
2984: expand_builtin (exp, target, subtarget, mode)
2985: tree exp;
2986: rtx target;
2987: rtx subtarget;
2988: enum machine_mode mode;
2989: {
2990: tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2991: tree arglist = TREE_OPERAND (exp, 1);
2992: rtx op0;
2993: rtx temp;
2994:
2995: switch (DECL_FUNCTION_CODE (fndecl))
2996: {
2997: case BUILT_IN_ABS:
2998: case BUILT_IN_LABS:
2999: case BUILT_IN_FABS:
3000: /* build_function_call changes these into ABS_EXPR. */
3001: abort ();
3002:
3003: case BUILT_IN_ALLOCA:
3004: if (arglist == 0)
3005: return const0_rtx;
3006: frame_pointer_needed = 1;
3007: /* Compute the argument. */
3008: op0 = expand_expr (TREE_VALUE (arglist), 0, VOIDmode, 0);
3009: if (! CONSTANT_P (op0))
3010: {
3011: op0 = force_reg (GET_MODE (op0), op0);
3012: if (GET_MODE (op0) != Pmode)
3013: op0 = convert_to_mode (Pmode, op0);
3014: }
3015: /* Push that much space (rounding it up). */
1.1.1.3 root 3016: do_pending_stack_adjust ();
1.1.1.4 root 3017: #ifdef STACK_GROWS_DOWNWARD
1.1.1.2 root 3018: anti_adjust_stack (round_push (op0));
1.1.1.4 root 3019: #endif
1.1.1.2 root 3020: /* Return a copy of current stack ptr, in TARGET if possible. */
3021: if (target)
3022: emit_move_insn (target, stack_pointer_rtx);
3023: else
3024: target = copy_to_reg (stack_pointer_rtx);
1.1.1.4 root 3025: #ifdef STACK_POINTER_OFFSET
3026: /* If the contents of the stack pointer reg are offset from the
3027: actual top-of-stack address, add the offset here. */
1.1.1.6 root 3028: if (GET_CODE (target) == REG)
3029: emit_insn (gen_add2_insn (target, gen_rtx (CONST_INT, VOIDmode,
3030: STACK_POINTER_OFFSET)));
3031: else
3032: {
3033: rtx temp =
3034: expand_binop (GET_MODE (target), add_optab, target,
3035: gen_rtx (CONST_INT, VOIDmode, STACK_POINTER_OFFSET),
3036: target,
3037: 1, OPTAB_DIRECT);
3038: if (temp == 0) abort ();
3039: if (temp != target)
3040: emit_move_insn (target, temp);
3041: }
1.1.1.4 root 3042: #endif
3043: #ifndef STACK_GROWS_DOWNWARD
3044: anti_adjust_stack (round_push (op0));
3045: #endif
1.1.1.2 root 3046: return target;
3047:
3048: case BUILT_IN_FFS:
3049: if (arglist == 0)
3050: return const0_rtx;
3051:
3052: /* Compute the argument. */
3053: op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3054: /* Compute ffs, into TARGET if possible.
3055: Set TARGET to wherever the result comes back. */
3056: target = expand_unop (mode, ffs_optab, op0, target, 1);
3057: if (target == 0)
3058: abort ();
3059: return target;
3060:
3061: default:
3062: abort ();
3063: }
3064: }
3065:
3066: /* Expand code for a post- or pre- increment or decrement
3067: and return the RTX for the result.
3068: POST is 1 for postinc/decrements and 0 for preinc/decrements. */
3069:
3070: static rtx
3071: expand_increment (exp, post)
3072: register tree exp;
3073: int post;
3074: {
3075: register rtx op0, op1;
3076: register rtx temp;
3077: register tree incremented = TREE_OPERAND (exp, 0);
3078: optab this_optab = add_optab;
3079: int icode;
3080: enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
3081: int op0_is_copy = 0;
3082:
3083: /* Stabilize any component ref that might need to be
3084: evaluated more than once below. */
3085: if (TREE_CODE (incremented) == COMPONENT_REF
3086: && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
3087: || DECL_MODE (TREE_OPERAND (exp, 1)) == BImode))
3088: incremented = stabilize_reference (incremented);
3089:
3090: /* Compute the operands as RTX.
3091: Note whether OP0 is the actual lvalue or a copy of it:
3092: I believe it is a copy iff it is a register and insns were
3093: generated in computing it. */
3094: temp = get_last_insn ();
3095: op0 = expand_expr (incremented, 0, VOIDmode, 0);
3096: if (temp != get_last_insn ())
3097: op0_is_copy = (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG);
3098: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
3099:
3100: /* Decide whether incrementing or decrementing. */
3101: if (TREE_CODE (exp) == POSTDECREMENT_EXPR
3102: || TREE_CODE (exp) == PREDECREMENT_EXPR)
3103: this_optab = sub_optab;
3104:
3105: /* If OP0 is not the actual lvalue, but rather a copy in a register,
3106: then we cannot just increment OP0. We must
3107: therefore contrive to increment the original value.
3108: Then we can return OP0 since it is a copy of the old value. */
3109: if (op0_is_copy)
3110: {
3111: /* This is the easiest way to increment the value wherever it is.
3112: Problems with multiple evaluation of INCREMENTED
3113: are prevented because either (1) it is a component_ref,
3114: in which case it was stabilized above, or (2) it is an array_ref
3115: with constant index in an array in a register, which is
3116: safe to reevaluate. */
3117: tree newexp = build ((this_optab == add_optab
3118: ? PLUS_EXPR : MINUS_EXPR),
3119: TREE_TYPE (exp),
3120: incremented,
3121: TREE_OPERAND (exp, 1));
3122: temp = expand_assignment (incremented, newexp, ! post, 0);
3123: return post ? op0 : temp;
3124: }
3125:
3126: /* Convert decrement by a constant into a negative increment. */
3127: if (this_optab == sub_optab
3128: && GET_CODE (op1) == CONST_INT)
3129: {
3130: op1 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op1));
3131: this_optab = add_optab;
3132: }
3133:
3134: if (post)
3135: {
3136: /* We have a true reference to the value in OP0.
3137: If there is an insn to add or subtract in this mode, queue it. */
3138:
3139: /* I'm not sure this is still necessary. */
3140: op0 = stabilize (op0);
3141:
3142: icode = (int) this_optab->handlers[(int) mode].insn_code;
3143: if (icode != (int) CODE_FOR_nothing
3144: /* Make sure that OP0 is valid for operands 0 and 1
3145: of the insn we want to queue. */
3146: && (*insn_operand_predicate[icode][0]) (op0, mode)
3147: && (*insn_operand_predicate[icode][1]) (op0, mode))
3148: {
3149: if (! (*insn_operand_predicate[icode][2]) (op1, mode))
3150: op1 = force_reg (mode, op1);
3151:
3152: return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
3153: }
3154: }
3155:
3156: /* Preincrement, or we can't increment with one simple insn. */
3157: if (post)
3158: /* Save a copy of the value before inc or dec, to return it later. */
3159: temp = copy_to_reg (op0);
3160: else
3161: /* Arrange to return the incremented value. */
3162: temp = op0;
3163:
3164: /* Increment however we can. */
3165: op1 = expand_binop (mode, this_optab, op0, op1, op0,
3166: 0, OPTAB_LIB_WIDEN);
3167: /* Make sure the value is stored into OP0. */
3168: if (op1 != op0)
3169: emit_move_insn (op0, op1);
3170:
3171: return temp;
3172: }
3173:
1.1 root 3174: /* Expand all function calls contained within EXP, innermost ones first.
3175: But don't look within expressions that have sequence points.
3176: For each CALL_EXPR, record the rtx for its value
1.1.1.2 root 3177: in the CALL_EXPR_RTL field.
3178:
3179: Calls that return large structures for which a structure return
3180: stack slot is needed are not preexpanded. Preexpanding them loses
3181: because if more than one were preexpanded they would try to use the
3182: same stack slot. */
1.1 root 3183:
3184: static void
3185: preexpand_calls (exp)
3186: tree exp;
3187: {
3188: register int nops, i;
3189:
3190: if (! do_preexpand_calls)
3191: return;
3192:
1.1.1.2 root 3193: /* Only expressions and references can contain calls. */
3194:
3195: if (tree_code_type[(int) TREE_CODE (exp)][0] != 'e'
3196: && tree_code_type[(int) TREE_CODE (exp)][0] != 'r')
3197: return;
3198:
1.1 root 3199: switch (TREE_CODE (exp))
3200: {
3201: case CALL_EXPR:
1.1.1.2 root 3202: /* Do nothing to built-in functions. */
3203: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
3204: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL
1.1.1.5 root 3205: && (DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
3206: != NOT_BUILT_IN))
1.1.1.2 root 3207: return;
3208: if (CALL_EXPR_RTL (exp) == 0
3209: && TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
3210: CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0);
1.1 root 3211: return;
3212:
3213: case COMPOUND_EXPR:
3214: case COND_EXPR:
3215: case TRUTH_ANDIF_EXPR:
3216: case TRUTH_ORIF_EXPR:
3217: /* If we find one of these, then we can be sure
3218: the adjust will be done for it (since it makes jumps).
3219: Do it now, so that if this is inside an argument
3220: of a function, we don't get the stack adjustment
3221: after some other args have already been pushed. */
3222: do_pending_stack_adjust ();
3223: return;
3224:
1.1.1.2 root 3225: case RTL_EXPR:
3226: return;
3227:
1.1 root 3228: case SAVE_EXPR:
3229: if (SAVE_EXPR_RTL (exp) != 0)
3230: return;
3231: }
3232:
3233: nops = tree_code_length[(int) TREE_CODE (exp)];
3234: for (i = 0; i < nops; i++)
3235: if (TREE_OPERAND (exp, i) != 0)
3236: {
3237: register int type = *tree_code_type[(int) TREE_CODE (TREE_OPERAND (exp, i))];
3238: if (type == 'e' || type == 'r')
3239: preexpand_calls (TREE_OPERAND (exp, i));
3240: }
3241: }
3242:
1.1.1.2 root 3243: /* Force FUNEXP into a form suitable for the address of a CALL,
3244: and return that as an rtx. Also load the static chain register
3245: from either FUNEXP or CONTEXT. */
1.1 root 3246:
1.1.1.2 root 3247: static rtx
3248: prepare_call_address (funexp, context)
1.1 root 3249: rtx funexp;
3250: rtx context;
3251: {
3252: funexp = protect_from_queue (funexp, 0);
1.1.1.2 root 3253: if (context != 0)
1.1 root 3254: context = protect_from_queue (context, 0);
3255:
3256: /* Function variable in language with nested functions. */
3257: if (GET_MODE (funexp) == EPmode)
3258: {
1.1.1.2 root 3259: emit_move_insn (static_chain_rtx, gen_highpart (Pmode, funexp));
3260: funexp = memory_address (FUNCTION_MODE, gen_lowpart (Pmode, funexp));
3261: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
1.1 root 3262: }
3263: else
3264: {
3265: if (context != 0)
1.1.1.2 root 3266: /* Unless function variable in C, or top level function constant */
3267: emit_move_insn (static_chain_rtx, lookup_static_chain (context));
3268:
3269: /* Make a valid memory address and copy constants thru pseudo-regs,
3270: but not for a constant address if -fno-function-cse. */
3271: if (GET_CODE (funexp) != SYMBOL_REF)
3272: funexp = memory_address (FUNCTION_MODE, funexp);
3273: else
1.1 root 3274: {
1.1.1.2 root 3275: #ifndef NO_FUNCTION_CSE
1.1.1.6 root 3276: if (optimize && ! flag_no_function_cse)
3277: funexp = force_reg (Pmode, funexp);
1.1.1.2 root 3278: #endif
3279: }
3280:
3281: if (context != 0)
3282: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
1.1 root 3283: }
1.1.1.2 root 3284: return funexp;
3285: }
3286:
3287: /* Generate instructions to call function FUNEXP,
3288: and optionally pop the results.
3289: The CALL_INSN is the first insn generated.
3290:
3291: FUNTYPE is the data type of the function, or, for a library call,
3292: the identifier for the name of the call. This is given to the
3293: macro RETURN_POPS_ARGS to determine whether this function pops its own args.
3294:
1.1.1.6 root 3295: STACK_SIZE is the number of bytes of arguments on the stack,
1.1.1.2 root 3296: rounded up to STACK_BOUNDARY; zero if the size is variable.
3297: This is both to put into the call insn and
3298: to generate explicit popping code if necessary.
3299:
3300: NEXT_ARG_REG is the rtx that results from executing
3301: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1)
3302: just after all the args have had their registers assigned.
3303: This could be whatever you like, but normally it is the first
3304: arg-register beyond those used for args in this call,
3305: or 0 if all the arg-registers are used in this call.
3306: It is passed on to `gen_call' so you can put this info in the call insn.
3307:
3308: VALREG is a hard register in which a value is returned,
3309: or 0 if the call does not return a value.
3310:
3311: OLD_ARGS_SIZE is the value that `current_args_size' had before
3312: the args to this call were processed.
3313: We restore `current_args_size' to that value. */
3314:
3315: static void
3316: emit_call_1 (funexp, funtype, stack_size, next_arg_reg, valreg, old_args_size)
3317: rtx funexp;
3318: tree funtype;
3319: int stack_size;
3320: rtx next_arg_reg;
3321: rtx valreg;
3322: int old_args_size;
3323: {
3324: rtx stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size);
3325:
3326: if (valreg)
3327: emit_call_insn (gen_call_value (valreg,
3328: gen_rtx (MEM, FUNCTION_MODE, funexp),
3329: stack_size_rtx, next_arg_reg));
3330: else
3331: emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp),
3332: stack_size_rtx, next_arg_reg));
3333:
3334: current_args_size = old_args_size;
3335:
1.1 root 3336: /* If returning from the subroutine does not automatically pop the args,
3337: we need an instruction to pop them sooner or later.
3338: Perhaps do it now; perhaps just record how much space to pop later. */
1.1.1.2 root 3339:
3340: if (! RETURN_POPS_ARGS (TREE_TYPE (funtype))
3341: && stack_size != 0)
1.1 root 3342: {
1.1.1.2 root 3343: if (flag_defer_pop && current_args_size == 0)
3344: pending_stack_adjust += stack_size;
1.1 root 3345: else
1.1.1.3 root 3346: adjust_stack (stack_size_rtx);
1.1 root 3347: }
3348: }
3349:
3350: /* At the start of a function, record that we have no previously-pushed
3351: arguments waiting to be popped. */
3352:
1.1.1.2 root 3353: void
3354: init_pending_stack_adjust ()
1.1 root 3355: {
3356: pending_stack_adjust = 0;
3357: }
3358:
1.1.1.2 root 3359: /* When exiting from function, if safe, clear out any pending stack adjust
3360: so the adjustment won't get done. */
3361:
3362: void
3363: clear_pending_stack_adjust ()
3364: {
3365: #ifdef EXIT_IGNORE_STACK
1.1.1.4 root 3366: if (!flag_omit_frame_pointer && EXIT_IGNORE_STACK
3367: && ! TREE_INLINE (current_function_decl))
1.1.1.2 root 3368: pending_stack_adjust = 0;
3369: #endif
3370: }
3371:
1.1 root 3372: /* At start of function, initialize. */
1.1.1.2 root 3373: void
1.1 root 3374: clear_current_args_size ()
3375: {
3376: current_args_size = 0;
3377: }
3378:
3379: /* Pop any previously-pushed arguments that have not been popped yet. */
3380:
1.1.1.2 root 3381: void
1.1 root 3382: do_pending_stack_adjust ()
3383: {
3384: if (current_args_size == 0)
3385: {
3386: if (pending_stack_adjust != 0)
3387: adjust_stack (gen_rtx (CONST_INT, VOIDmode, pending_stack_adjust));
3388: pending_stack_adjust = 0;
3389: }
3390: }
3391:
3392: /* Generate all the code for a function call
3393: and return an rtx for its value.
3394: Store the value in TARGET (specified as an rtx) if convenient.
1.1.1.2 root 3395: If the value is stored in TARGET then TARGET is returned.
3396: If IGNORE is nonzero, then we ignore the value of the function call. */
1.1 root 3397:
3398: static rtx
1.1.1.2 root 3399: expand_call (exp, target, ignore)
1.1 root 3400: tree exp;
3401: rtx target;
1.1.1.2 root 3402: int ignore;
1.1 root 3403: {
3404: tree actparms = TREE_OPERAND (exp, 1);
1.1.1.2 root 3405: tree funtype;
3406: rtx funexp;
3407: register tree p = TREE_OPERAND (exp, 0);
3408: struct args_size args_size;
1.1 root 3409: register int i;
3410: register tree *argvec;
1.1.1.2 root 3411: rtx *regvec;
3412: rtx *valvec;
3413: int *partial;
3414: struct args_size *arg_offset;
3415: struct args_size *arg_size;
1.1 root 3416: int num_actuals;
3417: rtx structure_value_addr = 0;
1.1.1.2 root 3418: tree fndecl = 0;
3419: int may_be_alloca;
3420: int inc;
3421: int is_setjmp;
3422: int is_integrable = 0;
3423: rtx argblock = 0;
3424: CUMULATIVE_ARGS args_so_far;
3425: int reg_parm_seen = 0;
3426: rtx valreg;
3427: rtx old_stack_level;
3428: int old_pending_adj;
3429: int old_current_args_size = current_args_size;
3430:
3431: /* Number of named args. Args after this are anonymous ones
3432: and they must all go on the stack. */
3433: int n_named_args;
3434:
3435: args_size.constant = 0;
3436: args_size.var = 0;
3437:
3438: /* See if we can find a DECL-node for the actual function.
3439: As a result, decide whether this is a call to an integrable function. */
3440:
3441: if (TREE_CODE (p) == ADDR_EXPR)
3442: {
3443: fndecl = TREE_OPERAND (p, 0);
3444: if (TREE_CODE (fndecl) != FUNCTION_DECL)
3445: fndecl = 0;
3446: else
3447: {
3448: extern tree current_function_decl;
1.1 root 3449:
1.1.1.2 root 3450: if (fndecl != current_function_decl
3451: && DECL_SAVED_INSNS (fndecl))
3452: is_integrable = 1;
3453: else
1.1.1.4 root 3454: {
3455: /* In case this function later becomes inlineable,
3456: record that there was already a non-inline call to it. */
3457: TREE_ADDRESSABLE (fndecl) = 1;
3458: TREE_ADDRESSABLE (DECL_NAME (fndecl)) = 1;
3459: }
1.1.1.2 root 3460: }
3461: }
1.1 root 3462:
1.1.1.2 root 3463: /* Set up a place to return a structure. */
1.1 root 3464:
3465: if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
3466: {
3467: /* This call returns a big structure. */
3468: if (target)
3469: structure_value_addr = XEXP (target, 0);
3470: else
3471: /* Make room on the stack to hold the value. */
3472: structure_value_addr = get_structure_value_addr (expr_size (exp));
3473: }
3474:
1.1.1.2 root 3475: if (is_integrable)
3476: {
3477: extern int integration_time;
3478: extern rtx expand_inline_function ();
3479: rtx temp;
3480:
3481: temp = expand_inline_function (fndecl, actparms, target,
3482: ignore, TREE_TYPE (exp),
3483: structure_value_addr);
3484:
1.1.1.4 root 3485: if (temp != (rtx)-1)
1.1.1.2 root 3486: return temp;
3487: }
3488:
3489: #if 0
3490: /* Unless it's a call to a specific function that isn't alloca,
3491: if it has one argument, we must assume it might be alloca. */
3492:
3493: may_be_alloca =
3494: (!(fndecl != 0
3495: && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
3496: "alloca"))
3497: && actparms != 0
3498: && TREE_CHAIN (actparms) == 0);
3499: #else
3500: /* We assume that alloca will always be called by name. It
3501: makes no sense to pass it as a pointer-to-function to
3502: anything that does not understand its behavior. */
3503: may_be_alloca =
3504: (fndecl && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "alloca"));
3505: #endif
3506:
3507: /* See if this is a call to a function that can return more than once. */
3508:
3509: is_setjmp
3510: = (fndecl != 0
3511: && (!strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "setjmp")
3512: || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "_setjmp")));
3513:
3514: if (may_be_alloca)
3515: {
3516: frame_pointer_needed = 1;
3517: may_call_alloca = 1;
3518: }
3519:
3520: /* Don't let pending stack adjusts add up to too much.
3521: Also, do all pending adjustments now
3522: if there is any chance this might be a call to alloca. */
3523:
3524: if (pending_stack_adjust >= 32
3525: || (pending_stack_adjust > 0 && may_be_alloca))
3526: do_pending_stack_adjust ();
3527:
3528: /* Operand 0 is a pointer-to-function; get the type of the function. */
3529: funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
3530: if (TREE_CODE (funtype) != POINTER_TYPE)
3531: abort ();
3532: funtype = TREE_TYPE (funtype);
3533:
1.1.1.7 ! root 3534: if (TREE_CODE (funtype) == METHOD_TYPE)
! 3535: funtype = TREE_TYPE (funtype);
! 3536:
1.1.1.6 root 3537: /* Pass the function the address in which to return a structure value. */
3538: if (structure_value_addr && GET_CODE (struct_value_rtx) == MEM)
3539: actparms = tree_cons (error_mark_node,
3540: build (SAVE_EXPR,
3541: type_for_size (BITS_PER_WORD, 0),
3542: 0, structure_value_addr),
3543: actparms);
3544:
1.1.1.2 root 3545: /* Count the arguments and set NUM_ACTUALS. */
1.1 root 3546: for (p = actparms, i = 0; p; p = TREE_CHAIN (p)) i++;
3547: num_actuals = i;
1.1.1.2 root 3548:
3549: /* Compute number of named args.
3550: This may actually be 1 too large, but that happens
3551: only in the case when all args are named, so no trouble results. */
3552: if (TYPE_ARG_TYPES (funtype) != 0)
3553: n_named_args = list_length (TYPE_ARG_TYPES (funtype));
3554: else
3555: /* If we know nothing, treat all args as named. */
3556: n_named_args = num_actuals;
3557:
3558: /* Make a vector of the args, in the order we want to compute them,
3559: and a parallel vector of where we want to put them.
3560: regvec[I] is 0 to if should push argvec[I] or else a reg to put it in.
3561: valvec[i] is the arg value as an rtx. */
1.1.1.6 root 3562: argvec = (tree *) alloca (num_actuals * sizeof (tree));
3563: regvec = (rtx *) alloca (num_actuals * sizeof (rtx));
3564: valvec = (rtx *) alloca (num_actuals * sizeof (rtx));
3565: partial = (int *) alloca (num_actuals * sizeof (int));
3566: arg_size = (struct args_size *) alloca (num_actuals * sizeof (struct args_size));
3567: arg_offset = (struct args_size *) alloca (num_actuals * sizeof (struct args_size));
1.1.1.2 root 3568:
3569: /* In this loop, we consider args in the order they are written.
3570: We fill up argvec from the front of from the back
3571: so that the first arg to be pushed ends up at the front. */
1.1 root 3572:
1.1.1.2 root 3573: #ifdef PUSH_ARGS_REVERSED
3574: i = num_actuals - 1, inc = -1;
1.1 root 3575: /* In this case, must reverse order of args
1.1.1.2 root 3576: so that we compute and push the last arg first. */
1.1 root 3577: #else
1.1.1.2 root 3578: i = 0, inc = 1;
3579: #endif
3580:
3581: INIT_CUMULATIVE_ARGS (args_so_far, funtype);
3582:
3583: for (p = actparms; p; p = TREE_CHAIN (p), i += inc)
3584: {
3585: tree type = TREE_TYPE (TREE_VALUE (p));
3586: argvec[i] = p;
3587: regvec[i] = 0;
3588: valvec[i] = 0;
3589: partial[i] = 0;
3590: arg_size[i].constant = 0;
3591: arg_size[i].var = 0;
3592: arg_offset[i] = args_size;
3593:
3594: if (type == error_mark_node)
3595: continue;
3596:
3597: /* Decide where to pass this arg. */
3598: /* regvec[i] is nonzero if all or part is passed in registers.
3599: partial[i] is nonzero if part but not all is passed in registers,
3600: and the exact value says how many words are passed in registers. */
3601:
3602: if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
1.1.1.6 root 3603: && args_size.var == 0
3604: /* error_mark_node here is a flag for the fake argument
3605: for a structure value address. */
3606: && TREE_PURPOSE (p) != error_mark_node)
1.1.1.2 root 3607: {
3608: regvec[i] = FUNCTION_ARG (args_so_far, TYPE_MODE (type), type,
3609: i < n_named_args);
3610: #ifdef FUNCTION_ARG_PARTIAL_NREGS
3611: partial[i] = FUNCTION_ARG_PARTIAL_NREGS (args_so_far,
3612: TYPE_MODE (type), type,
3613: i < n_named_args);
3614: #endif
3615: }
3616:
3617: /* Once we see at least one parm that is being passed in a register,
3618: precompute that parm and all remaining parms (if they do arithmetic)
3619: before loading any of them into their specified registers.
3620: That way we don't lose if one of them involves
3621: a function call OR a library routine that needs the same regs. */
3622: if (regvec[i] != 0)
3623: reg_parm_seen = 1;
3624:
3625: if (reg_parm_seen)
3626: {
3627: valvec[i] = expand_expr (TREE_VALUE (p), 0, VOIDmode, 0);
3628: if (GET_CODE (valvec[i]) != MEM
3629: && ! CONSTANT_P (valvec[i])
3630: && GET_CODE (valvec[i]) != CONST_DOUBLE)
3631: valvec[i] = force_reg (TYPE_MODE (type), valvec[i]);
1.1.1.4 root 3632: /* ANSI doesn't require a sequence point here,
3633: but PCC has one, so this will avoid some problems. */
3634: emit_queue ();
1.1.1.2 root 3635: }
3636:
3637: /* Increment ARGS_SO_FAR, which has info about which arg-registers
3638: have been used, etc. */
3639:
3640: FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type,
3641: i < n_named_args);
3642:
3643: /* Increment ARGS_SIZE, which is the size of all args so far. */
3644:
3645: if (regvec[i] != 0 && partial[i] == 0)
3646: /* A register-arg doesn't count. */
3647: ;
3648: else if (TYPE_MODE (type) != BLKmode)
3649: {
3650: register int size;
3651:
3652: size = GET_MODE_SIZE (TYPE_MODE (type));
3653: /* Compute how much space the push instruction will push.
3654: On many machines, pushing a byte will advance the stack
3655: pointer by a halfword. */
3656: #ifdef PUSH_ROUNDING
3657: size = PUSH_ROUNDING (size);
1.1 root 3658: #endif
1.1.1.2 root 3659: /* Compute how much space the argument should get:
1.1.1.6 root 3660: maybe pad to a multiple of the alignment for arguments. */
3661: if (none == FUNCTION_ARG_PADDING (TYPE_MODE (type), (rtx)0))
3662: arg_size[i].constant += size;
3663: else
3664: arg_size[i].constant
3665: = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
3666: / (PARM_BOUNDARY / BITS_PER_UNIT))
3667: * (PARM_BOUNDARY / BITS_PER_UNIT));
1.1.1.2 root 3668: }
3669: else
3670: {
3671: register tree size = size_in_bytes (type);
3672:
3673: /* A nonscalar. Round its size up to a multiple
3674: of the allocation unit for arguments. */
3675:
1.1.1.6 root 3676: /* Now maybe round up to multiple of PARM_BOUNDARY bits. */
3677: if (none
3678: != FUNCTION_ARG_PADDING (TYPE_MODE (type),
3679: expand_expr (size, 0, VOIDmode, 0)))
3680: size = convert_units (convert_units (size, BITS_PER_UNIT,
3681: PARM_BOUNDARY),
3682: PARM_BOUNDARY, BITS_PER_UNIT);
3683: ADD_PARM_SIZE (arg_size[i], size);
1.1.1.2 root 3684: }
3685: /* If a part of the arg was put into registers,
3686: don't include that part in the amount pushed. */
3687: arg_size[i].constant
3688: -= ((partial[i] * UNITS_PER_WORD)
3689: / (PARM_BOUNDARY / BITS_PER_UNIT)
3690: * (PARM_BOUNDARY / BITS_PER_UNIT));
3691:
3692: args_size.constant += arg_size[i].constant;
3693:
3694: if (arg_size[i].var)
3695: {
3696: ADD_PARM_SIZE (args_size, arg_size[i].var);
3697: }
3698: }
3699:
3700: /* If we have no actual push instructions, or we need a variable
3701: amount of space, make space for all the args right now.
3702: In any case, round the needed size up to multiple of STACK_BOUNDARY. */
3703:
3704: if (args_size.var != 0)
3705: {
3706: old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx);
3707: old_pending_adj = pending_stack_adjust;
3708: argblock = push_block (round_push (ARGS_SIZE_RTX (args_size)));
3709: }
3710: else if (args_size.constant != 0)
3711: {
3712: int needed = args_size.constant;
3713:
3714: #ifdef STACK_BOUNDARY
3715: needed = (needed + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES;
3716: args_size.constant = needed;
3717: #endif
3718:
3719: #ifndef PUSH_ROUNDING
3720: /* Try to reuse some or all of the pending_stack_adjust
3721: to get this space. Maybe we can avoid any pushing. */
3722: if (needed > pending_stack_adjust)
3723: {
3724: needed -= pending_stack_adjust;
3725: pending_stack_adjust = 0;
3726: }
3727: else
3728: {
3729: pending_stack_adjust -= needed;
3730: needed = 0;
3731: }
1.1.1.3 root 3732: argblock = push_block (gen_rtx (CONST_INT, VOIDmode, needed));
1.1.1.2 root 3733: #endif /* no PUSH_ROUNDING */
3734: }
3735:
3736: /* Get the function to call, in the form of RTL. */
3737: if (fndecl)
3738: /* Get a SYMBOL_REF rtx for the function address. */
3739: funexp = XEXP (DECL_RTL (fndecl), 0);
3740: else
3741: /* Generate an rtx (probably a pseudo-register) for the address. */
1.1.1.4 root 3742: {
3743: funexp = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
3744: emit_queue ();
3745: }
1.1.1.2 root 3746:
3747: /* Now actually compute the args, and push those that need pushing. */
3748:
1.1 root 3749: for (i = 0; i < num_actuals; i++)
3750: {
3751: register tree p = argvec[i];
3752: register tree pval = TREE_VALUE (p);
1.1.1.2 root 3753: int used = 0;
1.1 root 3754:
3755: /* Push the next argument. Note that it has already been converted
3756: if necessary to the type that the called function expects. */
3757:
3758: if (TREE_CODE (pval) == ERROR_MARK)
3759: ;
1.1.1.2 root 3760: else if (regvec[i] != 0 && partial[i] == 0)
3761: {
3762: /* Being passed entirely in a register. */
3763: if (valvec[i] != 0)
3764: {
3765: if (GET_MODE (valvec[i]) == BLKmode)
3766: move_block_to_reg (REGNO (regvec[i]), valvec[i],
3767: (int_size_in_bytes (TREE_TYPE (pval))
3768: / UNITS_PER_WORD));
3769: else
3770: emit_move_insn (regvec[i], valvec[i]);
3771: }
3772: else
3773: store_expr (pval, regvec[i], 0);
3774:
3775: /* Don't allow anything left on stack from computation
3776: of argument to alloca. */
3777: if (may_be_alloca)
3778: do_pending_stack_adjust ();
3779: }
1.1 root 3780: else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
3781: {
1.1.1.2 root 3782: register int size;
3783: rtx tem;
3784:
3785: /* Argument is a scalar, not entirely passed in registers.
3786: (If part is passed in registers, partial[I] says how much
3787: and emit_push_insn will take care of putting it there.)
1.1 root 3788:
3789: Push it, and if its size is less than the
3790: amount of space allocated to it,
3791: also bump stack pointer by the additional space.
3792: Note that in C the default argument promotions
3793: will prevent such mismatches. */
3794:
3795: used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
3796: /* Compute how much space the push instruction will push.
3797: On many machines, pushing a byte will advance the stack
3798: pointer by a halfword. */
1.1.1.2 root 3799: #ifdef PUSH_ROUNDING
1.1 root 3800: size = PUSH_ROUNDING (size);
1.1.1.2 root 3801: #endif
1.1 root 3802: /* Compute how much space the argument should get:
3803: round up to a multiple of the alignment for arguments. */
1.1.1.6 root 3804: if (none != FUNCTION_ARG_PADDING (TYPE_MODE (TREE_TYPE (pval)), (rtx)0))
3805: used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
3806: / (PARM_BOUNDARY / BITS_PER_UNIT))
3807: * (PARM_BOUNDARY / BITS_PER_UNIT));
1.1 root 3808:
1.1.1.2 root 3809: tem = valvec[i];
3810: if (tem == 0)
1.1.1.4 root 3811: {
3812: tem = expand_expr (pval, 0, VOIDmode, 0);
3813: /* ANSI doesn't require a sequence point here,
3814: but PCC has one, so this will avoid some problems. */
3815: emit_queue ();
3816: }
1.1.1.2 root 3817:
3818: /* Don't allow anything left on stack from computation
3819: of argument to alloca. */
3820: if (may_be_alloca)
3821: do_pending_stack_adjust ();
3822:
3823: emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), 0, 0,
3824: partial[i], regvec[i], used - size,
3825: argblock, ARGS_SIZE_RTX (arg_offset[i]));
1.1 root 3826: }
3827: else
3828: {
1.1.1.2 root 3829: register rtx tem
3830: = valvec[i] ? valvec[i] : expand_expr (pval, 0, VOIDmode, 0);
1.1 root 3831: register int excess;
1.1.1.2 root 3832: rtx size_rtx;
1.1 root 3833:
1.1.1.2 root 3834: /* Pushing a nonscalar.
3835: If part is passed in registers, partial[I] says how much
3836: and emit_push_insn will take care of putting it there. */
1.1 root 3837:
1.1.1.2 root 3838: /* Round its size up to a multiple
3839: of the allocation unit for arguments. */
1.1 root 3840:
1.1.1.2 root 3841: if (arg_size[i].var != 0)
3842: {
3843: excess = 0;
3844: size_rtx = ARGS_SIZE_RTX (arg_size[i]);
3845: }
3846: else
3847: {
3848: register tree size = size_in_bytes (TREE_TYPE (pval));
3849: /* PUSH_ROUNDING has no effect on us, because
3850: emit_push_insn for BLKmode is careful to avoid it. */
3851: excess = arg_size[i].constant - TREE_INT_CST_LOW (size);
3852: size_rtx = expand_expr (size, 0, VOIDmode, 0);
3853: }
1.1 root 3854:
1.1.1.2 root 3855: emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), size_rtx,
3856: TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT,
3857: partial[i], regvec[i], excess, argblock,
3858: ARGS_SIZE_RTX (arg_offset[i]));
3859: }
1.1 root 3860:
1.1.1.2 root 3861: /* Account for the stack space thus used. */
1.1 root 3862:
3863:
1.1.1.2 root 3864: current_args_size += arg_size[i].constant;
3865: if (arg_size[i].var)
3866: current_args_size += 1;
1.1 root 3867: }
3868:
3869: /* Perform postincrements before actually calling the function. */
3870: emit_queue ();
3871:
3872: /* Pass the function the address in which to return a structure value. */
1.1.1.6 root 3873: if (structure_value_addr && GET_CODE (struct_value_rtx) != MEM)
1.1.1.2 root 3874: emit_move_insn (struct_value_rtx, structure_value_addr);
3875:
3876: /* All arguments and registers used for the call must be set up by now! */
1.1 root 3877:
1.1.1.2 root 3878: /* ??? Other languages need a nontrivial second argument (static chain). */
3879: funexp = prepare_call_address (funexp, 0);
3880:
3881: /* Mark all register-parms as living through the call.
3882: ??? This is not quite correct, since it doesn't indicate
3883: that they are in use immediately before the call insn.
3884: Currently that doesn't matter since explicitly-used regs
3885: won't be used for reloading. But if the reloader becomes smarter,
3886: this will have to change somehow. */
3887: for (i = 0; i < num_actuals; i++)
3888: if (regvec[i] != 0)
3889: {
3890: if (partial[i] > 0)
3891: use_regs (REGNO (regvec[i]), partial[i]);
3892: else if (GET_MODE (regvec[i]) == BLKmode)
3893: use_regs (REGNO (regvec[i]),
3894: (int_size_in_bytes (TREE_TYPE (TREE_VALUE (argvec[i])))
3895: / UNITS_PER_WORD));
3896: else
3897: emit_insn (gen_rtx (USE, VOIDmode, regvec[i]));
3898: }
3899:
3900: if (structure_value_addr)
3901: emit_insn (gen_rtx (USE, VOIDmode, struct_value_rtx));
3902:
3903: /* Figure out the register where the value, if any, will come back. */
3904: valreg = 0;
3905: if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
3906: && TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
3907: valreg = hard_function_value (TREE_TYPE (exp), fndecl);
3908:
3909: /* Generate the actual call instruction. */
3910: emit_call_1 (funexp, funtype, args_size.constant,
3911: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
3912: valreg, old_current_args_size);
1.1 root 3913:
3914: /* ??? Nothing has been done here to record control flow
3915: when contained functions can do nonlocal gotos. */
3916:
1.1.1.2 root 3917: /* For calls to `setjmp', etc., inform flow.c it should complain
3918: if nonvolatile values are live. */
3919:
3920: if (is_setjmp)
3921: emit_note (IDENTIFIER_POINTER (DECL_NAME (fndecl)), NOTE_INSN_SETJMP);
3922:
3923: /* If size of args is variable, restore saved stack-pointer value. */
3924:
3925: if (args_size.var != 0)
3926: {
3927: emit_move_insn (stack_pointer_rtx, old_stack_level);
3928: pending_stack_adjust = old_pending_adj;
3929: }
3930:
1.1 root 3931: /* If value type not void, return an rtx for the value. */
3932:
1.1.1.2 root 3933: if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
3934: || ignore)
1.1 root 3935: return 0;
3936:
3937: if (structure_value_addr)
3938: {
3939: if (target)
3940: return target;
1.1.1.2 root 3941: return gen_rtx (MEM, BLKmode,
3942: memory_address (BLKmode, structure_value_addr));
1.1 root 3943: }
1.1.1.2 root 3944:
3945: if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
1.1 root 3946: {
1.1.1.2 root 3947: if (!rtx_equal_p (target, valreg))
3948: emit_move_insn (target, valreg);
3949: else
3950: /* This tells expand_inline_function to copy valreg to its target. */
3951: emit_insn (gen_rtx (USE, VOIDmode, valreg));
1.1 root 3952: return target;
3953: }
1.1.1.2 root 3954: return copy_to_reg (valreg);
1.1 root 3955: }
3956:
3957: /* Expand conditional expressions. */
3958:
3959: /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
3960: LABEL is an rtx of code CODE_LABEL, in this function and all the
3961: functions here. */
3962:
1.1.1.2 root 3963: void
1.1 root 3964: jumpifnot (exp, label)
3965: tree exp;
3966: rtx label;
3967: {
3968: do_jump (exp, label, 0);
3969: }
3970:
3971: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
3972:
1.1.1.2 root 3973: void
1.1 root 3974: jumpif (exp, label)
3975: tree exp;
3976: rtx label;
3977: {
3978: do_jump (exp, 0, label);
3979: }
3980:
3981: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
3982: the result is zero, or IF_TRUE_LABEL if the result is one.
3983: Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
3984: meaning fall through in that case.
3985:
3986: This function is responsible for optimizing cases such as
3987: &&, || and comparison operators in EXP. */
3988:
1.1.1.2 root 3989: void
1.1 root 3990: do_jump (exp, if_false_label, if_true_label)
3991: tree exp;
3992: rtx if_false_label, if_true_label;
3993: {
3994: register enum tree_code code = TREE_CODE (exp);
3995: /* Some cases need to create a label to jump to
3996: in order to properly fall through.
3997: These cases set DROP_THROUGH_LABEL nonzero. */
3998: rtx drop_through_label = 0;
3999: rtx temp;
4000: rtx comparison = 0;
4001:
4002: emit_queue ();
4003:
4004: switch (code)
4005: {
4006: case ERROR_MARK:
4007: break;
4008:
4009: case INTEGER_CST:
4010: temp = integer_zerop (exp) ? if_false_label : if_true_label;
4011: if (temp)
4012: emit_jump (temp);
4013: break;
4014:
4015: case ADDR_EXPR:
4016: /* The address of something can never be zero. */
4017: if (if_true_label)
4018: emit_jump (if_true_label);
4019: break;
1.1.1.6 root 4020:
1.1 root 4021: case NOP_EXPR:
4022: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
4023: break;
4024:
4025: case TRUTH_NOT_EXPR:
4026: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
4027: break;
4028:
4029: case TRUTH_ANDIF_EXPR:
4030: if (if_false_label == 0)
4031: if_false_label = drop_through_label = gen_label_rtx ();
4032: do_jump (TREE_OPERAND (exp, 0), if_false_label, 0);
4033: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
4034: break;
4035:
4036: case TRUTH_ORIF_EXPR:
4037: if (if_true_label == 0)
4038: if_true_label = drop_through_label = gen_label_rtx ();
4039: do_jump (TREE_OPERAND (exp, 0), 0, if_true_label);
4040: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
4041: break;
4042:
4043: case COMPOUND_EXPR:
1.1.1.2 root 4044: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
1.1 root 4045: emit_queue ();
4046: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
4047: break;
4048:
4049: case COND_EXPR:
4050: {
4051: register rtx label1 = gen_label_rtx ();
4052: drop_through_label = gen_label_rtx ();
4053: do_jump (TREE_OPERAND (exp, 0), label1, 0);
4054: /* Now the THEN-expression. */
4055: do_jump (TREE_OPERAND (exp, 1),
4056: if_false_label ? if_false_label : drop_through_label,
4057: if_true_label ? if_true_label : drop_through_label);
4058: emit_label (label1);
4059: /* Now the ELSE-expression. */
4060: do_jump (TREE_OPERAND (exp, 2),
4061: if_false_label ? if_false_label : drop_through_label,
4062: if_true_label ? if_true_label : drop_through_label);
4063: }
4064: break;
4065:
4066: case EQ_EXPR:
4067: comparison = compare (exp, EQ, EQ, EQ, EQ);
4068: break;
4069:
4070: case NE_EXPR:
4071: comparison = compare (exp, NE, NE, NE, NE);
4072: break;
4073:
4074: case LT_EXPR:
4075: comparison = compare (exp, LT, LTU, GT, GTU);
4076: break;
4077:
4078: case LE_EXPR:
4079: comparison = compare (exp, LE, LEU, GE, GEU);
4080: break;
4081:
4082: case GT_EXPR:
4083: comparison = compare (exp, GT, GTU, LT, LTU);
4084: break;
4085:
4086: case GE_EXPR:
4087: comparison = compare (exp, GE, GEU, LE, LEU);
4088: break;
4089:
4090: default:
4091: temp = expand_expr (exp, 0, VOIDmode, 0);
1.1.1.2 root 4092: /* Copy to register to avoid generating bad insns by cse
4093: from (set (mem ...) (arithop)) (set (cc0) (mem ...)). */
4094: if (!cse_not_expected && GET_CODE (temp) == MEM)
4095: temp = copy_to_reg (temp);
1.1 root 4096: do_pending_stack_adjust ();
1.1.1.2 root 4097: {
4098: rtx zero;
4099: if (GET_MODE (temp) == SFmode)
4100: zero = fconst0_rtx;
4101: else if (GET_MODE (temp) == DFmode)
4102: zero = dconst0_rtx;
4103: else
4104: zero = const0_rtx;
1.1 root 4105:
1.1.1.2 root 4106: if (GET_CODE (temp) == CONST_INT)
4107: comparison = compare_constants (NE, 0,
4108: INTVAL (temp), 0, BITS_PER_WORD);
4109: else if (GET_MODE (temp) != VOIDmode)
4110: comparison = compare1 (temp, zero, NE, NE, 0, GET_MODE (temp));
4111: else
4112: abort ();
4113: }
1.1 root 4114: }
4115:
1.1.1.2 root 4116: /* Do any postincrements in the expression that was tested. */
4117: emit_queue ();
4118:
1.1 root 4119: /* If COMPARISON is nonzero here, it is an rtx that can be substituted
4120: straight into a conditional jump instruction as the jump condition.
4121: Otherwise, all the work has been done already. */
4122:
1.1.1.2 root 4123: if (comparison == const1_rtx)
4124: {
4125: if (if_true_label)
4126: emit_jump (if_true_label);
4127: }
4128: else if (comparison == const0_rtx)
4129: {
4130: if (if_false_label)
4131: emit_jump (if_false_label);
4132: }
4133: else if (comparison)
4134: {
4135: if (if_true_label)
4136: {
4137: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
4138: gen_rtx (IF_THEN_ELSE, VOIDmode, comparison,
4139: gen_rtx (LABEL_REF, VOIDmode,
4140: if_true_label),
4141: pc_rtx)));
4142: if (if_false_label)
4143: emit_jump (if_false_label);
4144: }
4145: else if (if_false_label)
4146: {
4147: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
4148: gen_rtx (IF_THEN_ELSE, VOIDmode, comparison,
4149: pc_rtx,
4150: gen_rtx (LABEL_REF, VOIDmode,
4151: if_false_label))));
4152: }
4153: }
1.1 root 4154:
4155: if (drop_through_label)
4156: emit_label (drop_through_label);
4157: }
4158:
1.1.1.2 root 4159: /* Compare two integer constant rtx's, OP0 and OP1.
4160: The comparison operation is OPERATION.
4161: Return an rtx representing the value 1 or 0.
4162: WIDTH is the width in bits that is significant. */
4163:
4164: static rtx
4165: compare_constants (operation, unsignedp, op0, op1, width)
4166: enum rtx_code operation;
4167: int unsignedp;
4168: int op0, op1;
4169: int width;
4170: {
4171: int val;
4172:
4173: /* Sign-extend or zero-extend the operands to a full word
4174: from an initial width of WIDTH bits. */
4175: if (width < HOST_BITS_PER_INT)
4176: {
4177: op0 &= (1 << width) - 1;
4178: op1 &= (1 << width) - 1;
4179:
4180: if (! unsignedp)
4181: {
4182: if (op0 & (1 << (width - 1)))
4183: op0 |= ((-1) << width);
4184: if (op1 & (1 << (width - 1)))
4185: op1 |= ((-1) << width);
4186: }
4187: }
4188:
4189: switch (operation)
4190: {
4191: case EQ:
4192: val = op0 == op1;
4193: break;
4194:
4195: case NE:
4196: val = op0 != op1;
4197: break;
4198:
4199: case GT:
4200: case GTU:
4201: val = op0 > op1;
4202: break;
4203:
4204: case LT:
4205: case LTU:
4206: val = op0 < op1;
4207: break;
4208:
4209: case GE:
4210: case GEU:
4211: val = op0 >= op1;
4212: break;
4213:
4214: case LE:
4215: case LEU:
4216: val = op0 <= op1;
4217: }
4218:
4219: return val ? const1_rtx : const0_rtx;
4220: }
4221:
1.1 root 4222: /* Generate code for a comparison expression EXP
4223: (including code to compute the values to be compared)
4224: and set (CC0) according to the result.
4225: SIGNED_FORWARD should be the rtx operation for this comparison for
4226: signed data; UNSIGNED_FORWARD, likewise for use if data is unsigned.
4227: SIGNED_REVERSE and UNSIGNED_REVERSE are used if it is desirable
4228: to interchange the operands for the compare instruction.
4229:
4230: We force a stack adjustment unless there are currently
4231: things pushed on the stack that aren't yet used. */
4232:
4233: static rtx
4234: compare (exp, signed_forward, unsigned_forward,
4235: signed_reverse, unsigned_reverse)
4236: register tree exp;
4237: enum rtx_code signed_forward, unsigned_forward;
4238: enum rtx_code signed_reverse, unsigned_reverse;
4239: {
1.1.1.2 root 4240:
1.1 root 4241: register rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
4242: register rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
4243: register enum machine_mode mode = GET_MODE (op0);
4244: int unsignedp;
4245:
4246: /* If one operand is 0, make it the second one. */
4247:
4248: if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
4249: {
4250: rtx tem = op0;
4251: op0 = op1;
4252: op1 = tem;
4253: signed_forward = signed_reverse;
4254: unsigned_forward = unsigned_reverse;
4255: }
4256:
1.1.1.2 root 4257: if (flag_force_mem)
1.1 root 4258: {
4259: op0 = force_not_mem (op0);
4260: op1 = force_not_mem (op1);
4261: }
4262:
4263: do_pending_stack_adjust ();
4264:
1.1.1.2 root 4265: unsignedp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))
4266: || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))));
4267:
4268: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT)
4269: return compare_constants (signed_forward, unsignedp,
4270: INTVAL (op0), INTVAL (op1),
4271: GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))));
1.1 root 4272:
4273: emit_cmp_insn (op0, op1,
4274: (mode == BLKmode) ? expr_size (TREE_OPERAND (exp, 0)) : 0,
4275: unsignedp);
4276:
4277: return gen_rtx ((unsignedp ? unsigned_forward : signed_forward),
4278: VOIDmode, cc0_rtx, const0_rtx);
4279: }
4280:
4281: /* Like compare but expects the values to compare as two rtx's.
4282: The decision as to signed or unsigned comparison must be made by the caller.
4283: BLKmode is not allowed. */
4284:
4285: static rtx
1.1.1.2 root 4286: compare1 (op0, op1, forward_op, reverse_op, unsignedp, mode)
1.1 root 4287: register rtx op0, op1;
4288: enum rtx_code forward_op, reverse_op;
4289: int unsignedp;
1.1.1.2 root 4290: enum machine_mode mode;
1.1 root 4291: {
4292: /* If one operand is 0, make it the second one. */
4293:
4294: if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
4295: {
4296: rtx tem = op0;
4297: op0 = op1;
4298: op1 = tem;
4299: forward_op = reverse_op;
4300: }
4301:
1.1.1.2 root 4302: if (flag_force_mem)
1.1 root 4303: {
4304: op0 = force_not_mem (op0);
4305: op1 = force_not_mem (op1);
4306: }
4307:
4308: do_pending_stack_adjust ();
4309:
1.1.1.2 root 4310: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT)
4311: return compare_constants (forward_op, unsignedp,
4312: INTVAL (op0), INTVAL (op1),
4313: GET_MODE_BITSIZE (mode));
4314:
1.1 root 4315: emit_cmp_insn (op0, op1, 0, unsignedp);
4316:
4317: return gen_rtx (forward_op, VOIDmode, cc0_rtx, const0_rtx);
4318: }
4319:
4320: /* Generate code to calculate EXP using a store-flag instruction
4321: and return an rtx for the result.
4322: If TARGET is nonzero, store the result there if convenient.
4323:
4324: Return zero if there is no suitable set-flag instruction
4325: available on this machine. */
4326:
4327: static rtx
1.1.1.2 root 4328: do_store_flag (exp, target, mode)
1.1 root 4329: tree exp;
4330: rtx target;
1.1.1.2 root 4331: enum machine_mode mode;
1.1 root 4332: {
4333: register enum tree_code code = TREE_CODE (exp);
4334: register rtx comparison = 0;
1.1.1.2 root 4335: enum machine_mode compare_mode;
1.1 root 4336:
4337: switch (code)
4338: {
1.1.1.2 root 4339: #ifdef HAVE_seq
1.1 root 4340: case EQ_EXPR:
1.1.1.2 root 4341: if (HAVE_seq)
4342: {
4343: comparison = compare (exp, EQ, EQ, EQ, EQ);
4344: compare_mode = insn_operand_mode[(int) CODE_FOR_seq][0];
4345: }
1.1 root 4346: break;
4347: #endif
4348:
1.1.1.2 root 4349: #ifdef HAVE_sne
1.1 root 4350: case NE_EXPR:
1.1.1.2 root 4351: if (HAVE_sne)
4352: {
4353: comparison = compare (exp, NE, NE, NE, NE);
4354: compare_mode = insn_operand_mode[(int) CODE_FOR_sne][0];
4355: }
1.1 root 4356: break;
4357: #endif
4358:
1.1.1.2 root 4359: #if defined (HAVE_slt) && defined (HAVE_sltu) && defined (HAVE_sgt) && defined (HAVE_sgtu)
1.1 root 4360: case LT_EXPR:
1.1.1.2 root 4361: if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu)
4362: {
4363: comparison = compare (exp, LT, LTU, GT, GTU);
4364: compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0];
4365: }
1.1 root 4366: break;
4367:
4368: case GT_EXPR:
1.1.1.2 root 4369: if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu)
4370: {
4371: comparison = compare (exp, GT, GTU, LT, LTU);
4372: compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0];
4373: }
1.1 root 4374: break;
4375: #endif
4376:
1.1.1.2 root 4377: #if defined (HAVE_sle) && defined (HAVE_sleu) && defined (HAVE_sge) && defined (HAVE_sgeu)
1.1 root 4378: case LE_EXPR:
1.1.1.2 root 4379: if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu)
4380: {
4381: comparison = compare (exp, LE, LEU, GE, GEU);
4382: compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0];
4383: }
1.1 root 4384: break;
4385:
4386: case GE_EXPR:
1.1.1.2 root 4387: if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu)
4388: {
4389: comparison = compare (exp, GE, GEU, LE, LEU);
4390: compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0];
4391: }
1.1 root 4392: break;
4393: #endif
4394: }
4395: if (comparison == 0)
4396: return 0;
4397:
1.1.1.2 root 4398: if (target == 0 || GET_MODE (target) != mode
4399: || (mode != compare_mode && GET_CODE (target) != REG))
4400: target = gen_reg_rtx (mode);
4401:
4402: /* Store the comparison in its proper mode. */
4403: if (GET_MODE (target) != compare_mode)
4404: emit_insn (gen_rtx (SET, VOIDmode,
4405: gen_rtx (SUBREG, compare_mode, target, 0),
4406: comparison));
4407: else
4408: emit_insn (gen_rtx (SET, VOIDmode, target, comparison));
4409:
4410: #if STORE_FLAG_VALUE != 1
4411: expand_bit_and (mode, target, const1_rtx, target);
4412: #endif
1.1 root 4413: return target;
4414: }
4415:
4416: /* Generate a tablejump instruction (used for switch statements). */
4417:
4418: #ifdef HAVE_tablejump
4419:
4420: /* INDEX is the value being switched on, with the lowest value
4421: in the table already subtracted.
4422: RANGE is the length of the jump table.
4423: TABLE_LABEL is a CODE_LABEL rtx for the table itself.
1.1.1.2 root 4424:
1.1 root 4425: DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
4426: index value is out of range. */
4427:
4428: void
4429: do_tablejump (index, range, table_label, default_label)
4430: rtx index, range, table_label, default_label;
4431: {
4432: register rtx temp;
4433:
4434: emit_cmp_insn (range, index, 0);
1.1.1.2 root 4435: emit_jump_insn (gen_bltu (default_label));
1.1.1.4 root 4436: /* If flag_force_addr were to affect this address
4437: it could interfere with the tricky assumptions made
4438: about addresses that contain label-refs,
4439: which may be valid only very near the tablejump itself. */
4440: index = memory_address_noforce
4441: (CASE_VECTOR_MODE,
4442: gen_rtx (PLUS, Pmode,
4443: gen_rtx (MULT, Pmode, index,
4444: gen_rtx (CONST_INT, VOIDmode,
4445: GET_MODE_SIZE (CASE_VECTOR_MODE))),
4446: gen_rtx (LABEL_REF, VOIDmode, table_label)));
1.1 root 4447: temp = gen_reg_rtx (CASE_VECTOR_MODE);
4448: convert_move (temp, gen_rtx (MEM, CASE_VECTOR_MODE, index), 0);
4449:
1.1.1.2 root 4450: emit_jump_insn (gen_tablejump (temp, table_label));
1.1 root 4451: }
4452:
1.1.1.2 root 4453: #endif /* HAVE_tablejump */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.