00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "toplev.h"
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "tm_p.h"
00031 #include "flags.h"
00032 #include "function.h"
00033 #include "expr.h"
00034 #include "optabs.h"
00035 #include "hard-reg-set.h"
00036 #include "insn-config.h"
00037 #include "ggc.h"
00038 #include "recog.h"
00039 #include "langhooks.h"
00040
00041 static rtx break_out_memory_refs (rtx);
00042 static void emit_stack_probe (rtx);
00043
00044
00045
00046
00047 HOST_WIDE_INT
00048 trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
00049 {
00050 int width = GET_MODE_BITSIZE (mode);
00051
00052
00053 gcc_assert (SCALAR_INT_MODE_P (mode));
00054
00055
00056 if (mode == BImode)
00057 return c & 1 ? STORE_FLAG_VALUE : 0;
00058
00059
00060
00061 if (width < HOST_BITS_PER_WIDE_INT)
00062 {
00063 HOST_WIDE_INT sign = 1;
00064 sign <<= width - 1;
00065 c &= (sign << 1) - 1;
00066 c ^= sign;
00067 c -= sign;
00068 }
00069
00070 return c;
00071 }
00072
00073
00074
00075 rtx
00076 plus_constant (rtx x, HOST_WIDE_INT c)
00077 {
00078 RTX_CODE code;
00079 rtx y;
00080 enum machine_mode mode;
00081 rtx tem;
00082 int all_constant = 0;
00083
00084 if (c == 0)
00085 return x;
00086
00087 restart:
00088
00089 code = GET_CODE (x);
00090 mode = GET_MODE (x);
00091 y = x;
00092
00093 switch (code)
00094 {
00095 case CONST_INT:
00096 return GEN_INT (INTVAL (x) + c);
00097
00098 case CONST_DOUBLE:
00099 {
00100 unsigned HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x);
00101 HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x);
00102 unsigned HOST_WIDE_INT l2 = c;
00103 HOST_WIDE_INT h2 = c < 0 ? ~0 : 0;
00104 unsigned HOST_WIDE_INT lv;
00105 HOST_WIDE_INT hv;
00106
00107 add_double (l1, h1, l2, h2, &lv, &hv);
00108
00109 return immed_double_const (lv, hv, VOIDmode);
00110 }
00111
00112 case MEM:
00113
00114
00115
00116 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
00117 && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
00118 {
00119 tem
00120 = force_const_mem (GET_MODE (x),
00121 plus_constant (get_pool_constant (XEXP (x, 0)),
00122 c));
00123 if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
00124 return tem;
00125 }
00126 break;
00127
00128 case CONST:
00129
00130
00131 x = XEXP (x, 0);
00132 all_constant = 1;
00133 goto restart;
00134
00135 case SYMBOL_REF:
00136 case LABEL_REF:
00137 all_constant = 1;
00138 break;
00139
00140 case PLUS:
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
00154 {
00155 c += INTVAL (XEXP (x, 1));
00156
00157 if (GET_MODE (x) != VOIDmode)
00158 c = trunc_int_for_mode (c, GET_MODE (x));
00159
00160 x = XEXP (x, 0);
00161 goto restart;
00162 }
00163 else if (CONSTANT_P (XEXP (x, 1)))
00164 {
00165 x = gen_rtx_PLUS (mode, XEXP (x, 0), plus_constant (XEXP (x, 1), c));
00166 c = 0;
00167 }
00168 else if (find_constant_term_loc (&y))
00169 {
00170
00171
00172 rtx copy = copy_rtx (x);
00173 rtx *const_loc = find_constant_term_loc (©);
00174
00175 *const_loc = plus_constant (*const_loc, c);
00176 x = copy;
00177 c = 0;
00178 }
00179 break;
00180
00181 default:
00182 break;
00183 }
00184
00185 if (c != 0)
00186 x = gen_rtx_PLUS (mode, x, GEN_INT (c));
00187
00188 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
00189 return x;
00190 else if (all_constant)
00191 return gen_rtx_CONST (mode, x);
00192 else
00193 return x;
00194 }
00195
00196
00197
00198
00199
00200
00201 rtx
00202 eliminate_constant_term (rtx x, rtx *constptr)
00203 {
00204 rtx x0, x1;
00205 rtx tem;
00206
00207 if (GET_CODE (x) != PLUS)
00208 return x;
00209
00210
00211 if (GET_CODE (XEXP (x, 1)) == CONST_INT
00212 && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
00213 XEXP (x, 1)))
00214 && GET_CODE (tem) == CONST_INT)
00215 {
00216 *constptr = tem;
00217 return eliminate_constant_term (XEXP (x, 0), constptr);
00218 }
00219
00220 tem = const0_rtx;
00221 x0 = eliminate_constant_term (XEXP (x, 0), &tem);
00222 x1 = eliminate_constant_term (XEXP (x, 1), &tem);
00223 if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
00224 && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x),
00225 *constptr, tem))
00226 && GET_CODE (tem) == CONST_INT)
00227 {
00228 *constptr = tem;
00229 return gen_rtx_PLUS (GET_MODE (x), x0, x1);
00230 }
00231
00232 return x;
00233 }
00234
00235
00236
00237 rtx
00238 expr_size (tree exp)
00239 {
00240 tree size;
00241
00242 if (TREE_CODE (exp) == WITH_SIZE_EXPR)
00243 size = TREE_OPERAND (exp, 1);
00244 else
00245 size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
00246
00247 return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
00248 }
00249
00250
00251
00252
00253 HOST_WIDE_INT
00254 int_expr_size (tree exp)
00255 {
00256 tree size;
00257
00258 if (TREE_CODE (exp) == WITH_SIZE_EXPR)
00259 size = TREE_OPERAND (exp, 1);
00260 else
00261 size = lang_hooks.expr_size (exp);
00262
00263 if (size == 0 || !host_integerp (size, 0))
00264 return -1;
00265
00266 return tree_low_cst (size, 0);
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 static rtx
00286 break_out_memory_refs (rtx x)
00287 {
00288 if (MEM_P (x)
00289 || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
00290 && GET_MODE (x) != VOIDmode))
00291 x = force_reg (GET_MODE (x), x);
00292 else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
00293 || GET_CODE (x) == MULT)
00294 {
00295 rtx op0 = break_out_memory_refs (XEXP (x, 0));
00296 rtx op1 = break_out_memory_refs (XEXP (x, 1));
00297
00298 if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
00299 x = gen_rtx_fmt_ee (GET_CODE (x), Pmode, op0, op1);
00300 }
00301
00302 return x;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 rtx
00312 convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
00313 rtx x)
00314 {
00315 #ifndef POINTERS_EXTEND_UNSIGNED
00316 return x;
00317 #else
00318 enum machine_mode from_mode;
00319 rtx temp;
00320 enum rtx_code code;
00321
00322
00323 if (GET_MODE (x) == to_mode)
00324 return x;
00325
00326 from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
00327
00328
00329
00330 switch (GET_CODE (x))
00331 {
00332 case CONST_INT:
00333 case CONST_DOUBLE:
00334 if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode))
00335 code = TRUNCATE;
00336 else if (POINTERS_EXTEND_UNSIGNED < 0)
00337 break;
00338 else if (POINTERS_EXTEND_UNSIGNED > 0)
00339 code = ZERO_EXTEND;
00340 else
00341 code = SIGN_EXTEND;
00342 temp = simplify_unary_operation (code, to_mode, x, from_mode);
00343 if (temp)
00344 return temp;
00345 break;
00346
00347 case SUBREG:
00348 if ((SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
00349 && GET_MODE (SUBREG_REG (x)) == to_mode)
00350 return SUBREG_REG (x);
00351 break;
00352
00353 case LABEL_REF:
00354 temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
00355 LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
00356 return temp;
00357 break;
00358
00359 case SYMBOL_REF:
00360 temp = shallow_copy_rtx (x);
00361 PUT_MODE (temp, to_mode);
00362 return temp;
00363 break;
00364
00365 case CONST:
00366 return gen_rtx_CONST (to_mode,
00367 convert_memory_address (to_mode, XEXP (x, 0)));
00368 break;
00369
00370 case PLUS:
00371 case MULT:
00372
00373
00374
00375
00376 if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
00377 || (GET_CODE (x) == PLUS
00378 && GET_CODE (XEXP (x, 1)) == CONST_INT
00379 && XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))))
00380 return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
00381 convert_memory_address (to_mode, XEXP (x, 0)),
00382 XEXP (x, 1));
00383 break;
00384
00385 default:
00386 break;
00387 }
00388
00389 return convert_modes (to_mode, from_mode,
00390 x, POINTERS_EXTEND_UNSIGNED);
00391 #endif
00392 }
00393
00394
00395
00396
00397
00398 rtx
00399 memory_address (enum machine_mode mode, rtx x)
00400 {
00401 rtx oldx = x;
00402
00403 x = convert_memory_address (Pmode, x);
00404
00405
00406
00407 if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
00408 x = force_reg (Pmode, x);
00409
00410
00411
00412
00413
00414 else
00415 {
00416 if (! cse_not_expected && !REG_P (x))
00417 x = break_out_memory_refs (x);
00418
00419
00420 if (memory_address_p (mode, x))
00421 goto win;
00422
00423
00424
00425 if (memory_address_p (mode, oldx))
00426 goto win2;
00427
00428
00429
00430
00431
00432 LEGITIMIZE_ADDRESS (x, oldx, mode, win);
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 if (GET_CODE (x) == PLUS)
00444 {
00445 rtx constant_term = const0_rtx;
00446 rtx y = eliminate_constant_term (x, &constant_term);
00447 if (constant_term == const0_rtx
00448 || ! memory_address_p (mode, y))
00449 x = force_operand (x, NULL_RTX);
00450 else
00451 {
00452 y = gen_rtx_PLUS (GET_MODE (x), copy_to_reg (y), constant_term);
00453 if (! memory_address_p (mode, y))
00454 x = force_operand (x, NULL_RTX);
00455 else
00456 x = y;
00457 }
00458 }
00459
00460 else if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
00461 x = force_operand (x, NULL_RTX);
00462
00463
00464
00465 else if (REG_P (x))
00466 x = copy_to_reg (x);
00467
00468
00469
00470 else
00471 x = force_reg (Pmode, x);
00472
00473 goto done;
00474
00475 win2:
00476 x = oldx;
00477 win:
00478 if (flag_force_addr && ! cse_not_expected && !REG_P (x)
00479
00480 && ! (GET_CODE (x) == PLUS
00481 && (XEXP (x, 0) == virtual_stack_vars_rtx
00482 || XEXP (x, 0) == virtual_incoming_args_rtx)))
00483 {
00484 if (general_operand (x, Pmode))
00485 x = force_reg (Pmode, x);
00486 else
00487 x = force_operand (x, NULL_RTX);
00488 }
00489 }
00490
00491 done:
00492
00493
00494
00495 if (oldx == x)
00496 return x;
00497 else if (REG_P (x))
00498 mark_reg_pointer (x, BITS_PER_UNIT);
00499 else if (GET_CODE (x) == PLUS
00500 && REG_P (XEXP (x, 0))
00501 && GET_CODE (XEXP (x, 1)) == CONST_INT)
00502 mark_reg_pointer (XEXP (x, 0), BITS_PER_UNIT);
00503
00504
00505
00506 update_temp_slot_address (oldx, x);
00507
00508 return x;
00509 }
00510
00511
00512
00513 rtx
00514 memory_address_noforce (enum machine_mode mode, rtx x)
00515 {
00516 int ambient_force_addr = flag_force_addr;
00517 rtx val;
00518
00519 flag_force_addr = 0;
00520 val = memory_address (mode, x);
00521 flag_force_addr = ambient_force_addr;
00522 return val;
00523 }
00524
00525
00526
00527
00528 rtx
00529 validize_mem (rtx ref)
00530 {
00531 if (!MEM_P (ref))
00532 return ref;
00533 if (! (flag_force_addr && CONSTANT_ADDRESS_P (XEXP (ref, 0)))
00534 && memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
00535 return ref;
00536
00537
00538 return replace_equiv_address (ref, XEXP (ref, 0));
00539 }
00540
00541
00542
00543 rtx
00544 copy_to_reg (rtx x)
00545 {
00546 rtx temp = gen_reg_rtx (GET_MODE (x));
00547
00548
00549
00550 if (! general_operand (x, VOIDmode))
00551 x = force_operand (x, temp);
00552
00553 if (x != temp)
00554 emit_move_insn (temp, x);
00555
00556 return temp;
00557 }
00558
00559
00560
00561
00562 rtx
00563 copy_addr_to_reg (rtx x)
00564 {
00565 return copy_to_mode_reg (Pmode, x);
00566 }
00567
00568
00569
00570
00571 rtx
00572 copy_to_mode_reg (enum machine_mode mode, rtx x)
00573 {
00574 rtx temp = gen_reg_rtx (mode);
00575
00576
00577
00578 if (! general_operand (x, VOIDmode))
00579 x = force_operand (x, temp);
00580
00581 gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
00582 if (x != temp)
00583 emit_move_insn (temp, x);
00584 return temp;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 rtx
00596 force_reg (enum machine_mode mode, rtx x)
00597 {
00598 rtx temp, insn, set;
00599
00600 if (REG_P (x))
00601 return x;
00602
00603 if (general_operand (x, mode))
00604 {
00605 temp = gen_reg_rtx (mode);
00606 insn = emit_move_insn (temp, x);
00607 }
00608 else
00609 {
00610 temp = force_operand (x, NULL_RTX);
00611 if (REG_P (temp))
00612 insn = get_last_insn ();
00613 else
00614 {
00615 rtx temp2 = gen_reg_rtx (mode);
00616 insn = emit_move_insn (temp2, temp);
00617 temp = temp2;
00618 }
00619 }
00620
00621
00622
00623
00624 if (CONSTANT_P (x)
00625 && (set = single_set (insn)) != 0
00626 && SET_DEST (set) == temp
00627 && ! rtx_equal_p (x, SET_SRC (set)))
00628 set_unique_reg_note (insn, REG_EQUAL, x);
00629
00630
00631
00632 {
00633 unsigned align = 0;
00634 if (GET_CODE (x) == SYMBOL_REF)
00635 {
00636 align = BITS_PER_UNIT;
00637 if (SYMBOL_REF_DECL (x) && DECL_P (SYMBOL_REF_DECL (x)))
00638 align = DECL_ALIGN (SYMBOL_REF_DECL (x));
00639 }
00640 else if (GET_CODE (x) == LABEL_REF)
00641 align = BITS_PER_UNIT;
00642 else if (GET_CODE (x) == CONST
00643 && GET_CODE (XEXP (x, 0)) == PLUS
00644 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
00645 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
00646 {
00647 rtx s = XEXP (XEXP (x, 0), 0);
00648 rtx c = XEXP (XEXP (x, 0), 1);
00649 unsigned sa, ca;
00650
00651 sa = BITS_PER_UNIT;
00652 if (SYMBOL_REF_DECL (s) && DECL_P (SYMBOL_REF_DECL (s)))
00653 sa = DECL_ALIGN (SYMBOL_REF_DECL (s));
00654
00655 ca = exact_log2 (INTVAL (c) & -INTVAL (c)) * BITS_PER_UNIT;
00656
00657 align = MIN (sa, ca);
00658 }
00659
00660 if (align)
00661 mark_reg_pointer (temp, align);
00662 }
00663
00664 return temp;
00665 }
00666
00667
00668
00669
00670 rtx
00671 force_not_mem (rtx x)
00672 {
00673 rtx temp;
00674
00675 if (!MEM_P (x) || GET_MODE (x) == BLKmode)
00676 return x;
00677
00678 temp = gen_reg_rtx (GET_MODE (x));
00679
00680 if (MEM_POINTER (x))
00681 REG_POINTER (temp) = 1;
00682
00683 emit_move_insn (temp, x);
00684 return temp;
00685 }
00686
00687
00688
00689
00690
00691 rtx
00692 copy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode)
00693 {
00694 rtx temp;
00695
00696 if (target && REG_P (target))
00697 temp = target;
00698 else
00699 temp = gen_reg_rtx (mode);
00700
00701 emit_move_insn (temp, x);
00702 return temp;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711 #if defined(PROMOTE_MODE) && !defined(PROMOTE_FUNCTION_MODE)
00712 #define PROMOTE_FUNCTION_MODE PROMOTE_MODE
00713 #endif
00714
00715 enum machine_mode
00716 promote_mode (tree type, enum machine_mode mode, int *punsignedp,
00717 int for_call ATTRIBUTE_UNUSED)
00718 {
00719 enum tree_code code = TREE_CODE (type);
00720 int unsignedp = *punsignedp;
00721
00722 #ifndef PROMOTE_MODE
00723 if (! for_call)
00724 return mode;
00725 #endif
00726
00727 switch (code)
00728 {
00729 #ifdef PROMOTE_FUNCTION_MODE
00730 case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
00731 case CHAR_TYPE: case REAL_TYPE: case OFFSET_TYPE:
00732 #ifdef PROMOTE_MODE
00733 if (for_call)
00734 {
00735 #endif
00736 PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
00737 #ifdef PROMOTE_MODE
00738 }
00739 else
00740 {
00741 PROMOTE_MODE (mode, unsignedp, type);
00742 }
00743 #endif
00744 break;
00745 #endif
00746
00747 #ifdef POINTERS_EXTEND_UNSIGNED
00748 case REFERENCE_TYPE:
00749 case POINTER_TYPE:
00750 mode = Pmode;
00751 unsignedp = POINTERS_EXTEND_UNSIGNED;
00752 break;
00753 #endif
00754
00755 default:
00756 break;
00757 }
00758
00759 *punsignedp = unsignedp;
00760 return mode;
00761 }
00762
00763
00764
00765
00766 void
00767 adjust_stack (rtx adjust)
00768 {
00769 rtx temp;
00770
00771 if (adjust == const0_rtx)
00772 return;
00773
00774
00775
00776 if (GET_CODE (adjust) == CONST_INT)
00777 stack_pointer_delta -= INTVAL (adjust);
00778
00779 temp = expand_binop (Pmode,
00780 #ifdef STACK_GROWS_DOWNWARD
00781 add_optab,
00782 #else
00783 sub_optab,
00784 #endif
00785 stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
00786 OPTAB_LIB_WIDEN);
00787
00788 if (temp != stack_pointer_rtx)
00789 emit_move_insn (stack_pointer_rtx, temp);
00790 }
00791
00792
00793
00794
00795 void
00796 anti_adjust_stack (rtx adjust)
00797 {
00798 rtx temp;
00799
00800 if (adjust == const0_rtx)
00801 return;
00802
00803
00804
00805 if (GET_CODE (adjust) == CONST_INT)
00806 stack_pointer_delta += INTVAL (adjust);
00807
00808 temp = expand_binop (Pmode,
00809 #ifdef STACK_GROWS_DOWNWARD
00810 sub_optab,
00811 #else
00812 add_optab,
00813 #endif
00814 stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
00815 OPTAB_LIB_WIDEN);
00816
00817 if (temp != stack_pointer_rtx)
00818 emit_move_insn (stack_pointer_rtx, temp);
00819 }
00820
00821
00822
00823
00824 static rtx
00825 round_push (rtx size)
00826 {
00827 int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
00828
00829 if (align == 1)
00830 return size;
00831
00832 if (GET_CODE (size) == CONST_INT)
00833 {
00834 HOST_WIDE_INT new = (INTVAL (size) + align - 1) / align * align;
00835
00836 if (INTVAL (size) != new)
00837 size = GEN_INT (new);
00838 }
00839 else
00840 {
00841
00842
00843
00844 size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1),
00845 NULL_RTX, 1, OPTAB_LIB_WIDEN);
00846 size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align),
00847 NULL_RTX, 1);
00848 size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
00849 }
00850
00851 return size;
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862 void
00863 emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
00864 {
00865 rtx sa = *psave;
00866
00867 rtx (*fcn) (rtx, rtx) = gen_move_insn;
00868 enum machine_mode mode = STACK_SAVEAREA_MODE (save_level);
00869
00870
00871 switch (save_level)
00872 {
00873 #ifdef HAVE_save_stack_block
00874 case SAVE_BLOCK:
00875 if (HAVE_save_stack_block)
00876 fcn = gen_save_stack_block;
00877 break;
00878 #endif
00879 #ifdef HAVE_save_stack_function
00880 case SAVE_FUNCTION:
00881 if (HAVE_save_stack_function)
00882 fcn = gen_save_stack_function;
00883 break;
00884 #endif
00885 #ifdef HAVE_save_stack_nonlocal
00886 case SAVE_NONLOCAL:
00887 if (HAVE_save_stack_nonlocal)
00888 fcn = gen_save_stack_nonlocal;
00889 break;
00890 #endif
00891 default:
00892 break;
00893 }
00894
00895
00896
00897
00898 if (sa == 0)
00899 {
00900 if (mode != VOIDmode)
00901 {
00902 if (save_level == SAVE_NONLOCAL)
00903 *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
00904 else
00905 *psave = sa = gen_reg_rtx (mode);
00906 }
00907 }
00908
00909 if (after)
00910 {
00911 rtx seq;
00912
00913 start_sequence ();
00914 do_pending_stack_adjust ();
00915
00916
00917 if (sa != 0)
00918 sa = validize_mem (sa);
00919 emit_insn (fcn (sa, stack_pointer_rtx));
00920 seq = get_insns ();
00921 end_sequence ();
00922 emit_insn_after (seq, after);
00923 }
00924 else
00925 {
00926 do_pending_stack_adjust ();
00927 if (sa != 0)
00928 sa = validize_mem (sa);
00929 emit_insn (fcn (sa, stack_pointer_rtx));
00930 }
00931 }
00932
00933
00934
00935
00936
00937
00938
00939 void
00940 emit_stack_restore (enum save_level save_level, rtx sa, rtx after)
00941 {
00942
00943 rtx (*fcn) (rtx, rtx) = gen_move_insn;
00944
00945
00946 switch (save_level)
00947 {
00948 #ifdef HAVE_restore_stack_block
00949 case SAVE_BLOCK:
00950 if (HAVE_restore_stack_block)
00951 fcn = gen_restore_stack_block;
00952 break;
00953 #endif
00954 #ifdef HAVE_restore_stack_function
00955 case SAVE_FUNCTION:
00956 if (HAVE_restore_stack_function)
00957 fcn = gen_restore_stack_function;
00958 break;
00959 #endif
00960 #ifdef HAVE_restore_stack_nonlocal
00961 case SAVE_NONLOCAL:
00962 if (HAVE_restore_stack_nonlocal)
00963 fcn = gen_restore_stack_nonlocal;
00964 break;
00965 #endif
00966 default:
00967 break;
00968 }
00969
00970 if (sa != 0)
00971 {
00972 sa = validize_mem (sa);
00973
00974
00975
00976 emit_insn (gen_rtx_CLOBBER (VOIDmode,
00977 gen_rtx_MEM (BLKmode,
00978 gen_rtx_SCRATCH (VOIDmode))));
00979 emit_insn (gen_rtx_CLOBBER (VOIDmode,
00980 gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
00981 }
00982
00983 discard_pending_stack_adjust ();
00984
00985 if (after)
00986 {
00987 rtx seq;
00988
00989 start_sequence ();
00990 emit_insn (fcn (stack_pointer_rtx, sa));
00991 seq = get_insns ();
00992 end_sequence ();
00993 emit_insn_after (seq, after);
00994 }
00995 else
00996 emit_insn (fcn (stack_pointer_rtx, sa));
00997 }
00998
00999
01000
01001
01002
01003 void
01004 update_nonlocal_goto_save_area (void)
01005 {
01006 tree t_save;
01007 rtx r_save;
01008
01009
01010
01011
01012
01013 t_save = build4 (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
01014 integer_one_node, NULL_TREE, NULL_TREE);
01015 r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
01016
01017 emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
01018 }
01019
01020 #ifdef SETJMP_VIA_SAVE_AREA
01021
01022
01023
01024
01025
01026 void
01027 optimize_save_area_alloca (void)
01028 {
01029 rtx insn;
01030
01031 for (insn = get_insns (); insn; insn = NEXT_INSN(insn))
01032 {
01033 rtx note;
01034
01035 if (!NONJUMP_INSN_P (insn))
01036 continue;
01037
01038 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
01039 {
01040 if (REG_NOTE_KIND (note) != REG_SAVE_AREA)
01041 continue;
01042
01043 if (!current_function_calls_setjmp)
01044 {
01045 rtx pat = PATTERN (insn);
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 gcc_assert (GET_CODE (pat) == SET
01058 && SET_DEST (pat) == stack_pointer_rtx
01059 && GET_CODE (SET_SRC (pat)) == MINUS
01060 && XEXP (SET_SRC (pat), 0) == stack_pointer_rtx);
01061
01062
01063
01064 XEXP (SET_SRC (pat), 1) = XEXP (note, 0);
01065 REG_NOTES (insn) = NULL_RTX;
01066 }
01067 else
01068 {
01069
01070
01071
01072 if (note == REG_NOTES (insn))
01073 {
01074 REG_NOTES (insn) = XEXP (note, 1);
01075 }
01076 else
01077 {
01078 rtx srch;
01079
01080 for (srch = REG_NOTES (insn); srch; srch = XEXP (srch, 1))
01081 if (XEXP (srch, 1) == note)
01082 break;
01083
01084 gcc_assert (srch);
01085
01086 XEXP (srch, 1) = XEXP (note, 1);
01087 }
01088 }
01089
01090
01091 break;
01092 }
01093 }
01094 }
01095 #endif
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 rtx
01109 allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
01110 {
01111 #ifdef SETJMP_VIA_SAVE_AREA
01112 rtx setjmpless_size = NULL_RTX;
01113 #endif
01114
01115
01116
01117
01118 if (size == const0_rtx)
01119 return virtual_stack_dynamic_rtx;
01120
01121
01122 current_function_calls_alloca = 1;
01123
01124
01125 if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
01126 size = convert_to_mode (Pmode, size, 1);
01127
01128
01129
01130
01131 cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 #if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
01147 #define MUST_ALIGN 1
01148 #else
01149 #define MUST_ALIGN (PREFERRED_STACK_BOUNDARY < BIGGEST_ALIGNMENT)
01150 #endif
01151
01152 if (MUST_ALIGN)
01153 size
01154 = force_operand (plus_constant (size,
01155 BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
01156 NULL_RTX);
01157
01158 #ifdef SETJMP_VIA_SAVE_AREA
01159
01160
01161
01162
01163
01164 {
01165 rtx dynamic_offset
01166 = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
01167 stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
01168
01169 if (!current_function_calls_setjmp)
01170 {
01171 int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
01172
01173
01174
01175
01176
01177
01178 gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
01179
01180 if (GET_CODE (size) == CONST_INT)
01181 {
01182 HOST_WIDE_INT new = INTVAL (size) / align * align;
01183
01184 if (INTVAL (size) != new)
01185 setjmpless_size = GEN_INT (new);
01186 else
01187 setjmpless_size = size;
01188 }
01189 else
01190 {
01191
01192
01193 setjmpless_size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
01194 GEN_INT (align), NULL_RTX, 1);
01195 setjmpless_size = expand_mult (Pmode, setjmpless_size,
01196 GEN_INT (align), NULL_RTX, 1);
01197 }
01198
01199
01200
01201 if (!register_operand (setjmpless_size, Pmode))
01202 setjmpless_size = force_reg (Pmode, setjmpless_size);
01203 }
01204
01205 size = expand_binop (Pmode, add_optab, size, dynamic_offset,
01206 NULL_RTX, 1, OPTAB_LIB_WIDEN);
01207 }
01208 #endif
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 #if !defined (SETJMP_VIA_SAVE_AREA)
01227 if (MUST_ALIGN || known_align % PREFERRED_STACK_BOUNDARY != 0)
01228 #endif
01229 size = round_push (size);
01230
01231 do_pending_stack_adjust ();
01232
01233
01234
01235 gcc_assert (!(stack_pointer_delta
01236 % (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)));
01237
01238
01239
01240 if (flag_stack_check && ! STACK_CHECK_BUILTIN)
01241 probe_stack_range (STACK_CHECK_MAX_FRAME_SIZE + STACK_CHECK_PROTECT, size);
01242
01243
01244 if (target == 0 || !REG_P (target)
01245 || REGNO (target) < FIRST_PSEUDO_REGISTER
01246 || GET_MODE (target) != Pmode)
01247 target = gen_reg_rtx (Pmode);
01248
01249 mark_reg_pointer (target, known_align);
01250
01251
01252
01253
01254 #ifdef HAVE_allocate_stack
01255 if (HAVE_allocate_stack)
01256 {
01257 enum machine_mode mode = STACK_SIZE_MODE;
01258 insn_operand_predicate_fn pred;
01259
01260
01261
01262
01263
01264 if (mode == VOIDmode)
01265 mode = insn_data[(int) CODE_FOR_allocate_stack].operand[1].mode;
01266
01267 pred = insn_data[(int) CODE_FOR_allocate_stack].operand[1].predicate;
01268 if (pred && ! ((*pred) (size, mode)))
01269 size = copy_to_mode_reg (mode, convert_to_mode (mode, size, 1));
01270
01271 emit_insn (gen_allocate_stack (target, size));
01272 }
01273 else
01274 #endif
01275 {
01276 #ifndef STACK_GROWS_DOWNWARD
01277 emit_move_insn (target, virtual_stack_dynamic_rtx);
01278 #endif
01279
01280
01281 if (current_function_limit_stack)
01282 {
01283 rtx available;
01284 rtx space_available = gen_label_rtx ();
01285 #ifdef STACK_GROWS_DOWNWARD
01286 available = expand_binop (Pmode, sub_optab,
01287 stack_pointer_rtx, stack_limit_rtx,
01288 NULL_RTX, 1, OPTAB_WIDEN);
01289 #else
01290 available = expand_binop (Pmode, sub_optab,
01291 stack_limit_rtx, stack_pointer_rtx,
01292 NULL_RTX, 1, OPTAB_WIDEN);
01293 #endif
01294 emit_cmp_and_jump_insns (available, size, GEU, NULL_RTX, Pmode, 1,
01295 space_available);
01296 #ifdef HAVE_trap
01297 if (HAVE_trap)
01298 emit_insn (gen_trap ());
01299 else
01300 #endif
01301 error ("stack limits not supported on this target");
01302 emit_barrier ();
01303 emit_label (space_available);
01304 }
01305
01306 anti_adjust_stack (size);
01307 #ifdef SETJMP_VIA_SAVE_AREA
01308 if (setjmpless_size != NULL_RTX)
01309 {
01310 rtx note_target = get_last_insn ();
01311
01312 REG_NOTES (note_target)
01313 = gen_rtx_EXPR_LIST (REG_SAVE_AREA, setjmpless_size,
01314 REG_NOTES (note_target));
01315 }
01316 #endif
01317
01318 #ifdef STACK_GROWS_DOWNWARD
01319 emit_move_insn (target, virtual_stack_dynamic_rtx);
01320 #endif
01321 }
01322
01323 if (MUST_ALIGN)
01324 {
01325
01326
01327
01328 target = expand_binop (Pmode, add_optab, target,
01329 GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
01330 NULL_RTX, 1, OPTAB_LIB_WIDEN);
01331 target = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, target,
01332 GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
01333 NULL_RTX, 1);
01334 target = expand_mult (Pmode, target,
01335 GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
01336 NULL_RTX, 1);
01337 }
01338
01339
01340 if (cfun->nonlocal_goto_save_area != 0)
01341 update_nonlocal_goto_save_area ();
01342
01343 return target;
01344 }
01345
01346
01347
01348
01349
01350 static GTY(()) rtx stack_check_libfunc;
01351
01352 void
01353 set_stack_check_libfunc (rtx libfunc)
01354 {
01355 stack_check_libfunc = libfunc;
01356 }
01357
01358
01359
01360 static void
01361 emit_stack_probe (rtx address)
01362 {
01363 rtx memref = gen_rtx_MEM (word_mode, address);
01364
01365 MEM_VOLATILE_P (memref) = 1;
01366
01367 if (STACK_CHECK_PROBE_LOAD)
01368 emit_move_insn (gen_reg_rtx (word_mode), memref);
01369 else
01370 emit_move_insn (memref, const0_rtx);
01371 }
01372
01373
01374
01375
01376
01377
01378
01379 #ifdef STACK_GROWS_DOWNWARD
01380 #define STACK_GROW_OP MINUS
01381 #else
01382 #define STACK_GROW_OP PLUS
01383 #endif
01384
01385 void
01386 probe_stack_range (HOST_WIDE_INT first, rtx size)
01387 {
01388
01389 if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
01390 size = convert_to_mode (Pmode, size, 1);
01391
01392
01393
01394 if (stack_check_libfunc != 0)
01395 {
01396 rtx addr = memory_address (QImode,
01397 gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
01398 stack_pointer_rtx,
01399 plus_constant (size, first)));
01400
01401 addr = convert_memory_address (ptr_mode, addr);
01402 emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
01403 ptr_mode);
01404 }
01405
01406
01407 #ifdef HAVE_check_stack
01408 else if (HAVE_check_stack)
01409 {
01410 insn_operand_predicate_fn pred;
01411 rtx last_addr
01412 = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
01413 stack_pointer_rtx,
01414 plus_constant (size, first)),
01415 NULL_RTX);
01416
01417 pred = insn_data[(int) CODE_FOR_check_stack].operand[0].predicate;
01418 if (pred && ! ((*pred) (last_addr, Pmode)))
01419 last_addr = copy_to_mode_reg (Pmode, last_addr);
01420
01421 emit_insn (gen_check_stack (last_addr));
01422 }
01423 #endif
01424
01425
01426
01427 else if (GET_CODE (size) == CONST_INT
01428 && INTVAL (size) < 10 * STACK_CHECK_PROBE_INTERVAL)
01429 {
01430 HOST_WIDE_INT offset;
01431
01432
01433
01434
01435
01436 for (offset = first + STACK_CHECK_PROBE_INTERVAL;
01437 offset < INTVAL (size);
01438 offset = offset + STACK_CHECK_PROBE_INTERVAL)
01439 emit_stack_probe (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
01440 stack_pointer_rtx,
01441 GEN_INT (offset)));
01442
01443 emit_stack_probe (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
01444 stack_pointer_rtx,
01445 plus_constant (size, first)));
01446 }
01447
01448
01449
01450 else
01451 {
01452 rtx test_addr
01453 = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
01454 stack_pointer_rtx,
01455 GEN_INT (first + STACK_CHECK_PROBE_INTERVAL)),
01456 NULL_RTX);
01457 rtx last_addr
01458 = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
01459 stack_pointer_rtx,
01460 plus_constant (size, first)),
01461 NULL_RTX);
01462 rtx incr = GEN_INT (STACK_CHECK_PROBE_INTERVAL);
01463 rtx loop_lab = gen_label_rtx ();
01464 rtx test_lab = gen_label_rtx ();
01465 rtx end_lab = gen_label_rtx ();
01466 rtx temp;
01467
01468 if (!REG_P (test_addr)
01469 || REGNO (test_addr) < FIRST_PSEUDO_REGISTER)
01470 test_addr = force_reg (Pmode, test_addr);
01471
01472 emit_jump (test_lab);
01473
01474 emit_label (loop_lab);
01475 emit_stack_probe (test_addr);
01476
01477 #ifdef STACK_GROWS_DOWNWARD
01478 #define CMP_OPCODE GTU
01479 temp = expand_binop (Pmode, sub_optab, test_addr, incr, test_addr,
01480 1, OPTAB_WIDEN);
01481 #else
01482 #define CMP_OPCODE LTU
01483 temp = expand_binop (Pmode, add_optab, test_addr, incr, test_addr,
01484 1, OPTAB_WIDEN);
01485 #endif
01486
01487 gcc_assert (temp == test_addr);
01488
01489 emit_label (test_lab);
01490 emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
01491 NULL_RTX, Pmode, 1, loop_lab);
01492 emit_jump (end_lab);
01493 emit_label (end_lab);
01494
01495 emit_stack_probe (last_addr);
01496 }
01497 }
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 rtx
01509 hard_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
01510 int outgoing ATTRIBUTE_UNUSED)
01511 {
01512 rtx val;
01513
01514 #ifdef FUNCTION_OUTGOING_VALUE
01515 if (outgoing)
01516 val = FUNCTION_OUTGOING_VALUE (valtype, func);
01517 else
01518 #endif
01519 val = FUNCTION_VALUE (valtype, func);
01520
01521 if (REG_P (val)
01522 && GET_MODE (val) == BLKmode)
01523 {
01524 unsigned HOST_WIDE_INT bytes = int_size_in_bytes (valtype);
01525 enum machine_mode tmpmode;
01526
01527
01528
01529
01530
01531 for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01532 tmpmode != VOIDmode;
01533 tmpmode = GET_MODE_WIDER_MODE (tmpmode))
01534 {
01535
01536 if (GET_MODE_SIZE (tmpmode) >= bytes)
01537 break;
01538 }
01539
01540
01541 gcc_assert (tmpmode != VOIDmode);
01542
01543 PUT_MODE (val, tmpmode);
01544 }
01545 return val;
01546 }
01547
01548
01549
01550
01551 rtx
01552 hard_libcall_value (enum machine_mode mode)
01553 {
01554 return LIBCALL_VALUE (mode);
01555 }
01556
01557
01558
01559
01560
01561
01562 int
01563 rtx_to_tree_code (enum rtx_code code)
01564 {
01565 enum tree_code tcode;
01566
01567 switch (code)
01568 {
01569 case PLUS:
01570 tcode = PLUS_EXPR;
01571 break;
01572 case MINUS:
01573 tcode = MINUS_EXPR;
01574 break;
01575 case MULT:
01576 tcode = MULT_EXPR;
01577 break;
01578 case DIV:
01579 tcode = RDIV_EXPR;
01580 break;
01581 case SMIN:
01582 tcode = MIN_EXPR;
01583 break;
01584 case SMAX:
01585 tcode = MAX_EXPR;
01586 break;
01587 default:
01588 tcode = LAST_AND_UNUSED_TREE_CODE;
01589 break;
01590 }
01591 return ((int) tcode);
01592 }
01593
01594 #include "gt-explow.h"