|
|
1.1 ! root 1: /* Subroutines for manipulating rtx's in semantically interesting ways. ! 2: Copyright (C) 1987, 1991 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include "config.h" ! 22: #include "rtl.h" ! 23: #include "tree.h" ! 24: #include "flags.h" ! 25: #include "expr.h" ! 26: #include "hard-reg-set.h" ! 27: #include "insn-config.h" ! 28: #include "recog.h" ! 29: #include "insn-flags.h" ! 30: #include "insn-codes.h" ! 31: ! 32: /* Return an rtx for the sum of X and the integer C. */ ! 33: ! 34: rtx ! 35: plus_constant (x, c) ! 36: register rtx x; ! 37: register int c; ! 38: { ! 39: register RTX_CODE code; ! 40: register enum machine_mode mode; ! 41: register rtx tem; ! 42: int all_constant = 0; ! 43: ! 44: if (c == 0) ! 45: return x; ! 46: ! 47: restart: ! 48: ! 49: code = GET_CODE (x); ! 50: mode = GET_MODE (x); ! 51: switch (code) ! 52: { ! 53: case CONST_INT: ! 54: return gen_rtx (CONST_INT, VOIDmode, (INTVAL (x) + c)); ! 55: ! 56: case CONST_DOUBLE: ! 57: { ! 58: int l1 = CONST_DOUBLE_LOW (x); ! 59: int h1 = CONST_DOUBLE_HIGH (x); ! 60: int l2 = c; ! 61: int h2 = c < 0 ? ~0 : 0; ! 62: int lv, hv; ! 63: ! 64: add_double (l1, h1, l2, h2, &lv, &hv); ! 65: ! 66: return immed_double_const (lv, hv, VOIDmode); ! 67: } ! 68: ! 69: case MEM: ! 70: /* If this is a reference to the constant pool, try replacing it with ! 71: a reference to a new constant. If the resulting address isn't ! 72: valid, don't return it because we have no way to validize it. */ ! 73: if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF ! 74: && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))) ! 75: { ! 76: tem ! 77: = force_const_mem (GET_MODE (x), ! 78: plus_constant (get_pool_constant (XEXP (x, 0)), ! 79: c)); ! 80: if (memory_address_p (GET_MODE (tem), XEXP (tem, 0))) ! 81: return tem; ! 82: } ! 83: break; ! 84: ! 85: case CONST: ! 86: /* If adding to something entirely constant, set a flag ! 87: so that we can add a CONST around the result. */ ! 88: x = XEXP (x, 0); ! 89: all_constant = 1; ! 90: goto restart; ! 91: ! 92: case SYMBOL_REF: ! 93: case LABEL_REF: ! 94: all_constant = 1; ! 95: break; ! 96: ! 97: case PLUS: ! 98: /* The interesting case is adding the integer to a sum. ! 99: Look for constant term in the sum and combine ! 100: with C. For an integer constant term, we make a combined ! 101: integer. For a constant term that is not an explicit integer, ! 102: we cannot really combine, but group them together anyway. */ ! 103: if (GET_CODE (XEXP (x, 0)) == CONST_INT) ! 104: { ! 105: c += INTVAL (XEXP (x, 0)); ! 106: x = XEXP (x, 1); ! 107: } ! 108: else if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 109: { ! 110: c += INTVAL (XEXP (x, 1)); ! 111: x = XEXP (x, 0); ! 112: } ! 113: else if (CONSTANT_P (XEXP (x, 0))) ! 114: return gen_rtx (PLUS, mode, ! 115: plus_constant (XEXP (x, 0), c), ! 116: XEXP (x, 1)); ! 117: else if (CONSTANT_P (XEXP (x, 1))) ! 118: return gen_rtx (PLUS, mode, ! 119: XEXP (x, 0), ! 120: plus_constant (XEXP (x, 1), c)); ! 121: } ! 122: ! 123: if (c != 0) ! 124: x = gen_rtx (PLUS, mode, x, gen_rtx (CONST_INT, VOIDmode, c)); ! 125: ! 126: if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) ! 127: return x; ! 128: else if (all_constant) ! 129: return gen_rtx (CONST, mode, x); ! 130: else ! 131: return x; ! 132: } ! 133: ! 134: /* This is the same a `plus_constant', except that it handles LO_SUM. */ ! 135: ! 136: rtx ! 137: plus_constant_for_output (x, c) ! 138: register rtx x; ! 139: register int c; ! 140: { ! 141: register RTX_CODE code = GET_CODE (x); ! 142: register enum machine_mode mode = GET_MODE (x); ! 143: int all_constant = 0; ! 144: ! 145: if (GET_CODE (x) == LO_SUM) ! 146: return gen_rtx (LO_SUM, mode, XEXP (x, 0), ! 147: plus_constant_for_output (XEXP (x, 1), c)); ! 148: ! 149: else ! 150: return plus_constant (x, c); ! 151: } ! 152: ! 153: /* If X is a sum, return a new sum like X but lacking any constant terms. ! 154: Add all the removed constant terms into *CONSTPTR. ! 155: X itself is not altered. The result != X if and only if ! 156: it is not isomorphic to X. */ ! 157: ! 158: rtx ! 159: eliminate_constant_term (x, constptr) ! 160: rtx x; ! 161: int *constptr; ! 162: { ! 163: int c; ! 164: register rtx x0, x1; ! 165: ! 166: if (GET_CODE (x) != PLUS) ! 167: return x; ! 168: ! 169: /* First handle constants appearing at this level explicitly. */ ! 170: if (GET_CODE (XEXP (x, 0)) == CONST_INT) ! 171: { ! 172: *constptr += INTVAL (XEXP (x, 0)); ! 173: return eliminate_constant_term (XEXP (x, 1), constptr); ! 174: } ! 175: ! 176: if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 177: { ! 178: *constptr += INTVAL (XEXP (x, 1)); ! 179: return eliminate_constant_term (XEXP (x, 0), constptr); ! 180: } ! 181: ! 182: c = 0; ! 183: x0 = eliminate_constant_term (XEXP (x, 0), &c); ! 184: x1 = eliminate_constant_term (XEXP (x, 1), &c); ! 185: if (x1 != XEXP (x, 1) || x0 != XEXP (x, 0)) ! 186: { ! 187: *constptr += c; ! 188: return gen_rtx (PLUS, GET_MODE (x), x0, x1); ! 189: } ! 190: return x; ! 191: } ! 192: ! 193: /* Returns the insn that next references REG after INSN, or 0 ! 194: if REG is clobbered before next referenced or we cannot find ! 195: an insn that references REG in a straight-line piece of code. */ ! 196: ! 197: rtx ! 198: find_next_ref (reg, insn) ! 199: rtx reg; ! 200: rtx insn; ! 201: { ! 202: rtx next; ! 203: ! 204: for (insn = NEXT_INSN (insn); insn; insn = next) ! 205: { ! 206: next = NEXT_INSN (insn); ! 207: if (GET_CODE (insn) == NOTE) ! 208: continue; ! 209: if (GET_CODE (insn) == CODE_LABEL ! 210: || GET_CODE (insn) == BARRIER) ! 211: return 0; ! 212: if (GET_CODE (insn) == INSN ! 213: || GET_CODE (insn) == JUMP_INSN ! 214: || GET_CODE (insn) == CALL_INSN) ! 215: { ! 216: if (reg_set_p (reg, insn)) ! 217: return 0; ! 218: if (reg_mentioned_p (reg, PATTERN (insn))) ! 219: return insn; ! 220: if (GET_CODE (insn) == JUMP_INSN) ! 221: { ! 222: if (simplejump_p (insn)) ! 223: next = JUMP_LABEL (insn); ! 224: else ! 225: return 0; ! 226: } ! 227: if (GET_CODE (insn) == CALL_INSN ! 228: && REGNO (reg) < FIRST_PSEUDO_REGISTER ! 229: && call_used_regs[REGNO (reg)]) ! 230: return 0; ! 231: } ! 232: else ! 233: abort (); ! 234: } ! 235: return 0; ! 236: } ! 237: ! 238: /* Return an rtx for the size in bytes of the value of EXP. */ ! 239: ! 240: rtx ! 241: expr_size (exp) ! 242: tree exp; ! 243: { ! 244: return expand_expr (size_in_bytes (TREE_TYPE (exp)), ! 245: 0, TYPE_MODE (sizetype), 0); ! 246: } ! 247: ! 248: /* Return a copy of X in which all memory references ! 249: and all constants that involve symbol refs ! 250: have been replaced with new temporary registers. ! 251: Also emit code to load the memory locations and constants ! 252: into those registers. ! 253: ! 254: If X contains no such constants or memory references, ! 255: X itself (not a copy) is returned. ! 256: ! 257: If a constant is found in the address that is not a legitimate constant ! 258: in an insn, it is left alone in the hope that it might be valid in the ! 259: address. ! 260: ! 261: X may contain no arithmetic except addition, subtraction and multiplication. ! 262: Values returned by expand_expr with 1 for sum_ok fit this constraint. */ ! 263: ! 264: static rtx ! 265: break_out_memory_refs (x) ! 266: register rtx x; ! 267: { ! 268: if (GET_CODE (x) == MEM ! 269: || (CONSTANT_P (x) && LEGITIMATE_CONSTANT_P (x) ! 270: && GET_MODE (x) != VOIDmode)) ! 271: { ! 272: register rtx temp = force_reg (GET_MODE (x), x); ! 273: mark_reg_pointer (temp); ! 274: x = temp; ! 275: } ! 276: else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS ! 277: || GET_CODE (x) == MULT) ! 278: { ! 279: register rtx op0 = break_out_memory_refs (XEXP (x, 0)); ! 280: register rtx op1 = break_out_memory_refs (XEXP (x, 1)); ! 281: if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1)) ! 282: x = gen_rtx (GET_CODE (x), Pmode, op0, op1); ! 283: } ! 284: return x; ! 285: } ! 286: ! 287: /* Given a memory address or facsimile X, construct a new address, ! 288: currently equivalent, that is stable: future stores won't change it. ! 289: ! 290: X must be composed of constants, register and memory references ! 291: combined with addition, subtraction and multiplication: ! 292: in other words, just what you can get from expand_expr if sum_ok is 1. ! 293: ! 294: Works by making copies of all regs and memory locations used ! 295: by X and combining them the same way X does. ! 296: You could also stabilize the reference to this address ! 297: by copying the address to a register with copy_to_reg; ! 298: but then you wouldn't get indexed addressing in the reference. */ ! 299: ! 300: rtx ! 301: copy_all_regs (x) ! 302: register rtx x; ! 303: { ! 304: if (GET_CODE (x) == REG) ! 305: { ! 306: if (REGNO (x) != FRAME_POINTER_REGNUM) ! 307: x = copy_to_reg (x); ! 308: } ! 309: else if (GET_CODE (x) == MEM) ! 310: x = copy_to_reg (x); ! 311: else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS ! 312: || GET_CODE (x) == MULT) ! 313: { ! 314: register rtx op0 = copy_all_regs (XEXP (x, 0)); ! 315: register rtx op1 = copy_all_regs (XEXP (x, 1)); ! 316: if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1)) ! 317: x = gen_rtx (GET_CODE (x), Pmode, op0, op1); ! 318: } ! 319: return x; ! 320: } ! 321: ! 322: /* Return something equivalent to X but valid as a memory address ! 323: for something of mode MODE. When X is not itself valid, this ! 324: works by copying X or subexpressions of it into registers. */ ! 325: ! 326: rtx ! 327: memory_address (mode, x) ! 328: enum machine_mode mode; ! 329: register rtx x; ! 330: { ! 331: register rtx oldx; ! 332: ! 333: /* By passing constant addresses thru registers ! 334: we get a chance to cse them. */ ! 335: if (! cse_not_expected && CONSTANT_P (x) && LEGITIMATE_CONSTANT_P (x)) ! 336: return force_reg (Pmode, x); ! 337: ! 338: /* Accept a QUEUED that refers to a REG ! 339: even though that isn't a valid address. ! 340: On attempting to put this in an insn we will call protect_from_queue ! 341: which will turn it into a REG, which is valid. */ ! 342: if (GET_CODE (x) == QUEUED ! 343: && GET_CODE (QUEUED_VAR (x)) == REG) ! 344: return x; ! 345: ! 346: /* We get better cse by rejecting indirect addressing at this stage. ! 347: Let the combiner create indirect addresses where appropriate. ! 348: For now, generate the code so that the subexpressions useful to share ! 349: are visible. But not if cse won't be done! */ ! 350: oldx = x; ! 351: if (! cse_not_expected && GET_CODE (x) != REG) ! 352: x = break_out_memory_refs (x); ! 353: ! 354: /* At this point, any valid address is accepted. */ ! 355: GO_IF_LEGITIMATE_ADDRESS (mode, x, win); ! 356: ! 357: /* If it was valid before but breaking out memory refs invalidated it, ! 358: use it the old way. */ ! 359: if (memory_address_p (mode, oldx)) ! 360: goto win2; ! 361: ! 362: /* Perform machine-dependent transformations on X ! 363: in certain cases. This is not necessary since the code ! 364: below can handle all possible cases, but machine-dependent ! 365: transformations can make better code. */ ! 366: LEGITIMIZE_ADDRESS (x, oldx, mode, win); ! 367: ! 368: /* PLUS and MULT can appear in special ways ! 369: as the result of attempts to make an address usable for indexing. ! 370: Usually they are dealt with by calling force_operand, below. ! 371: But a sum containing constant terms is special ! 372: if removing them makes the sum a valid address: ! 373: then we generate that address in a register ! 374: and index off of it. We do this because it often makes ! 375: shorter code, and because the addresses thus generated ! 376: in registers often become common subexpressions. */ ! 377: if (GET_CODE (x) == PLUS) ! 378: { ! 379: int constant_term = 0; ! 380: rtx y = eliminate_constant_term (x, &constant_term); ! 381: if (constant_term == 0 ! 382: || ! memory_address_p (mode, y)) ! 383: return force_operand (x, 0); ! 384: ! 385: y = plus_constant (copy_to_reg (y), constant_term); ! 386: if (! memory_address_p (mode, y)) ! 387: return force_operand (x, 0); ! 388: return y; ! 389: } ! 390: if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS) ! 391: return force_operand (x, 0); ! 392: ! 393: /* If we have a register that's an invalid address, ! 394: it must be a hard reg of the wrong class. Copy it to a pseudo. */ ! 395: if (GET_CODE (x) == REG) ! 396: return copy_to_reg (x); ! 397: ! 398: /* Last resort: copy the value to a register, since ! 399: the register is a valid address. */ ! 400: return force_reg (Pmode, x); ! 401: ! 402: win2: ! 403: x = oldx; ! 404: win: ! 405: if (flag_force_addr && ! cse_not_expected && GET_CODE (x) != REG ! 406: /* Don't copy an addr via a reg if it is one of our stack slots. */ ! 407: && ! (GET_CODE (x) == PLUS ! 408: && (XEXP (x, 0) == virtual_stack_vars_rtx ! 409: || XEXP (x, 0) == virtual_incoming_args_rtx))) ! 410: { ! 411: if (general_operand (x, Pmode)) ! 412: return force_reg (Pmode, x); ! 413: else ! 414: return force_operand (x, 0); ! 415: } ! 416: return x; ! 417: } ! 418: ! 419: /* Like `memory_address' but pretend `flag_force_addr' is 0. */ ! 420: ! 421: rtx ! 422: memory_address_noforce (mode, x) ! 423: enum machine_mode mode; ! 424: rtx x; ! 425: { ! 426: int ambient_force_addr = flag_force_addr; ! 427: rtx val; ! 428: ! 429: flag_force_addr = 0; ! 430: val = memory_address (mode, x); ! 431: flag_force_addr = ambient_force_addr; ! 432: return val; ! 433: } ! 434: ! 435: /* Convert a mem ref into one with a valid memory address. ! 436: Pass through anything else unchanged. */ ! 437: ! 438: rtx ! 439: validize_mem (ref) ! 440: rtx ref; ! 441: { ! 442: if (GET_CODE (ref) != MEM) ! 443: return ref; ! 444: if (memory_address_p (GET_MODE (ref), XEXP (ref, 0))) ! 445: return ref; ! 446: /* Don't alter REF itself, since that is probably a stack slot. */ ! 447: return change_address (ref, GET_MODE (ref), XEXP (ref, 0)); ! 448: } ! 449: ! 450: /* Return a modified copy of X with its memory address copied ! 451: into a temporary register to protect it from side effects. ! 452: If X is not a MEM, it is returned unchanged (and not copied). ! 453: Perhaps even if it is a MEM, if there is no need to change it. */ ! 454: ! 455: rtx ! 456: stabilize (x) ! 457: rtx x; ! 458: { ! 459: register rtx addr; ! 460: if (GET_CODE (x) != MEM) ! 461: return x; ! 462: addr = XEXP (x, 0); ! 463: if (rtx_unstable_p (addr)) ! 464: { ! 465: rtx temp = copy_all_regs (addr); ! 466: rtx mem; ! 467: if (GET_CODE (temp) != REG) ! 468: temp = copy_to_reg (temp); ! 469: mem = gen_rtx (MEM, GET_MODE (x), temp); ! 470: /* Mark returned memref with in_struct ! 471: if it's in an array or structure. */ ! 472: if (GET_CODE (addr) == PLUS || MEM_IN_STRUCT_P (x)) ! 473: MEM_IN_STRUCT_P (mem) = 1; ! 474: return mem; ! 475: } ! 476: return x; ! 477: } ! 478: ! 479: /* Copy the value or contents of X to a new temp reg and return that reg. */ ! 480: ! 481: rtx ! 482: copy_to_reg (x) ! 483: rtx x; ! 484: { ! 485: register rtx temp = gen_reg_rtx (GET_MODE (x)); ! 486: ! 487: /* If not an operand, must be an address with PLUS and MULT so ! 488: do the computation. */ ! 489: if (! general_operand (x, VOIDmode)) ! 490: x = force_operand (x, temp); ! 491: ! 492: if (x != temp) ! 493: emit_move_insn (temp, x); ! 494: ! 495: return temp; ! 496: } ! 497: ! 498: /* Like copy_to_reg but always give the new register mode Pmode ! 499: in case X is a constant. */ ! 500: ! 501: rtx ! 502: copy_addr_to_reg (x) ! 503: rtx x; ! 504: { ! 505: return copy_to_mode_reg (Pmode, x); ! 506: } ! 507: ! 508: /* Like copy_to_reg but always give the new register mode MODE ! 509: in case X is a constant. */ ! 510: ! 511: rtx ! 512: copy_to_mode_reg (mode, x) ! 513: enum machine_mode mode; ! 514: rtx x; ! 515: { ! 516: register rtx temp = gen_reg_rtx (mode); ! 517: ! 518: /* If not an operand, must be an address with PLUS and MULT so ! 519: do the computation. */ ! 520: if (! general_operand (x, VOIDmode)) ! 521: x = force_operand (x, temp); ! 522: ! 523: if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode) ! 524: abort (); ! 525: if (x != temp) ! 526: emit_move_insn (temp, x); ! 527: return temp; ! 528: } ! 529: ! 530: /* Load X into a register if it is not already one. ! 531: Use mode MODE for the register. ! 532: X should be valid for mode MODE, but it may be a constant which ! 533: is valid for all integer modes; that's why caller must specify MODE. ! 534: ! 535: The caller must not alter the value in the register we return, ! 536: since we mark it as a "constant" register. */ ! 537: ! 538: rtx ! 539: force_reg (mode, x) ! 540: enum machine_mode mode; ! 541: rtx x; ! 542: { ! 543: register rtx temp, insn; ! 544: ! 545: if (GET_CODE (x) == REG) ! 546: return x; ! 547: temp = gen_reg_rtx (mode); ! 548: insn = emit_move_insn (temp, x); ! 549: /* Let optimizers know that TEMP's value never changes ! 550: and that X can be substituted for it. */ ! 551: if (CONSTANT_P (x)) ! 552: { ! 553: rtx note = find_reg_note (insn, REG_EQUAL, 0); ! 554: ! 555: if (note) ! 556: XEXP (note, 0) = x; ! 557: else ! 558: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, x, REG_NOTES (insn)); ! 559: } ! 560: return temp; ! 561: } ! 562: ! 563: /* If X is a memory ref, copy its contents to a new temp reg and return ! 564: that reg. Otherwise, return X. */ ! 565: ! 566: rtx ! 567: force_not_mem (x) ! 568: rtx x; ! 569: { ! 570: register rtx temp; ! 571: if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode) ! 572: return x; ! 573: temp = gen_reg_rtx (GET_MODE (x)); ! 574: emit_move_insn (temp, x); ! 575: return temp; ! 576: } ! 577: ! 578: /* Copy X to TARGET (if it's nonzero and a reg) ! 579: or to a new temp reg and return that reg. ! 580: ! 581: If we need to make a temp reg, try getting the mode from ! 582: both X and TARGET. */ ! 583: ! 584: rtx ! 585: copy_to_suggested_reg (x, target) ! 586: rtx x, target; ! 587: { ! 588: register rtx temp; ! 589: ! 590: if (target && GET_CODE (target) == REG) ! 591: temp = target; ! 592: else ! 593: { ! 594: enum machine_mode mode = GET_MODE (x); ! 595: ! 596: if (mode == VOIDmode && target != 0) ! 597: mode = GET_MODE (target); ! 598: ! 599: temp = gen_reg_rtx (mode); ! 600: } ! 601: ! 602: emit_move_insn (temp, x); ! 603: return temp; ! 604: } ! 605: ! 606: /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes). ! 607: This pops when ADJUST is positive. ADJUST need not be constant. */ ! 608: ! 609: void ! 610: adjust_stack (adjust) ! 611: rtx adjust; ! 612: { ! 613: rtx temp; ! 614: adjust = protect_from_queue (adjust, 0); ! 615: ! 616: if (adjust == const0_rtx) ! 617: return; ! 618: ! 619: temp = expand_binop (Pmode, ! 620: #ifdef STACK_GROWS_DOWNWARD ! 621: add_optab, ! 622: #else ! 623: sub_optab, ! 624: #endif ! 625: stack_pointer_rtx, adjust, stack_pointer_rtx, 0, ! 626: OPTAB_LIB_WIDEN); ! 627: ! 628: if (temp != stack_pointer_rtx) ! 629: emit_move_insn (stack_pointer_rtx, temp); ! 630: } ! 631: ! 632: /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes). ! 633: This pushes when ADJUST is positive. ADJUST need not be constant. */ ! 634: ! 635: void ! 636: anti_adjust_stack (adjust) ! 637: rtx adjust; ! 638: { ! 639: rtx temp; ! 640: adjust = protect_from_queue (adjust, 0); ! 641: ! 642: if (adjust == const0_rtx) ! 643: return; ! 644: ! 645: temp = expand_binop (Pmode, ! 646: #ifdef STACK_GROWS_DOWNWARD ! 647: sub_optab, ! 648: #else ! 649: add_optab, ! 650: #endif ! 651: stack_pointer_rtx, adjust, stack_pointer_rtx, 0, ! 652: OPTAB_LIB_WIDEN); ! 653: ! 654: if (temp != stack_pointer_rtx) ! 655: emit_move_insn (stack_pointer_rtx, temp); ! 656: } ! 657: ! 658: /* Round the size of a block to be pushed up to the boundary required ! 659: by this machine. SIZE is the desired size, which need not be constant. */ ! 660: ! 661: rtx ! 662: round_push (size) ! 663: rtx size; ! 664: { ! 665: #ifdef STACK_BOUNDARY ! 666: int align = STACK_BOUNDARY / BITS_PER_UNIT; ! 667: if (align == 1) ! 668: return size; ! 669: if (GET_CODE (size) == CONST_INT) ! 670: { ! 671: int new = (INTVAL (size) + align - 1) / align * align; ! 672: if (INTVAL (size) != new) ! 673: size = gen_rtx (CONST_INT, VOIDmode, new); ! 674: } ! 675: else ! 676: { ! 677: size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size, ! 678: gen_rtx (CONST_INT, VOIDmode, align), ! 679: 0, 1); ! 680: size = expand_mult (Pmode, size, ! 681: gen_rtx (CONST_INT, VOIDmode, align), ! 682: 0, 1); ! 683: } ! 684: #endif /* STACK_BOUNDARY */ ! 685: return size; ! 686: } ! 687: ! 688: /* Return an rtx representing the address of an area of memory dynamically ! 689: pushed on the stack. This region of memory is always aligned to ! 690: a multiple of BIGGEST_ALIGNMENT. ! 691: ! 692: Any required stack pointer alignment is preserved. ! 693: ! 694: SIZE is an rtx representing the size of the area. ! 695: TARGET is a place in which the address can be placed. */ ! 696: ! 697: rtx ! 698: allocate_dynamic_stack_space (size, target) ! 699: rtx size; ! 700: rtx target; ! 701: { ! 702: /* Ensure the size is in the proper mode. */ ! 703: if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode) ! 704: size = convert_to_mode (Pmode, size, 1); ! 705: ! 706: /* We will need to ensure that the address we return is aligned to ! 707: BIGGEST_ALIGNMENT. If STACK_DYNAMIC_OFFSET is defined, we don't ! 708: always know its final value at this point in the compilation (it ! 709: might depend on the size of the outgoing parameter lists, for ! 710: example), so we must align the value to be returned in that case. ! 711: (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if ! 712: STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined). ! 713: We must also do an alignment operation on the returned value if ! 714: the stack pointer alignment is less strict that BIGGEST_ALIGNMENT. ! 715: ! 716: If we have to align, we must leave space in SIZE for the hole ! 717: that might result from the alignment operation. */ ! 718: ! 719: #if defined (STACK_DYNAMIC_OFFSET) || defined(STACK_POINTER_OFFSET) || defined (ALLOCATE_OUTGOING_ARGS) ! 720: #define MUST_ALIGN ! 721: #endif ! 722: ! 723: #if ! defined (MUST_ALIGN) && (!defined(STACK_BOUNDARY) || STACK_BOUNDARY < BIGGEST_ALIGNMENT) ! 724: #define MUST_ALIGN ! 725: #endif ! 726: ! 727: #ifdef MUST_ALIGN ! 728: ! 729: if (GET_CODE (size) == CONST_INT) ! 730: size = gen_rtx (CONST_INT, VOIDmode, ! 731: INTVAL (size) + (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1)); ! 732: else ! 733: size = expand_binop (Pmode, add_optab, size, ! 734: gen_rtx (CONST_INT, VOIDmode, ! 735: BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1), ! 736: 0, 1, OPTAB_LIB_WIDEN); ! 737: #endif ! 738: ! 739: #ifdef SETJMP_VIA_SAVE_AREA ! 740: /* If setjmp restores regs from a save area in the stack frame, ! 741: avoid clobbering the reg save area. Note that the offset of ! 742: virtual_incoming_args_rtx includes the preallocated stack args space. ! 743: It would be no problem to clobber that, but it's on the wrong side ! 744: of the old save area. */ ! 745: { ! 746: rtx dynamic_offset ! 747: = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx, ! 748: stack_pointer_rtx, 0, 1, OPTAB_LIB_WIDEN); ! 749: size = expand_binop (Pmode, add_optab, size, dynamic_offset, ! 750: 0, 1, OPTAB_LIB_WIDEN); ! 751: } ! 752: #endif /* SETJMP_VIA_SAVE_AREA */ ! 753: ! 754: /* Round the size to a multiple of the required stack alignment. ! 755: Since the stack if presumed to be rounded before this allocation, ! 756: this will maintain the required alignment. ! 757: ! 758: If the stack grows downward, we could save an insn by subtracting ! 759: SIZE from the stack pointer and then aligning the stack pointer. ! 760: The problem with this is that the stack pointer may be unaligned ! 761: between the execution of the subtraction and alignment insns and ! 762: some machines do not allow this. Even on those that do, some ! 763: signal handlers malfunction if a signal should occur between those ! 764: insns. Since this is an extremely rare event, we have no reliable ! 765: way of knowing which systems have this problem. So we avoid even ! 766: momentarily mis-aligning the stack. */ ! 767: ! 768: size = round_push (size); ! 769: ! 770: do_pending_stack_adjust (); ! 771: ! 772: if (target == 0) ! 773: target = gen_reg_rtx (Pmode); ! 774: ! 775: #ifndef STACK_GROWS_DOWNWARD ! 776: emit_move_insn (target, virtual_stack_dynamic_rtx); ! 777: #endif ! 778: ! 779: /* Perform the required allocation from the stack. Some systems do ! 780: this differently than simply incrementing/decrementing from the ! 781: stack pointer. */ ! 782: #ifdef HAVE_allocate_stack ! 783: if (HAVE_allocate_stack) ! 784: { ! 785: enum machine_mode mode ! 786: = insn_operand_mode[(int) CODE_FOR_allocate_stack][0]; ! 787: ! 788: if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0] ! 789: && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]) ! 790: (size, mode))) ! 791: size = copy_to_mode_reg (mode, size); ! 792: ! 793: emit_insn (gen_allocate_stack (size)); ! 794: } ! 795: else ! 796: #endif ! 797: anti_adjust_stack (size); ! 798: ! 799: #ifdef STACK_GROWS_DOWNWARD ! 800: emit_move_insn (target, virtual_stack_dynamic_rtx); ! 801: #endif ! 802: ! 803: #ifdef MUST_ALIGN ! 804: target = expand_divmod (0, CEIL_DIV_EXPR, Pmode, target, ! 805: gen_rtx (CONST_INT, VOIDmode, ! 806: BIGGEST_ALIGNMENT / BITS_PER_UNIT), ! 807: 0, 1); ! 808: ! 809: target = expand_mult (Pmode, target, ! 810: gen_rtx (CONST_INT, VOIDmode, ! 811: BIGGEST_ALIGNMENT / BITS_PER_UNIT), ! 812: 0, 1); ! 813: #endif ! 814: ! 815: /* Some systems require a particular insn to refer to the stack ! 816: to make the pages exist. */ ! 817: #ifdef HAVE_probe ! 818: if (HAVE_probe) ! 819: emit_insn (gen_probe ()); ! 820: #endif ! 821: ! 822: return target; ! 823: } ! 824: ! 825: /* Return an rtx representing the register or memory location ! 826: in which a scalar value of data type VALTYPE ! 827: was returned by a function call to function FUNC. ! 828: FUNC is a FUNCTION_DECL node if the precise function is known, ! 829: otherwise 0. */ ! 830: ! 831: rtx ! 832: hard_function_value (valtype, func) ! 833: tree valtype; ! 834: tree func; ! 835: { ! 836: return FUNCTION_VALUE (valtype, func); ! 837: } ! 838: ! 839: /* Return an rtx representing the register or memory location ! 840: in which a scalar value of mode MODE was returned by a library call. */ ! 841: ! 842: rtx ! 843: hard_libcall_value (mode) ! 844: enum machine_mode mode; ! 845: { ! 846: return LIBCALL_VALUE (mode); ! 847: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.