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