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