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