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