|
|
1.1 ! root 1: /* Emit RTL for the GNU C-Compiler expander. ! 2: Copyright (C) 1987, 1988, 1992 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: /* Middle-to-low level generation of rtx code and insns. ! 22: ! 23: This file contains the functions `gen_rtx', `gen_reg_rtx' ! 24: and `gen_label_rtx' that are the usual ways of creating rtl ! 25: expressions for most purposes. ! 26: ! 27: It also has the functions for creating insns and linking ! 28: them in the doubly-linked chain. ! 29: ! 30: The patterns of the insns are created by machine-dependent ! 31: routines in insn-emit.c, which is generated automatically from ! 32: the machine description. These routines use `gen_rtx' to make ! 33: the individual rtx's of the pattern; what is machine dependent ! 34: is the kind of rtx's they make and what arguments they use. */ ! 35: ! 36: #include "config.h" ! 37: #include <stdio.h> ! 38: #include "gvarargs.h" ! 39: #include "rtl.h" ! 40: #include "flags.h" ! 41: #include "function.h" ! 42: #include "expr.h" ! 43: #include "regs.h" ! 44: #include "insn-config.h" ! 45: #include "real.h" ! 46: ! 47: /* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function. ! 48: After rtl generation, it is 1 plus the largest register number used. */ ! 49: ! 50: int reg_rtx_no = LAST_VIRTUAL_REGISTER + 1; ! 51: ! 52: /* This is *not* reset after each function. It gives each CODE_LABEL ! 53: in the entire compilation a unique label number. */ ! 54: ! 55: static int label_num = 1; ! 56: ! 57: /* Lowest label number in current function. */ ! 58: ! 59: static int first_label_num; ! 60: ! 61: /* Highest label number in current function. ! 62: Zero means use the value of label_num instead. ! 63: This is nonzero only when belatedly compiling an inline function. */ ! 64: ! 65: static int last_label_num; ! 66: ! 67: /* Value label_num had when set_new_first_and_last_label_number was called. ! 68: If label_num has not changed since then, last_label_num is valid. */ ! 69: ! 70: static int base_label_num; ! 71: ! 72: /* Nonzero means do not generate NOTEs for source line numbers. */ ! 73: ! 74: static int no_line_numbers; ! 75: ! 76: /* Commonly used rtx's, so that we only need space for one copy. ! 77: These are initialized once for the entire compilation. ! 78: All of these except perhaps the floating-point CONST_DOUBLEs ! 79: are unique; no other rtx-object will be equal to any of these. */ ! 80: ! 81: rtx pc_rtx; /* (PC) */ ! 82: rtx cc0_rtx; /* (CC0) */ ! 83: rtx cc1_rtx; /* (CC1) (not actually used nowadays) */ ! 84: rtx const0_rtx; /* (CONST_INT 0) */ ! 85: rtx const1_rtx; /* (CONST_INT 1) */ ! 86: rtx const2_rtx; /* (CONST_INT 2) */ ! 87: rtx constm1_rtx; /* (CONST_INT -1) */ ! 88: rtx const_true_rtx; /* (CONST_INT STORE_FLAG_VALUE) */ ! 89: ! 90: /* We record floating-point CONST_DOUBLEs in each floating-point mode for ! 91: the values of 0, 1, and 2. For the integer entries and VOIDmode, we ! 92: record a copy of const[012]_rtx. */ ! 93: ! 94: rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE]; ! 95: ! 96: REAL_VALUE_TYPE dconst0; ! 97: REAL_VALUE_TYPE dconst1; ! 98: REAL_VALUE_TYPE dconst2; ! 99: REAL_VALUE_TYPE dconstm1; ! 100: ! 101: /* All references to the following fixed hard registers go through ! 102: these unique rtl objects. On machines where the frame-pointer and ! 103: arg-pointer are the same register, they use the same unique object. ! 104: ! 105: After register allocation, other rtl objects which used to be pseudo-regs ! 106: may be clobbered to refer to the frame-pointer register. ! 107: But references that were originally to the frame-pointer can be ! 108: distinguished from the others because they contain frame_pointer_rtx. ! 109: ! 110: In an inline procedure, the stack and frame pointer rtxs may not be ! 111: used for anything else. */ ! 112: rtx stack_pointer_rtx; /* (REG:Pmode STACK_POINTER_REGNUM) */ ! 113: rtx frame_pointer_rtx; /* (REG:Pmode FRAME_POINTER_REGNUM) */ ! 114: rtx arg_pointer_rtx; /* (REG:Pmode ARG_POINTER_REGNUM) */ ! 115: rtx struct_value_rtx; /* (REG:Pmode STRUCT_VALUE_REGNUM) */ ! 116: rtx struct_value_incoming_rtx; /* (REG:Pmode STRUCT_VALUE_INCOMING_REGNUM) */ ! 117: rtx static_chain_rtx; /* (REG:Pmode STATIC_CHAIN_REGNUM) */ ! 118: rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */ ! 119: rtx pic_offset_table_rtx; /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */ ! 120: ! 121: rtx virtual_incoming_args_rtx; /* (REG:Pmode VIRTUAL_INCOMING_ARGS_REGNUM) */ ! 122: rtx virtual_stack_vars_rtx; /* (REG:Pmode VIRTUAL_STACK_VARS_REGNUM) */ ! 123: rtx virtual_stack_dynamic_rtx; /* (REG:Pmode VIRTUAL_STACK_DYNAMIC_REGNUM) */ ! 124: rtx virtual_outgoing_args_rtx; /* (REG:Pmode VIRTUAL_OUTGOING_ARGS_REGNUM) */ ! 125: ! 126: /* We make one copy of (const_int C) where C is in ! 127: [- MAX_SAVED_CONST_INT, MAX_SAVED_CONST_INT] ! 128: to save space during the compilation and simplify comparisons of ! 129: integers. */ ! 130: ! 131: #define MAX_SAVED_CONST_INT 64 ! 132: ! 133: static rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1]; ! 134: ! 135: /* The ends of the doubly-linked chain of rtl for the current function. ! 136: Both are reset to null at the start of rtl generation for the function. ! 137: ! 138: start_sequence saves both of these on `sequence_stack' and then ! 139: starts a new, nested sequence of insns. */ ! 140: ! 141: static rtx first_insn = NULL; ! 142: static rtx last_insn = NULL; ! 143: ! 144: /* INSN_UID for next insn emitted. ! 145: Reset to 1 for each function compiled. */ ! 146: ! 147: static int cur_insn_uid = 1; ! 148: ! 149: /* Line number and source file of the last line-number NOTE emitted. ! 150: This is used to avoid generating duplicates. */ ! 151: ! 152: static int last_linenum = 0; ! 153: static char *last_filename = 0; ! 154: ! 155: /* A vector indexed by pseudo reg number. The allocated length ! 156: of this vector is regno_pointer_flag_length. Since this ! 157: vector is needed during the expansion phase when the total ! 158: number of registers in the function is not yet known, ! 159: it is copied and made bigger when necessary. */ ! 160: ! 161: char *regno_pointer_flag; ! 162: int regno_pointer_flag_length; ! 163: ! 164: /* Indexed by pseudo register number, gives the rtx for that pseudo. ! 165: Allocated in parallel with regno_pointer_flag. */ ! 166: ! 167: rtx *regno_reg_rtx; ! 168: ! 169: /* Stack of pending (incomplete) sequences saved by `start_sequence'. ! 170: Each element describes one pending sequence. ! 171: The main insn-chain is saved in the last element of the chain, ! 172: unless the chain is empty. */ ! 173: ! 174: struct sequence_stack *sequence_stack; ! 175: ! 176: /* start_sequence and gen_sequence can make a lot of rtx expressions which are ! 177: shortly thrown away. We use two mechanisms to prevent this waste: ! 178: ! 179: First, we keep a list of the expressions used to represent the sequence ! 180: stack in sequence_element_free_list. ! 181: ! 182: Second, for sizes up to 5 elements, we keep a SEQUENCE and its associated ! 183: rtvec for use by gen_sequence. One entry for each size is sufficient ! 184: because most cases are calls to gen_sequence followed by immediately ! 185: emitting the SEQUENCE. Reuse is safe since emitting a sequence is ! 186: destructive on the insn in it anyway and hence can't be redone. ! 187: ! 188: We do not bother to save this cached data over nested function calls. ! 189: Instead, we just reinitialize them. */ ! 190: ! 191: #define SEQUENCE_RESULT_SIZE 5 ! 192: ! 193: static struct sequence_stack *sequence_element_free_list; ! 194: static rtx sequence_result[SEQUENCE_RESULT_SIZE]; ! 195: ! 196: extern int rtx_equal_function_value_matters; ! 197: ! 198: /* Filename and line number of last line-number note, ! 199: whether we actually emitted it or not. */ ! 200: extern char *emit_filename; ! 201: extern int emit_lineno; ! 202: ! 203: rtx change_address (); ! 204: void init_emit (); ! 205: ! 206: /* rtx gen_rtx (code, mode, [element1, ..., elementn]) ! 207: ** ! 208: ** This routine generates an RTX of the size specified by ! 209: ** <code>, which is an RTX code. The RTX structure is initialized ! 210: ** from the arguments <element1> through <elementn>, which are ! 211: ** interpreted according to the specific RTX type's format. The ! 212: ** special machine mode associated with the rtx (if any) is specified ! 213: ** in <mode>. ! 214: ** ! 215: ** gen_rtx() can be invoked in a way which resembles the lisp-like ! 216: ** rtx it will generate. For example, the following rtx structure: ! 217: ** ! 218: ** (plus:QI (mem:QI (reg:SI 1)) ! 219: ** (mem:QI (plusw:SI (reg:SI 2) (reg:SI 3)))) ! 220: ** ! 221: ** ...would be generated by the following C code: ! 222: ** ! 223: ** gen_rtx (PLUS, QImode, ! 224: ** gen_rtx (MEM, QImode, ! 225: ** gen_rtx (REG, SImode, 1)), ! 226: ** gen_rtx (MEM, QImode, ! 227: ** gen_rtx (PLUS, SImode, ! 228: ** gen_rtx (REG, SImode, 2), ! 229: ** gen_rtx (REG, SImode, 3)))), ! 230: */ ! 231: ! 232: /*VARARGS2*/ ! 233: rtx ! 234: gen_rtx (va_alist) ! 235: va_dcl ! 236: { ! 237: va_list p; ! 238: enum rtx_code code; ! 239: enum machine_mode mode; ! 240: register int i; /* Array indices... */ ! 241: register char *fmt; /* Current rtx's format... */ ! 242: register rtx rt_val; /* RTX to return to caller... */ ! 243: ! 244: va_start (p); ! 245: code = va_arg (p, enum rtx_code); ! 246: mode = va_arg (p, enum machine_mode); ! 247: ! 248: if (code == CONST_INT) ! 249: { ! 250: int arg = va_arg (p, int); ! 251: ! 252: if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT) ! 253: return const_int_rtx[arg + MAX_SAVED_CONST_INT]; ! 254: ! 255: if (const_true_rtx && arg == STORE_FLAG_VALUE) ! 256: return const_true_rtx; ! 257: ! 258: rt_val = rtx_alloc (code); ! 259: INTVAL (rt_val) = arg; ! 260: } ! 261: else if (code == REG) ! 262: { ! 263: int regno = va_arg (p, int); ! 264: ! 265: /* In case the MD file explicitly references the frame pointer, have ! 266: all such references point to the same frame pointer. This is used ! 267: during frame pointer elimination to distinguish the explicit ! 268: references to these registers from psuedos that happened to be ! 269: assigned to them. ! 270: ! 271: If we have eliminated the frame pointer or arg pointer, we will ! 272: be using it as a normal register, for example as a spill register. ! 273: In such cases, we might be accessing it in a mode that is not ! 274: Pmode and therefore cannot use the pre-allocated rtx. */ ! 275: ! 276: if (frame_pointer_rtx && regno == FRAME_POINTER_REGNUM && mode == Pmode) ! 277: return frame_pointer_rtx; ! 278: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM ! 279: if (arg_pointer_rtx && regno == ARG_POINTER_REGNUM && mode == Pmode) ! 280: return arg_pointer_rtx; ! 281: #endif ! 282: if (stack_pointer_rtx && regno == STACK_POINTER_REGNUM && mode == Pmode) ! 283: return stack_pointer_rtx; ! 284: else ! 285: { ! 286: rt_val = rtx_alloc (code); ! 287: rt_val->mode = mode; ! 288: REGNO (rt_val) = regno; ! 289: return rt_val; ! 290: } ! 291: } ! 292: else ! 293: { ! 294: rt_val = rtx_alloc (code); /* Allocate the storage space. */ ! 295: rt_val->mode = mode; /* Store the machine mode... */ ! 296: ! 297: fmt = GET_RTX_FORMAT (code); /* Find the right format... */ ! 298: for (i = 0; i < GET_RTX_LENGTH (code); i++) ! 299: { ! 300: switch (*fmt++) ! 301: { ! 302: case '0': /* Unused field. */ ! 303: break; ! 304: ! 305: case 'i': /* An integer? */ ! 306: XINT (rt_val, i) = va_arg (p, int); ! 307: break; ! 308: ! 309: case 's': /* A string? */ ! 310: XSTR (rt_val, i) = va_arg (p, char *); ! 311: break; ! 312: ! 313: case 'e': /* An expression? */ ! 314: case 'u': /* An insn? Same except when printing. */ ! 315: XEXP (rt_val, i) = va_arg (p, rtx); ! 316: break; ! 317: ! 318: case 'E': /* An RTX vector? */ ! 319: XVEC (rt_val, i) = va_arg (p, rtvec); ! 320: break; ! 321: ! 322: default: ! 323: abort(); ! 324: } ! 325: } ! 326: } ! 327: va_end (p); ! 328: return rt_val; /* Return the new RTX... */ ! 329: } ! 330: ! 331: /* gen_rtvec (n, [rt1, ..., rtn]) ! 332: ** ! 333: ** This routine creates an rtvec and stores within it the ! 334: ** pointers to rtx's which are its arguments. ! 335: */ ! 336: ! 337: /*VARARGS1*/ ! 338: rtvec ! 339: gen_rtvec (va_alist) ! 340: va_dcl ! 341: { ! 342: int n, i; ! 343: va_list p; ! 344: rtx *vector; ! 345: ! 346: va_start (p); ! 347: n = va_arg (p, int); ! 348: ! 349: if (n == 0) ! 350: return NULL_RTVEC; /* Don't allocate an empty rtvec... */ ! 351: ! 352: vector = (rtx *) alloca (n * sizeof (rtx)); ! 353: for (i = 0; i < n; i++) ! 354: vector[i] = va_arg (p, rtx); ! 355: va_end (p); ! 356: ! 357: return gen_rtvec_v (n, vector); ! 358: } ! 359: ! 360: rtvec ! 361: gen_rtvec_v (n, argp) ! 362: int n; ! 363: rtx *argp; ! 364: { ! 365: register int i; ! 366: register rtvec rt_val; ! 367: ! 368: if (n == 0) ! 369: return NULL_RTVEC; /* Don't allocate an empty rtvec... */ ! 370: ! 371: rt_val = rtvec_alloc (n); /* Allocate an rtvec... */ ! 372: ! 373: for (i = 0; i < n; i++) ! 374: rt_val->elem[i].rtx = *argp++; ! 375: ! 376: return rt_val; ! 377: } ! 378: ! 379: /* Generate a REG rtx for a new pseudo register of mode MODE. ! 380: This pseudo is assigned the next sequential register number. */ ! 381: ! 382: rtx ! 383: gen_reg_rtx (mode) ! 384: enum machine_mode mode; ! 385: { ! 386: register rtx val; ! 387: ! 388: /* Don't let anything called by or after reload create new registers ! 389: (actually, registers can't be created after flow, but this is a good ! 390: approximation). */ ! 391: ! 392: if (reload_in_progress || reload_completed) ! 393: abort (); ! 394: ! 395: /* Make sure regno_pointer_flag and regno_reg_rtx are large ! 396: enough to have an element for this pseudo reg number. */ ! 397: ! 398: if (reg_rtx_no == regno_pointer_flag_length) ! 399: { ! 400: rtx *new1; ! 401: char *new = ! 402: (char *) oballoc (regno_pointer_flag_length * 2); ! 403: bzero (new, regno_pointer_flag_length * 2); ! 404: bcopy (regno_pointer_flag, new, regno_pointer_flag_length); ! 405: regno_pointer_flag = new; ! 406: ! 407: new1 = (rtx *) oballoc (regno_pointer_flag_length * 2 * sizeof (rtx)); ! 408: bzero (new1, regno_pointer_flag_length * 2 * sizeof (rtx)); ! 409: bcopy (regno_reg_rtx, new1, regno_pointer_flag_length * sizeof (rtx)); ! 410: regno_reg_rtx = new1; ! 411: ! 412: regno_pointer_flag_length *= 2; ! 413: } ! 414: ! 415: val = gen_rtx (REG, mode, reg_rtx_no); ! 416: regno_reg_rtx[reg_rtx_no++] = val; ! 417: return val; ! 418: } ! 419: ! 420: /* Identify REG as a probable pointer register. */ ! 421: ! 422: void ! 423: mark_reg_pointer (reg) ! 424: rtx reg; ! 425: { ! 426: REGNO_POINTER_FLAG (REGNO (reg)) = 1; ! 427: } ! 428: ! 429: /* Return 1 plus largest pseudo reg number used in the current function. */ ! 430: ! 431: int ! 432: max_reg_num () ! 433: { ! 434: return reg_rtx_no; ! 435: } ! 436: ! 437: /* Return 1 + the largest label number used so far in the current function. */ ! 438: ! 439: int ! 440: max_label_num () ! 441: { ! 442: if (last_label_num && label_num == base_label_num) ! 443: return last_label_num; ! 444: return label_num; ! 445: } ! 446: ! 447: /* Return first label number used in this function (if any were used). */ ! 448: ! 449: int ! 450: get_first_label_num () ! 451: { ! 452: return first_label_num; ! 453: } ! 454: ! 455: /* Return a value representing some low-order bits of X, where the number ! 456: of low-order bits is given by MODE. Note that no conversion is done ! 457: between floating-point and fixed-point values, rather, the bit ! 458: representation is returned. ! 459: ! 460: This function handles the cases in common between gen_lowpart, below, ! 461: and two variants in cse.c and combine.c. These are the cases that can ! 462: be safely handled at all points in the compilation. ! 463: ! 464: If this is not a case we can handle, return 0. */ ! 465: ! 466: rtx ! 467: gen_lowpart_common (mode, x) ! 468: enum machine_mode mode; ! 469: register rtx x; ! 470: { ! 471: int word = 0; ! 472: ! 473: if (GET_MODE (x) == mode) ! 474: return x; ! 475: ! 476: /* MODE must occupy no more words than the mode of X. */ ! 477: if (GET_MODE (x) != VOIDmode ! 478: && ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD ! 479: > ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1)) ! 480: / UNITS_PER_WORD))) ! 481: return 0; ! 482: ! 483: if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) ! 484: word = ((GET_MODE_SIZE (GET_MODE (x)) ! 485: - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)) ! 486: / UNITS_PER_WORD); ! 487: ! 488: if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) ! 489: && GET_MODE_CLASS (mode) == MODE_INT) ! 490: { ! 491: /* If we are getting the low-order part of something that has been ! 492: sign- or zero-extended, we can either just use the object being ! 493: extended or make a narrower extension. If we want an even smaller ! 494: piece than the size of the object being extended, call ourselves ! 495: recursively. ! 496: ! 497: This case is used mostly by combine and cse. */ ! 498: ! 499: if (GET_MODE (XEXP (x, 0)) == mode) ! 500: return XEXP (x, 0); ! 501: else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (XEXP (x, 0)))) ! 502: return gen_lowpart_common (mode, XEXP (x, 0)); ! 503: else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))) ! 504: return gen_rtx (GET_CODE (x), mode, XEXP (x, 0)); ! 505: } ! 506: else if (GET_CODE (x) == SUBREG ! 507: && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD ! 508: || GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x)))) ! 509: return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0 ! 510: ? SUBREG_REG (x) ! 511: : gen_rtx (SUBREG, mode, SUBREG_REG (x), SUBREG_WORD (x))); ! 512: else if (GET_CODE (x) == REG) ! 513: { ! 514: /* If the register is not valid for MODE, return 0. If we don't ! 515: do this, there is no way to fix up the resulting REG later. */ ! 516: if (REGNO (x) < FIRST_PSEUDO_REGISTER ! 517: && ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode)) ! 518: return 0; ! 519: else if (REGNO (x) < FIRST_PSEUDO_REGISTER ! 520: /* integrate.c can't handle parts of a return value register. */ ! 521: && (! REG_FUNCTION_VALUE_P (x) ! 522: || ! rtx_equal_function_value_matters)) ! 523: return gen_rtx (REG, mode, REGNO (x) + word); ! 524: else ! 525: return gen_rtx (SUBREG, mode, x, word); ! 526: } ! 527: ! 528: /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits ! 529: from the low-order part of the constant. */ ! 530: else if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (x) == VOIDmode ! 531: && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)) ! 532: return (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_INT ? x ! 533: : (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_INT ! 534: && GET_CODE (x) == CONST_INT) ? x ! 535: : gen_rtx (CONST_INT, VOIDmode, ! 536: (GET_MODE_MASK (mode) ! 537: & (GET_CODE (x) == CONST_INT ! 538: ? INTVAL (x) : CONST_DOUBLE_LOW (x))))); ! 539: ! 540: /* Otherwise, we can't do this. */ ! 541: return 0; ! 542: } ! 543: ! 544: /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value, ! 545: return an rtx (MEM, SUBREG, or CONST_INT) that refers to the ! 546: least-significant part of X. ! 547: MODE specifies how big a part of X to return; ! 548: it usually should not be larger than a word. ! 549: If X is a MEM whose address is a QUEUED, the value may be so also. */ ! 550: ! 551: rtx ! 552: gen_lowpart (mode, x) ! 553: enum machine_mode mode; ! 554: register rtx x; ! 555: { ! 556: rtx result = gen_lowpart_common (mode, x); ! 557: ! 558: if (result) ! 559: return result; ! 560: else if (GET_CODE (x) == MEM) ! 561: { ! 562: /* The only additional case we can do is MEM. */ ! 563: register int offset = 0; ! 564: if (WORDS_BIG_ENDIAN) ! 565: offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) ! 566: - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)); ! 567: ! 568: if (BYTES_BIG_ENDIAN) ! 569: /* Adjust the address so that the address-after-the-data ! 570: is unchanged. */ ! 571: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) ! 572: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); ! 573: ! 574: return change_address (x, mode, plus_constant (XEXP (x, 0), offset)); ! 575: } ! 576: else ! 577: abort (); ! 578: } ! 579: ! 580: /* Return 1 iff X, assumed to be a SUBREG, ! 581: refers to the least significant part of its containing reg. ! 582: If X is not a SUBREG, always return 1 (it is its own low part!). */ ! 583: ! 584: int ! 585: subreg_lowpart_p (x) ! 586: rtx x; ! 587: { ! 588: if (GET_CODE (x) != SUBREG) ! 589: return 1; ! 590: ! 591: if (WORDS_BIG_ENDIAN ! 592: && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD) ! 593: return (SUBREG_WORD (x) ! 594: == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) ! 595: - MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)) ! 596: / UNITS_PER_WORD)); ! 597: ! 598: return SUBREG_WORD (x) == 0; ! 599: } ! 600: ! 601: /* Return subword I of operand OP. ! 602: The word number, I, is interpreted as the word number starting at the ! 603: low-order address. Word 0 is the low-order word if not WORDS_BIG_ENDIAN, ! 604: otherwise it is the high-order word. ! 605: ! 606: If we cannot extract the required word, we return zero. Otherwise, an ! 607: rtx corresponding to the requested word will be returned. ! 608: ! 609: VALIDATE_ADDRESS is nonzero if the address should be validated. Before ! 610: reload has completed, a valid address will always be returned. After ! 611: reload, if a valid address cannot be returned, we return zero. ! 612: ! 613: If VALIDATE_ADDRESS is zero, we simply form the required address; validating ! 614: it is the responsibility of the caller. ! 615: ! 616: MODE is the mode of OP in case it is a CONST_INT. */ ! 617: ! 618: rtx ! 619: operand_subword (op, i, validate_address, mode) ! 620: rtx op; ! 621: int i; ! 622: int validate_address; ! 623: enum machine_mode mode; ! 624: { ! 625: int val; ! 626: int size_ratio = HOST_BITS_PER_INT / BITS_PER_WORD; ! 627: ! 628: if (mode == VOIDmode) ! 629: mode = GET_MODE (op); ! 630: ! 631: if (mode == VOIDmode) ! 632: abort (); ! 633: ! 634: /* If OP is narrower than a word or if we want a word outside OP, fail. */ ! 635: if (mode != BLKmode ! 636: && (GET_MODE_SIZE (mode) < UNITS_PER_WORD ! 637: || (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))) ! 638: return 0; ! 639: ! 640: /* If OP is already an integer word, return it. */ ! 641: if (GET_MODE_CLASS (mode) == MODE_INT ! 642: && GET_MODE_SIZE (mode) == UNITS_PER_WORD) ! 643: return op; ! 644: ! 645: /* If OP is a REG or SUBREG, we can handle it very simply. */ ! 646: if (GET_CODE (op) == REG) ! 647: { ! 648: /* If the register is not valid for MODE, return 0. If we don't ! 649: do this, there is no way to fix up the resulting REG later. */ ! 650: if (REGNO (op) < FIRST_PSEUDO_REGISTER ! 651: && ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)) ! 652: return 0; ! 653: else if (REGNO (op) >= FIRST_PSEUDO_REGISTER ! 654: || (REG_FUNCTION_VALUE_P (op) ! 655: && rtx_equal_function_value_matters)) ! 656: return gen_rtx (SUBREG, word_mode, op, i); ! 657: else ! 658: return gen_rtx (REG, word_mode, REGNO (op) + i); ! 659: } ! 660: else if (GET_CODE (op) == SUBREG) ! 661: return gen_rtx (SUBREG, word_mode, SUBREG_REG (op), i + SUBREG_WORD (op)); ! 662: ! 663: /* Form a new MEM at the requested address. */ ! 664: if (GET_CODE (op) == MEM) ! 665: { ! 666: rtx addr = plus_constant (XEXP (op, 0), i * UNITS_PER_WORD); ! 667: rtx new; ! 668: ! 669: if (validate_address) ! 670: { ! 671: if (reload_completed) ! 672: { ! 673: if (! strict_memory_address_p (word_mode, addr)) ! 674: return 0; ! 675: } ! 676: else ! 677: addr = memory_address (word_mode, addr); ! 678: } ! 679: ! 680: new = gen_rtx (MEM, word_mode, addr); ! 681: ! 682: MEM_VOLATILE_P (new) = MEM_VOLATILE_P (op); ! 683: MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (op); ! 684: RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op); ! 685: ! 686: return new; ! 687: } ! 688: ! 689: /* The only remaining cases are when OP is a constant. If the host and ! 690: target floating formats are the same, handling two-word floating ! 691: constants are easy. */ ! 692: if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! 693: && HOST_BITS_PER_INT == BITS_PER_WORD) ! 694: || flag_pretend_float) ! 695: && GET_MODE_CLASS (mode) == MODE_FLOAT ! 696: && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD ! 697: && GET_CODE (op) == CONST_DOUBLE) ! 698: return gen_rtx (CONST_INT, VOIDmode, ! 699: i ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op)); ! 700: ! 701: /* Single word float is a little harder, since single- and double-word ! 702: values often do not have the same high-order bits. We have already ! 703: verified that we want the only defined word of the single-word value. */ ! 704: if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! 705: && HOST_BITS_PER_INT == BITS_PER_WORD) ! 706: || flag_pretend_float) ! 707: && GET_MODE_CLASS (mode) == MODE_FLOAT ! 708: && GET_MODE_SIZE (mode) == UNITS_PER_WORD ! 709: && GET_CODE (op) == CONST_DOUBLE) ! 710: { ! 711: double d; ! 712: union {float f; int i; } u; ! 713: ! 714: REAL_VALUE_FROM_CONST_DOUBLE (d, op); ! 715: ! 716: u.f = d; ! 717: return gen_rtx (CONST_INT, VOIDmode, u.i); ! 718: } ! 719: ! 720: /* The only remaining cases that we can handle are integers. ! 721: Convert to proper endianness now since these cases need it. ! 722: At this point, i == 0 means the low-order word. ! 723: ! 724: Note that it must be that BITS_PER_WORD <= HOST_BITS_PER_INT. ! 725: This is because if it were greater, it could only have been two ! 726: times greater since we do not support making wider constants. In ! 727: that case, it MODE would have already been the proper size and ! 728: it would have been handled above. This means we do not have to ! 729: worry about the case where we would be returning a CONST_DOUBLE. */ ! 730: ! 731: if (GET_MODE_CLASS (mode) != MODE_INT ! 732: || (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE)) ! 733: return 0; ! 734: ! 735: if (WORDS_BIG_ENDIAN) ! 736: i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i; ! 737: ! 738: /* Find out which word on the host machine this value is in and get ! 739: it from the constant. */ ! 740: val = (i / size_ratio == 0 ! 741: ? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op)) ! 742: : (GET_CODE (op) == CONST_INT ! 743: ? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op))); ! 744: ! 745: /* If BITS_PER_WORD is smaller than an int, get the appropriate bits. */ ! 746: if (BITS_PER_WORD < HOST_BITS_PER_INT) ! 747: val = ((val >> ((i % size_ratio) * BITS_PER_WORD)) ! 748: & ((1 << (BITS_PER_WORD % HOST_BITS_PER_INT)) - 1)); ! 749: ! 750: return gen_rtx (CONST_INT, VOIDmode, val); ! 751: } ! 752: ! 753: /* Similar to `operand_subword', but never return 0. If we can't extract ! 754: the required subword, put OP into a register and try again. If that fails, ! 755: abort. We always validate the address in this case. It is not valid ! 756: to call this function after reload; it is mostly meant for RTL ! 757: generation. ! 758: ! 759: MODE is the mode of OP, in case it is CONST_INT. */ ! 760: ! 761: rtx ! 762: operand_subword_force (op, i, mode) ! 763: rtx op; ! 764: int i; ! 765: enum machine_mode mode; ! 766: { ! 767: rtx result = operand_subword (op, i, 1, mode); ! 768: ! 769: if (result) ! 770: return result; ! 771: ! 772: if (mode != BLKmode && mode != VOIDmode) ! 773: op = force_reg (mode, op); ! 774: ! 775: result = operand_subword (op, i, 1, mode); ! 776: if (result == 0) ! 777: abort (); ! 778: ! 779: return result; ! 780: } ! 781: ! 782: /* Given a compare instruction, swap the operands. ! 783: A test instruction is changed into a compare of 0 against the operand. */ ! 784: ! 785: void ! 786: reverse_comparison (insn) ! 787: rtx insn; ! 788: { ! 789: rtx body = PATTERN (insn); ! 790: rtx comp; ! 791: ! 792: if (GET_CODE (body) == SET) ! 793: comp = SET_SRC (body); ! 794: else ! 795: comp = SET_SRC (XVECEXP (body, 0, 0)); ! 796: ! 797: if (GET_CODE (comp) == COMPARE) ! 798: { ! 799: rtx op0 = XEXP (comp, 0); ! 800: rtx op1 = XEXP (comp, 1); ! 801: XEXP (comp, 0) = op1; ! 802: XEXP (comp, 1) = op0; ! 803: } ! 804: else ! 805: { ! 806: rtx new = gen_rtx (COMPARE, VOIDmode, ! 807: CONST0_RTX (GET_MODE (comp)), comp); ! 808: if (GET_CODE (body) == SET) ! 809: SET_SRC (body) = new; ! 810: else ! 811: SET_SRC (XVECEXP (body, 0, 0)) = new; ! 812: } ! 813: } ! 814: ! 815: /* Return a memory reference like MEMREF, but with its mode changed ! 816: to MODE and its address changed to ADDR. ! 817: (VOIDmode means don't change the mode. ! 818: NULL for ADDR means don't change the address.) */ ! 819: ! 820: rtx ! 821: change_address (memref, mode, addr) ! 822: rtx memref; ! 823: enum machine_mode mode; ! 824: rtx addr; ! 825: { ! 826: rtx new; ! 827: ! 828: if (GET_CODE (memref) != MEM) ! 829: abort (); ! 830: if (mode == VOIDmode) ! 831: mode = GET_MODE (memref); ! 832: if (addr == 0) ! 833: addr = XEXP (memref, 0); ! 834: ! 835: /* If reload is in progress or has completed, ADDR must be valid. ! 836: Otherwise, we can call memory_address to make it valid. */ ! 837: if (reload_completed || reload_in_progress) ! 838: { ! 839: if (! memory_address_p (mode, addr)) ! 840: abort (); ! 841: } ! 842: else ! 843: addr = memory_address (mode, addr); ! 844: ! 845: new = gen_rtx (MEM, mode, addr); ! 846: MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref); ! 847: RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref); ! 848: MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (memref); ! 849: return new; ! 850: } ! 851: ! 852: /* Return a newly created CODE_LABEL rtx with a unique label number. */ ! 853: ! 854: rtx ! 855: gen_label_rtx () ! 856: { ! 857: register rtx label = gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0, label_num++, 0); ! 858: LABEL_NUSES (label) = 0; ! 859: return label; ! 860: } ! 861: ! 862: /* For procedure integration. */ ! 863: ! 864: /* Return a newly created INLINE_HEADER rtx. Should allocate this ! 865: from a permanent obstack when the opportunity arises. */ ! 866: ! 867: rtx ! 868: gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno, ! 869: last_labelno, max_parm_regnum, max_regnum, args_size, ! 870: pops_args, stack_slots, function_flags, ! 871: outgoing_args_size, original_arg_vector, ! 872: original_decl_initial) ! 873: rtx first_insn, first_parm_insn; ! 874: int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size; ! 875: int pops_args; ! 876: rtx stack_slots; ! 877: int function_flags; ! 878: int outgoing_args_size; ! 879: rtvec original_arg_vector; ! 880: rtx original_decl_initial; ! 881: { ! 882: rtx header = gen_rtx (INLINE_HEADER, VOIDmode, ! 883: cur_insn_uid++, NULL, ! 884: first_insn, first_parm_insn, ! 885: first_labelno, last_labelno, ! 886: max_parm_regnum, max_regnum, args_size, pops_args, ! 887: stack_slots, function_flags, outgoing_args_size, ! 888: original_arg_vector, original_decl_initial); ! 889: return header; ! 890: } ! 891: ! 892: /* Install new pointers to the first and last insns in the chain. ! 893: Used for an inline-procedure after copying the insn chain. */ ! 894: ! 895: void ! 896: set_new_first_and_last_insn (first, last) ! 897: rtx first, last; ! 898: { ! 899: first_insn = first; ! 900: last_insn = last; ! 901: } ! 902: ! 903: /* Set the range of label numbers found in the current function. ! 904: This is used when belatedly compiling an inline function. */ ! 905: ! 906: void ! 907: set_new_first_and_last_label_num (first, last) ! 908: int first, last; ! 909: { ! 910: base_label_num = label_num; ! 911: first_label_num = first; ! 912: last_label_num = last; ! 913: } ! 914: ! 915: /* Save all variables describing the current status into the structure *P. ! 916: This is used before starting a nested function. */ ! 917: ! 918: void ! 919: save_emit_status (p) ! 920: struct function *p; ! 921: { ! 922: p->reg_rtx_no = reg_rtx_no; ! 923: p->first_label_num = first_label_num; ! 924: p->first_insn = first_insn; ! 925: p->last_insn = last_insn; ! 926: p->sequence_stack = sequence_stack; ! 927: p->cur_insn_uid = cur_insn_uid; ! 928: p->last_linenum = last_linenum; ! 929: p->last_filename = last_filename; ! 930: p->regno_pointer_flag = regno_pointer_flag; ! 931: p->regno_pointer_flag_length = regno_pointer_flag_length; ! 932: p->regno_reg_rtx = regno_reg_rtx; ! 933: } ! 934: ! 935: /* Restore all variables describing the current status from the structure *P. ! 936: This is used after a nested function. */ ! 937: ! 938: void ! 939: restore_emit_status (p) ! 940: struct function *p; ! 941: { ! 942: int i; ! 943: ! 944: reg_rtx_no = p->reg_rtx_no; ! 945: first_label_num = p->first_label_num; ! 946: first_insn = p->first_insn; ! 947: last_insn = p->last_insn; ! 948: sequence_stack = p->sequence_stack; ! 949: cur_insn_uid = p->cur_insn_uid; ! 950: last_linenum = p->last_linenum; ! 951: last_filename = p->last_filename; ! 952: regno_pointer_flag = p->regno_pointer_flag; ! 953: regno_pointer_flag_length = p->regno_pointer_flag_length; ! 954: regno_reg_rtx = p->regno_reg_rtx; ! 955: ! 956: /* Clear our cache of rtx expressions for start_sequence and gen_sequence. */ ! 957: sequence_element_free_list = 0; ! 958: for (i = 0; i < SEQUENCE_RESULT_SIZE; i++) ! 959: sequence_result[i] = 0; ! 960: } ! 961: ! 962: /* Go through all the RTL insn bodies and copy any invalid shared structure. ! 963: It does not work to do this twice, because the mark bits set here ! 964: are not cleared afterwards. */ ! 965: ! 966: void ! 967: unshare_all_rtl (insn) ! 968: register rtx insn; ! 969: { ! 970: for (; insn; insn = NEXT_INSN (insn)) ! 971: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN ! 972: || GET_CODE (insn) == CALL_INSN) ! 973: { ! 974: PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn)); ! 975: REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn)); ! 976: LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn)); ! 977: } ! 978: ! 979: /* Make sure the addresses of stack slots found outside the insn chain ! 980: (such as, in DECL_RTL of a variable) are not shared ! 981: with the insn chain. ! 982: ! 983: This special care is necessary when the stack slot MEM does not ! 984: actually appear in the insn chain. If it does appear, its address ! 985: is unshared from all else at that point. */ ! 986: ! 987: copy_rtx_if_shared (stack_slot_list); ! 988: } ! 989: ! 990: /* Mark ORIG as in use, and return a copy of it if it was already in use. ! 991: Recursively does the same for subexpressions. */ ! 992: ! 993: rtx ! 994: copy_rtx_if_shared (orig) ! 995: rtx orig; ! 996: { ! 997: register rtx x = orig; ! 998: register int i; ! 999: register enum rtx_code code; ! 1000: register char *format_ptr; ! 1001: int copied = 0; ! 1002: ! 1003: if (x == 0) ! 1004: return 0; ! 1005: ! 1006: code = GET_CODE (x); ! 1007: ! 1008: /* These types may be freely shared. */ ! 1009: ! 1010: switch (code) ! 1011: { ! 1012: case REG: ! 1013: case QUEUED: ! 1014: case CONST_INT: ! 1015: case CONST_DOUBLE: ! 1016: case SYMBOL_REF: ! 1017: case CODE_LABEL: ! 1018: case PC: ! 1019: case CC0: ! 1020: case SCRATCH: ! 1021: /* SCRATCH must be shared because they represent distinct values. */ ! 1022: return x; ! 1023: ! 1024: case INSN: ! 1025: case JUMP_INSN: ! 1026: case CALL_INSN: ! 1027: case NOTE: ! 1028: case LABEL_REF: ! 1029: case BARRIER: ! 1030: /* The chain of insns is not being copied. */ ! 1031: return x; ! 1032: ! 1033: case MEM: ! 1034: /* A MEM is allowed to be shared if its address is constant ! 1035: or is a constant plus one of the special registers. */ ! 1036: if (CONSTANT_ADDRESS_P (XEXP (x, 0)) ! 1037: || XEXP (x, 0) == virtual_stack_vars_rtx ! 1038: || XEXP (x, 0) == virtual_incoming_args_rtx) ! 1039: return x; ! 1040: ! 1041: if (GET_CODE (XEXP (x, 0)) == PLUS ! 1042: && (XEXP (XEXP (x, 0), 0) == virtual_stack_vars_rtx ! 1043: || XEXP (XEXP (x, 0), 0) == virtual_incoming_args_rtx) ! 1044: && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1))) ! 1045: { ! 1046: /* This MEM can appear in more than one place, ! 1047: but its address better not be shared with anything else. */ ! 1048: if (! x->used) ! 1049: XEXP (x, 0) = copy_rtx_if_shared (XEXP (x, 0)); ! 1050: x->used = 1; ! 1051: return x; ! 1052: } ! 1053: } ! 1054: ! 1055: /* This rtx may not be shared. If it has already been seen, ! 1056: replace it with a copy of itself. */ ! 1057: ! 1058: if (x->used) ! 1059: { ! 1060: register rtx copy; ! 1061: ! 1062: copy = rtx_alloc (code); ! 1063: bcopy (x, copy, (sizeof (*copy) - sizeof (copy->fld) ! 1064: + sizeof (copy->fld[0]) * GET_RTX_LENGTH (code))); ! 1065: x = copy; ! 1066: copied = 1; ! 1067: } ! 1068: x->used = 1; ! 1069: ! 1070: /* Now scan the subexpressions recursively. ! 1071: We can store any replaced subexpressions directly into X ! 1072: since we know X is not shared! Any vectors in X ! 1073: must be copied if X was copied. */ ! 1074: ! 1075: format_ptr = GET_RTX_FORMAT (code); ! 1076: ! 1077: for (i = 0; i < GET_RTX_LENGTH (code); i++) ! 1078: { ! 1079: switch (*format_ptr++) ! 1080: { ! 1081: case 'e': ! 1082: XEXP (x, i) = copy_rtx_if_shared (XEXP (x, i)); ! 1083: break; ! 1084: ! 1085: case 'E': ! 1086: if (XVEC (x, i) != NULL) ! 1087: { ! 1088: register int j; ! 1089: ! 1090: if (copied) ! 1091: XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0)); ! 1092: for (j = 0; j < XVECLEN (x, i); j++) ! 1093: XVECEXP (x, i, j) ! 1094: = copy_rtx_if_shared (XVECEXP (x, i, j)); ! 1095: } ! 1096: break; ! 1097: } ! 1098: } ! 1099: return x; ! 1100: } ! 1101: ! 1102: /* Clear all the USED bits in X to allow copy_rtx_if_shared to be used ! 1103: to look for shared sub-parts. */ ! 1104: ! 1105: void ! 1106: reset_used_flags (x) ! 1107: rtx x; ! 1108: { ! 1109: register int i, j; ! 1110: register enum rtx_code code; ! 1111: register char *format_ptr; ! 1112: int copied = 0; ! 1113: ! 1114: if (x == 0) ! 1115: return; ! 1116: ! 1117: code = GET_CODE (x); ! 1118: ! 1119: /* These types may be freely shared so we needn't do any reseting ! 1120: for them. */ ! 1121: ! 1122: switch (code) ! 1123: { ! 1124: case REG: ! 1125: case QUEUED: ! 1126: case CONST_INT: ! 1127: case CONST_DOUBLE: ! 1128: case SYMBOL_REF: ! 1129: case CODE_LABEL: ! 1130: case PC: ! 1131: case CC0: ! 1132: return; ! 1133: ! 1134: case INSN: ! 1135: case JUMP_INSN: ! 1136: case CALL_INSN: ! 1137: case NOTE: ! 1138: case LABEL_REF: ! 1139: case BARRIER: ! 1140: /* The chain of insns is not being copied. */ ! 1141: return; ! 1142: } ! 1143: ! 1144: x->used = 0; ! 1145: ! 1146: format_ptr = GET_RTX_FORMAT (code); ! 1147: for (i = 0; i < GET_RTX_LENGTH (code); i++) ! 1148: { ! 1149: switch (*format_ptr++) ! 1150: { ! 1151: case 'e': ! 1152: reset_used_flags (XEXP (x, i)); ! 1153: break; ! 1154: ! 1155: case 'E': ! 1156: for (j = 0; j < XVECLEN (x, i); j++) ! 1157: reset_used_flags (XVECEXP (x, i, j)); ! 1158: break; ! 1159: } ! 1160: } ! 1161: } ! 1162: ! 1163: /* Copy X if necessary so that it won't be altered by changes in OTHER. ! 1164: Return X or the rtx for the pseudo reg the value of X was copied into. ! 1165: OTHER must be valid as a SET_DEST. */ ! 1166: ! 1167: rtx ! 1168: make_safe_from (x, other) ! 1169: rtx x, other; ! 1170: { ! 1171: while (1) ! 1172: switch (GET_CODE (other)) ! 1173: { ! 1174: case SUBREG: ! 1175: other = SUBREG_REG (other); ! 1176: break; ! 1177: case STRICT_LOW_PART: ! 1178: case SIGN_EXTEND: ! 1179: case ZERO_EXTEND: ! 1180: other = XEXP (other, 0); ! 1181: break; ! 1182: default: ! 1183: goto done; ! 1184: } ! 1185: done: ! 1186: if ((GET_CODE (other) == MEM ! 1187: && ! CONSTANT_P (x) ! 1188: && GET_CODE (x) != REG ! 1189: && GET_CODE (x) != SUBREG) ! 1190: || (GET_CODE (other) == REG ! 1191: && (REGNO (other) < FIRST_PSEUDO_REGISTER ! 1192: || reg_mentioned_p (other, x)))) ! 1193: { ! 1194: rtx temp = gen_reg_rtx (GET_MODE (x)); ! 1195: emit_move_insn (temp, x); ! 1196: return temp; ! 1197: } ! 1198: return x; ! 1199: } ! 1200: ! 1201: /* Emission of insns (adding them to the doubly-linked list). */ ! 1202: ! 1203: /* Return the first insn of the current sequence or current function. */ ! 1204: ! 1205: rtx ! 1206: get_insns () ! 1207: { ! 1208: return first_insn; ! 1209: } ! 1210: ! 1211: /* Return the last insn emitted in current sequence or current function. */ ! 1212: ! 1213: rtx ! 1214: get_last_insn () ! 1215: { ! 1216: return last_insn; ! 1217: } ! 1218: ! 1219: /* Specify a new insn as the last in the chain. */ ! 1220: ! 1221: void ! 1222: set_last_insn (insn) ! 1223: rtx insn; ! 1224: { ! 1225: if (NEXT_INSN (insn) != 0) ! 1226: abort (); ! 1227: last_insn = insn; ! 1228: } ! 1229: ! 1230: /* Return the last insn emitted, even if it is in a sequence now pushed. */ ! 1231: ! 1232: rtx ! 1233: get_last_insn_anywhere () ! 1234: { ! 1235: struct sequence_stack *stack; ! 1236: if (last_insn) ! 1237: return last_insn; ! 1238: for (stack = sequence_stack; stack; stack = stack->next) ! 1239: if (stack->last != 0) ! 1240: return stack->last; ! 1241: return 0; ! 1242: } ! 1243: ! 1244: /* Return a number larger than any instruction's uid in this function. */ ! 1245: ! 1246: int ! 1247: get_max_uid () ! 1248: { ! 1249: return cur_insn_uid; ! 1250: } ! 1251: ! 1252: /* Return the next insn. If it is a SEQUENCE, return the first insn ! 1253: of the sequence. */ ! 1254: ! 1255: rtx ! 1256: next_insn (insn) ! 1257: rtx insn; ! 1258: { ! 1259: if (insn) ! 1260: { ! 1261: insn = NEXT_INSN (insn); ! 1262: if (insn && GET_CODE (insn) == INSN ! 1263: && GET_CODE (PATTERN (insn)) == SEQUENCE) ! 1264: insn = XVECEXP (PATTERN (insn), 0, 0); ! 1265: } ! 1266: ! 1267: return insn; ! 1268: } ! 1269: ! 1270: /* Return the previous insn. If it is a SEQUENCE, return the last insn ! 1271: of the sequence. */ ! 1272: ! 1273: rtx ! 1274: previous_insn (insn) ! 1275: rtx insn; ! 1276: { ! 1277: if (insn) ! 1278: { ! 1279: insn = PREV_INSN (insn); ! 1280: if (insn && GET_CODE (insn) == INSN ! 1281: && GET_CODE (PATTERN (insn)) == SEQUENCE) ! 1282: insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1); ! 1283: } ! 1284: ! 1285: return insn; ! 1286: } ! 1287: ! 1288: /* Return the next insn after INSN that is not a NOTE. This routine does not ! 1289: look inside SEQUENCEs. */ ! 1290: ! 1291: rtx ! 1292: next_nonnote_insn (insn) ! 1293: rtx insn; ! 1294: { ! 1295: while (insn) ! 1296: { ! 1297: insn = NEXT_INSN (insn); ! 1298: if (insn == 0 || GET_CODE (insn) != NOTE) ! 1299: break; ! 1300: } ! 1301: ! 1302: return insn; ! 1303: } ! 1304: ! 1305: /* Return the previous insn before INSN that is not a NOTE. This routine does ! 1306: not look inside SEQUENCEs. */ ! 1307: ! 1308: rtx ! 1309: prev_nonnote_insn (insn) ! 1310: rtx insn; ! 1311: { ! 1312: while (insn) ! 1313: { ! 1314: insn = PREV_INSN (insn); ! 1315: if (insn == 0 || GET_CODE (insn) != NOTE) ! 1316: break; ! 1317: } ! 1318: ! 1319: return insn; ! 1320: } ! 1321: ! 1322: /* Return the next INSN, CALL_INSN or JUMP_INSN after INSN; ! 1323: or 0, if there is none. This routine does not look inside ! 1324: SEQUENCEs. */ ! 1325: ! 1326: rtx ! 1327: next_real_insn (insn) ! 1328: rtx insn; ! 1329: { ! 1330: while (insn) ! 1331: { ! 1332: insn = NEXT_INSN (insn); ! 1333: if (insn == 0 || GET_CODE (insn) == INSN ! 1334: || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN) ! 1335: break; ! 1336: } ! 1337: ! 1338: return insn; ! 1339: } ! 1340: ! 1341: /* Return the last INSN, CALL_INSN or JUMP_INSN before INSN; ! 1342: or 0, if there is none. This routine does not look inside ! 1343: SEQUENCEs. */ ! 1344: ! 1345: rtx ! 1346: prev_real_insn (insn) ! 1347: rtx insn; ! 1348: { ! 1349: while (insn) ! 1350: { ! 1351: insn = PREV_INSN (insn); ! 1352: if (insn == 0 || GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN ! 1353: || GET_CODE (insn) == JUMP_INSN) ! 1354: break; ! 1355: } ! 1356: ! 1357: return insn; ! 1358: } ! 1359: ! 1360: /* Find the next insn after INSN that really does something. This routine ! 1361: does not look inside SEQUENCEs. Until reload has completed, this is the ! 1362: same as next_real_insn. */ ! 1363: ! 1364: rtx ! 1365: next_active_insn (insn) ! 1366: rtx insn; ! 1367: { ! 1368: while (insn) ! 1369: { ! 1370: insn = NEXT_INSN (insn); ! 1371: if (insn == 0 ! 1372: || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN ! 1373: || (GET_CODE (insn) == INSN ! 1374: && (! reload_completed ! 1375: || (GET_CODE (PATTERN (insn)) != USE ! 1376: && GET_CODE (PATTERN (insn)) != CLOBBER)))) ! 1377: break; ! 1378: } ! 1379: ! 1380: return insn; ! 1381: } ! 1382: ! 1383: /* Find the last insn before INSN that really does something. This routine ! 1384: does not look inside SEQUENCEs. Until reload has completed, this is the ! 1385: same as prev_real_insn. */ ! 1386: ! 1387: rtx ! 1388: prev_active_insn (insn) ! 1389: rtx insn; ! 1390: { ! 1391: while (insn) ! 1392: { ! 1393: insn = PREV_INSN (insn); ! 1394: if (insn == 0 ! 1395: || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN ! 1396: || (GET_CODE (insn) == INSN ! 1397: && (! reload_completed ! 1398: || (GET_CODE (PATTERN (insn)) != USE ! 1399: && GET_CODE (PATTERN (insn)) != CLOBBER)))) ! 1400: break; ! 1401: } ! 1402: ! 1403: return insn; ! 1404: } ! 1405: ! 1406: /* Return the next CODE_LABEL after the insn INSN, or 0 if there is none. */ ! 1407: ! 1408: rtx ! 1409: next_label (insn) ! 1410: rtx insn; ! 1411: { ! 1412: while (insn) ! 1413: { ! 1414: insn = NEXT_INSN (insn); ! 1415: if (insn == 0 || GET_CODE (insn) == CODE_LABEL) ! 1416: break; ! 1417: } ! 1418: ! 1419: return insn; ! 1420: } ! 1421: ! 1422: /* Return the last CODE_LABEL before the insn INSN, or 0 if there is none. */ ! 1423: ! 1424: rtx ! 1425: prev_label (insn) ! 1426: rtx insn; ! 1427: { ! 1428: while (insn) ! 1429: { ! 1430: insn = PREV_INSN (insn); ! 1431: if (insn == 0 || GET_CODE (insn) == CODE_LABEL) ! 1432: break; ! 1433: } ! 1434: ! 1435: return insn; ! 1436: } ! 1437: ! 1438: #ifdef HAVE_cc0 ! 1439: /* Return the next insn that uses CC0 after INSN, which is assumed to ! 1440: set it. This is the inverse of prev_cc0_setter (i.e., prev_cc0_setter ! 1441: applied to the result of this function should yield INSN). ! 1442: ! 1443: Normally, this is simply the next insn. However, if a REG_CC_USER note ! 1444: is present, it contains the insn that uses CC0. ! 1445: ! 1446: Return 0 if we can't find the insn. */ ! 1447: ! 1448: rtx ! 1449: next_cc0_user (insn) ! 1450: rtx insn; ! 1451: { ! 1452: rtx note = find_reg_note (insn, REG_CC_USER, 0); ! 1453: ! 1454: if (note) ! 1455: return XEXP (note, 0); ! 1456: ! 1457: insn = next_nonnote_insn (insn); ! 1458: if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) ! 1459: insn = XVECEXP (PATTERN (insn), 0, 0); ! 1460: ! 1461: if (insn && GET_RTX_CLASS (GET_CODE (insn)) == 'i' ! 1462: && reg_mentioned_p (cc0_rtx, PATTERN (insn))) ! 1463: return insn; ! 1464: ! 1465: return 0; ! 1466: } ! 1467: ! 1468: /* Find the insn that set CC0 for INSN. Unless INSN has a REG_CC_SETTER ! 1469: note, it is the previous insn. */ ! 1470: ! 1471: rtx ! 1472: prev_cc0_setter (insn) ! 1473: rtx insn; ! 1474: { ! 1475: rtx note = find_reg_note (insn, REG_CC_SETTER, 0); ! 1476: rtx link; ! 1477: ! 1478: if (note) ! 1479: return XEXP (note, 0); ! 1480: ! 1481: insn = prev_nonnote_insn (insn); ! 1482: if (! sets_cc0_p (PATTERN (insn))) ! 1483: abort (); ! 1484: ! 1485: return insn; ! 1486: } ! 1487: #endif ! 1488: ! 1489: /* Try splitting insns that can be split for better scheduling. ! 1490: PAT is the pattern which might split. ! 1491: TRIAL is the insn providing PAT. ! 1492: BACKWARDS is non-zero if we are scanning insns from last to first. ! 1493: ! 1494: If this routine succeeds in splitting, it returns the first or last ! 1495: replacement insn depending on the value of BACKWARDS. Otherwise, it ! 1496: returns TRIAL. If the insn to be returned can be split, it will be. */ ! 1497: ! 1498: rtx ! 1499: try_split (pat, trial, backwards) ! 1500: rtx pat, trial; ! 1501: int backwards; ! 1502: { ! 1503: rtx before = PREV_INSN (trial); ! 1504: rtx after = NEXT_INSN (trial); ! 1505: rtx seq = split_insns (pat, trial); ! 1506: int has_barrier = 0; ! 1507: rtx tem; ! 1508: ! 1509: /* If we are splitting a JUMP_INSN, it might be followed by a BARRIER. ! 1510: We may need to handle this specially. */ ! 1511: if (after && GET_CODE (after) == BARRIER) ! 1512: { ! 1513: has_barrier = 1; ! 1514: after = NEXT_INSN (after); ! 1515: } ! 1516: ! 1517: if (seq) ! 1518: { ! 1519: /* SEQ can either be a SEQUENCE or the pattern of a single insn. ! 1520: The latter case will normally arise only when being done so that ! 1521: it, in turn, will be split (SFmode on the 29k is an example). */ ! 1522: if (GET_CODE (seq) == SEQUENCE) ! 1523: { ! 1524: /* If we are splitting a JUMP_INSN, look for the JUMP_INSN in ! 1525: SEQ and copy our JUMP_LABEL to it. If JUMP_LABEL is non-zero, ! 1526: increment the usage count so we don't delete the label. */ ! 1527: int i; ! 1528: ! 1529: if (GET_CODE (trial) == JUMP_INSN) ! 1530: for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) ! 1531: if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN) ! 1532: { ! 1533: JUMP_LABEL (XVECEXP (seq, 0, i)) = JUMP_LABEL (trial); ! 1534: ! 1535: if (JUMP_LABEL (trial)) ! 1536: LABEL_NUSES (JUMP_LABEL (trial))++; ! 1537: } ! 1538: ! 1539: tem = emit_insn_after (seq, before); ! 1540: ! 1541: delete_insn (trial); ! 1542: if (has_barrier) ! 1543: emit_barrier_after (tem); ! 1544: } ! 1545: /* Avoid infinite loop if the result matches the original pattern. */ ! 1546: else if (rtx_equal_p (seq, pat)) ! 1547: return trial; ! 1548: else ! 1549: { ! 1550: PATTERN (trial) = seq; ! 1551: INSN_CODE (trial) = -1; ! 1552: } ! 1553: ! 1554: /* Set TEM to the insn we should return. */ ! 1555: tem = backwards ? prev_active_insn (after) : next_active_insn (before); ! 1556: return try_split (PATTERN (tem), tem, backwards); ! 1557: } ! 1558: ! 1559: return trial; ! 1560: } ! 1561: ! 1562: /* Make and return an INSN rtx, initializing all its slots. ! 1563: Store PATTERN in the pattern slots. ! 1564: PAT_FORMALS is an idea that never really went anywhere. */ ! 1565: ! 1566: rtx ! 1567: make_insn_raw (pattern, pat_formals) ! 1568: rtx pattern; ! 1569: rtvec pat_formals; ! 1570: { ! 1571: register rtx insn; ! 1572: ! 1573: insn = rtx_alloc(INSN); ! 1574: INSN_UID(insn) = cur_insn_uid++; ! 1575: ! 1576: PATTERN (insn) = pattern; ! 1577: INSN_CODE (insn) = -1; ! 1578: LOG_LINKS(insn) = NULL; ! 1579: REG_NOTES(insn) = NULL; ! 1580: ! 1581: return insn; ! 1582: } ! 1583: ! 1584: /* Like `make_insn' but make a JUMP_INSN instead of an insn. */ ! 1585: ! 1586: static rtx ! 1587: make_jump_insn_raw (pattern, pat_formals) ! 1588: rtx pattern; ! 1589: rtvec pat_formals; ! 1590: { ! 1591: register rtx insn; ! 1592: ! 1593: insn = rtx_alloc(JUMP_INSN); ! 1594: INSN_UID(insn) = cur_insn_uid++; ! 1595: ! 1596: PATTERN (insn) = pattern; ! 1597: INSN_CODE (insn) = -1; ! 1598: LOG_LINKS(insn) = NULL; ! 1599: REG_NOTES(insn) = NULL; ! 1600: JUMP_LABEL(insn) = NULL; ! 1601: ! 1602: return insn; ! 1603: } ! 1604: ! 1605: /* Add INSN to the end of the doubly-linked list. ! 1606: INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE. */ ! 1607: ! 1608: void ! 1609: add_insn (insn) ! 1610: register rtx insn; ! 1611: { ! 1612: PREV_INSN (insn) = last_insn; ! 1613: NEXT_INSN (insn) = 0; ! 1614: ! 1615: if (NULL != last_insn) ! 1616: NEXT_INSN (last_insn) = insn; ! 1617: ! 1618: if (NULL == first_insn) ! 1619: first_insn = insn; ! 1620: ! 1621: last_insn = insn; ! 1622: } ! 1623: ! 1624: /* Add INSN into the doubly-linked list after insn AFTER. This should be the ! 1625: only function called to insert an insn once delay slots have been filled ! 1626: since only it knows how to update a SEQUENCE. */ ! 1627: ! 1628: void ! 1629: add_insn_after (insn, after) ! 1630: rtx insn, after; ! 1631: { ! 1632: rtx next = NEXT_INSN (after); ! 1633: ! 1634: NEXT_INSN (insn) = next; ! 1635: PREV_INSN (insn) = after; ! 1636: ! 1637: if (next) ! 1638: { ! 1639: PREV_INSN (next) = insn; ! 1640: if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE) ! 1641: PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn; ! 1642: } ! 1643: else if (last_insn == after) ! 1644: last_insn = insn; ! 1645: else ! 1646: { ! 1647: struct sequence_stack *stack = sequence_stack; ! 1648: /* Scan all pending sequences too. */ ! 1649: for (; stack; stack = stack->next) ! 1650: if (after == stack->last) ! 1651: stack->last = insn; ! 1652: } ! 1653: ! 1654: NEXT_INSN (after) = insn; ! 1655: if (GET_CODE (after) == INSN && GET_CODE (PATTERN (after)) == SEQUENCE) ! 1656: { ! 1657: rtx sequence = PATTERN (after); ! 1658: NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn; ! 1659: } ! 1660: } ! 1661: ! 1662: /* Delete all insns made since FROM. ! 1663: FROM becomes the new last instruction. */ ! 1664: ! 1665: void ! 1666: delete_insns_since (from) ! 1667: rtx from; ! 1668: { ! 1669: if (from == 0) ! 1670: first_insn = 0; ! 1671: else ! 1672: NEXT_INSN (from) = 0; ! 1673: last_insn = from; ! 1674: } ! 1675: ! 1676: /* Move a consecutive bunch of insns to a different place in the chain. ! 1677: The insns to be moved are those between FROM and TO. ! 1678: They are moved to a new position after the insn AFTER. ! 1679: AFTER must not be FROM or TO or any insn in between. ! 1680: ! 1681: This function does not know about SEQUENCEs and hence should not be ! 1682: called after delay-slot filling has been done. */ ! 1683: ! 1684: void ! 1685: reorder_insns (from, to, after) ! 1686: rtx from, to, after; ! 1687: { ! 1688: /* Splice this bunch out of where it is now. */ ! 1689: if (PREV_INSN (from)) ! 1690: NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to); ! 1691: if (NEXT_INSN (to)) ! 1692: PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from); ! 1693: if (last_insn == to) ! 1694: last_insn = PREV_INSN (from); ! 1695: if (first_insn == from) ! 1696: first_insn = NEXT_INSN (to); ! 1697: ! 1698: /* Make the new neighbors point to it and it to them. */ ! 1699: if (NEXT_INSN (after)) ! 1700: PREV_INSN (NEXT_INSN (after)) = to; ! 1701: ! 1702: NEXT_INSN (to) = NEXT_INSN (after); ! 1703: PREV_INSN (from) = after; ! 1704: NEXT_INSN (after) = from; ! 1705: if (after == last_insn) ! 1706: last_insn = to; ! 1707: } ! 1708: ! 1709: /* Return the line note insn preceding INSN. */ ! 1710: ! 1711: static rtx ! 1712: find_line_note (insn) ! 1713: rtx insn; ! 1714: { ! 1715: if (no_line_numbers) ! 1716: return 0; ! 1717: ! 1718: for (; insn; insn = PREV_INSN (insn)) ! 1719: if (GET_CODE (insn) == NOTE ! 1720: && NOTE_LINE_NUMBER (insn) >= 0) ! 1721: break; ! 1722: ! 1723: return insn; ! 1724: } ! 1725: ! 1726: /* Like reorder_insns, but inserts line notes to preserve the line numbers ! 1727: of the moved insns when debugging. This may insert a note between AFTER ! 1728: and FROM, and another one after TO. */ ! 1729: ! 1730: void ! 1731: reorder_insns_with_line_notes (from, to, after) ! 1732: rtx from, to, after; ! 1733: { ! 1734: rtx from_line = find_line_note (from); ! 1735: rtx after_line = find_line_note (after); ! 1736: ! 1737: reorder_insns (from, to, after); ! 1738: ! 1739: if (from_line == after_line) ! 1740: return; ! 1741: ! 1742: if (from_line) ! 1743: emit_line_note_after (NOTE_SOURCE_FILE (from_line), ! 1744: NOTE_LINE_NUMBER (from_line), ! 1745: after); ! 1746: if (after_line) ! 1747: emit_line_note_after (NOTE_SOURCE_FILE (after_line), ! 1748: NOTE_LINE_NUMBER (after_line), ! 1749: to); ! 1750: } ! 1751: ! 1752: /* Emit an insn of given code and pattern ! 1753: at a specified place within the doubly-linked list. */ ! 1754: ! 1755: /* Make an instruction with body PATTERN ! 1756: and output it before the instruction BEFORE. */ ! 1757: ! 1758: rtx ! 1759: emit_insn_before (pattern, before) ! 1760: register rtx pattern, before; ! 1761: { ! 1762: register rtx insn = before; ! 1763: ! 1764: if (GET_CODE (pattern) == SEQUENCE) ! 1765: { ! 1766: register int i; ! 1767: ! 1768: for (i = 0; i < XVECLEN (pattern, 0); i++) ! 1769: { ! 1770: insn = XVECEXP (pattern, 0, i); ! 1771: add_insn_after (insn, PREV_INSN (before)); ! 1772: } ! 1773: if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE) ! 1774: sequence_result[XVECLEN (pattern, 0)] = pattern; ! 1775: } ! 1776: else ! 1777: { ! 1778: insn = make_insn_raw (pattern, 0); ! 1779: add_insn_after (insn, PREV_INSN (before)); ! 1780: } ! 1781: ! 1782: return insn; ! 1783: } ! 1784: ! 1785: /* Make an instruction with body PATTERN and code JUMP_INSN ! 1786: and output it before the instruction BEFORE. */ ! 1787: ! 1788: rtx ! 1789: emit_jump_insn_before (pattern, before) ! 1790: register rtx pattern, before; ! 1791: { ! 1792: register rtx insn; ! 1793: ! 1794: if (GET_CODE (pattern) == SEQUENCE) ! 1795: insn = emit_insn_before (pattern, before); ! 1796: else ! 1797: { ! 1798: insn = make_jump_insn_raw (pattern, 0); ! 1799: add_insn_after (insn, PREV_INSN (before)); ! 1800: } ! 1801: ! 1802: return insn; ! 1803: } ! 1804: ! 1805: /* Make an instruction with body PATTERN and code CALL_INSN ! 1806: and output it before the instruction BEFORE. */ ! 1807: ! 1808: rtx ! 1809: emit_call_insn_before (pattern, before) ! 1810: register rtx pattern, before; ! 1811: { ! 1812: rtx insn = emit_insn_before (pattern, before); ! 1813: PUT_CODE (insn, CALL_INSN); ! 1814: return insn; ! 1815: } ! 1816: ! 1817: /* Make an insn of code BARRIER ! 1818: and output it before the insn AFTER. */ ! 1819: ! 1820: rtx ! 1821: emit_barrier_before (before) ! 1822: register rtx before; ! 1823: { ! 1824: register rtx insn = rtx_alloc (BARRIER); ! 1825: ! 1826: INSN_UID (insn) = cur_insn_uid++; ! 1827: ! 1828: add_insn_after (insn, PREV_INSN (before)); ! 1829: return insn; ! 1830: } ! 1831: ! 1832: /* Emit a note of subtype SUBTYPE before the insn BEFORE. */ ! 1833: ! 1834: rtx ! 1835: emit_note_before (subtype, before) ! 1836: int subtype; ! 1837: rtx before; ! 1838: { ! 1839: register rtx note = rtx_alloc (NOTE); ! 1840: INSN_UID (note) = cur_insn_uid++; ! 1841: NOTE_SOURCE_FILE (note) = 0; ! 1842: NOTE_LINE_NUMBER (note) = subtype; ! 1843: ! 1844: add_insn_after (note, PREV_INSN (before)); ! 1845: return note; ! 1846: } ! 1847: ! 1848: /* Make an insn of code INSN with body PATTERN ! 1849: and output it after the insn AFTER. */ ! 1850: ! 1851: rtx ! 1852: emit_insn_after (pattern, after) ! 1853: register rtx pattern, after; ! 1854: { ! 1855: register rtx insn = after; ! 1856: ! 1857: if (GET_CODE (pattern) == SEQUENCE) ! 1858: { ! 1859: register int i; ! 1860: ! 1861: for (i = 0; i < XVECLEN (pattern, 0); i++) ! 1862: { ! 1863: insn = XVECEXP (pattern, 0, i); ! 1864: add_insn_after (insn, after); ! 1865: after = insn; ! 1866: } ! 1867: if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE) ! 1868: sequence_result[XVECLEN (pattern, 0)] = pattern; ! 1869: } ! 1870: else ! 1871: { ! 1872: insn = make_insn_raw (pattern, 0); ! 1873: add_insn_after (insn, after); ! 1874: } ! 1875: ! 1876: return insn; ! 1877: } ! 1878: ! 1879: /* Make an insn of code JUMP_INSN with body PATTERN ! 1880: and output it after the insn AFTER. */ ! 1881: ! 1882: rtx ! 1883: emit_jump_insn_after (pattern, after) ! 1884: register rtx pattern, after; ! 1885: { ! 1886: register rtx insn; ! 1887: ! 1888: if (GET_CODE (pattern) == SEQUENCE) ! 1889: insn = emit_insn_after (pattern, after); ! 1890: else ! 1891: { ! 1892: insn = make_jump_insn_raw (pattern, 0); ! 1893: add_insn_after (insn, after); ! 1894: } ! 1895: ! 1896: return insn; ! 1897: } ! 1898: ! 1899: /* Make an insn of code BARRIER ! 1900: and output it after the insn AFTER. */ ! 1901: ! 1902: rtx ! 1903: emit_barrier_after (after) ! 1904: register rtx after; ! 1905: { ! 1906: register rtx insn = rtx_alloc (BARRIER); ! 1907: ! 1908: INSN_UID (insn) = cur_insn_uid++; ! 1909: ! 1910: add_insn_after (insn, after); ! 1911: return insn; ! 1912: } ! 1913: ! 1914: /* Emit the label LABEL after the insn AFTER. */ ! 1915: ! 1916: rtx ! 1917: emit_label_after (label, after) ! 1918: rtx label, after; ! 1919: { ! 1920: /* This can be called twice for the same label ! 1921: as a result of the confusion that follows a syntax error! ! 1922: So make it harmless. */ ! 1923: if (INSN_UID (label) == 0) ! 1924: { ! 1925: INSN_UID (label) = cur_insn_uid++; ! 1926: add_insn_after (label, after); ! 1927: } ! 1928: ! 1929: return label; ! 1930: } ! 1931: ! 1932: /* Emit a note of subtype SUBTYPE after the insn AFTER. */ ! 1933: ! 1934: rtx ! 1935: emit_note_after (subtype, after) ! 1936: int subtype; ! 1937: rtx after; ! 1938: { ! 1939: register rtx note = rtx_alloc (NOTE); ! 1940: INSN_UID (note) = cur_insn_uid++; ! 1941: NOTE_SOURCE_FILE (note) = 0; ! 1942: NOTE_LINE_NUMBER (note) = subtype; ! 1943: add_insn_after (note, after); ! 1944: return note; ! 1945: } ! 1946: ! 1947: /* Emit a line note for FILE and LINE after the insn AFTER. */ ! 1948: ! 1949: rtx ! 1950: emit_line_note_after (file, line, after) ! 1951: char *file; ! 1952: int line; ! 1953: rtx after; ! 1954: { ! 1955: register rtx note; ! 1956: ! 1957: if (no_line_numbers && line > 0) ! 1958: { ! 1959: cur_insn_uid++; ! 1960: return 0; ! 1961: } ! 1962: ! 1963: note = rtx_alloc (NOTE); ! 1964: INSN_UID (note) = cur_insn_uid++; ! 1965: NOTE_SOURCE_FILE (note) = file; ! 1966: NOTE_LINE_NUMBER (note) = line; ! 1967: add_insn_after (note, after); ! 1968: return note; ! 1969: } ! 1970: ! 1971: /* Make an insn of code INSN with pattern PATTERN ! 1972: and add it to the end of the doubly-linked list. ! 1973: If PATTERN is a SEQUENCE, take the elements of it ! 1974: and emit an insn for each element. ! 1975: ! 1976: Returns the last insn emitted. */ ! 1977: ! 1978: rtx ! 1979: emit_insn (pattern) ! 1980: rtx pattern; ! 1981: { ! 1982: rtx insn = last_insn; ! 1983: ! 1984: if (GET_CODE (pattern) == SEQUENCE) ! 1985: { ! 1986: register int i; ! 1987: ! 1988: for (i = 0; i < XVECLEN (pattern, 0); i++) ! 1989: { ! 1990: insn = XVECEXP (pattern, 0, i); ! 1991: add_insn (insn); ! 1992: } ! 1993: if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE) ! 1994: sequence_result[XVECLEN (pattern, 0)] = pattern; ! 1995: } ! 1996: else ! 1997: { ! 1998: insn = make_insn_raw (pattern, NULL); ! 1999: add_insn (insn); ! 2000: } ! 2001: ! 2002: return insn; ! 2003: } ! 2004: ! 2005: /* Emit the insns in a chain starting with INSN. ! 2006: Return the last insn emitted. */ ! 2007: ! 2008: rtx ! 2009: emit_insns (insn) ! 2010: rtx insn; ! 2011: { ! 2012: rtx last = 0; ! 2013: ! 2014: while (insn) ! 2015: { ! 2016: rtx next = NEXT_INSN (insn); ! 2017: add_insn (insn); ! 2018: last = insn; ! 2019: insn = next; ! 2020: } ! 2021: ! 2022: return last; ! 2023: } ! 2024: ! 2025: /* Emit the insns in a chain starting with INSN and place them in front of ! 2026: the insn BEFORE. Return the last insn emitted. */ ! 2027: ! 2028: rtx ! 2029: emit_insns_before (insn, before) ! 2030: rtx insn; ! 2031: rtx before; ! 2032: { ! 2033: rtx last = 0; ! 2034: ! 2035: while (insn) ! 2036: { ! 2037: rtx next = NEXT_INSN (insn); ! 2038: add_insn_after (insn, PREV_INSN (before)); ! 2039: last = insn; ! 2040: insn = next; ! 2041: } ! 2042: ! 2043: return last; ! 2044: } ! 2045: ! 2046: /* Make an insn of code JUMP_INSN with pattern PATTERN ! 2047: and add it to the end of the doubly-linked list. */ ! 2048: ! 2049: rtx ! 2050: emit_jump_insn (pattern) ! 2051: rtx pattern; ! 2052: { ! 2053: if (GET_CODE (pattern) == SEQUENCE) ! 2054: return emit_insn (pattern); ! 2055: else ! 2056: { ! 2057: register rtx insn = make_jump_insn_raw (pattern, NULL); ! 2058: add_insn (insn); ! 2059: return insn; ! 2060: } ! 2061: } ! 2062: ! 2063: /* Make an insn of code CALL_INSN with pattern PATTERN ! 2064: and add it to the end of the doubly-linked list. */ ! 2065: ! 2066: rtx ! 2067: emit_call_insn (pattern) ! 2068: rtx pattern; ! 2069: { ! 2070: if (GET_CODE (pattern) == SEQUENCE) ! 2071: return emit_insn (pattern); ! 2072: else ! 2073: { ! 2074: register rtx insn = make_insn_raw (pattern, NULL); ! 2075: add_insn (insn); ! 2076: PUT_CODE (insn, CALL_INSN); ! 2077: return insn; ! 2078: } ! 2079: } ! 2080: ! 2081: /* Add the label LABEL to the end of the doubly-linked list. */ ! 2082: ! 2083: rtx ! 2084: emit_label (label) ! 2085: rtx label; ! 2086: { ! 2087: /* This can be called twice for the same label ! 2088: as a result of the confusion that follows a syntax error! ! 2089: So make it harmless. */ ! 2090: if (INSN_UID (label) == 0) ! 2091: { ! 2092: INSN_UID (label) = cur_insn_uid++; ! 2093: add_insn (label); ! 2094: } ! 2095: return label; ! 2096: } ! 2097: ! 2098: /* Make an insn of code BARRIER ! 2099: and add it to the end of the doubly-linked list. */ ! 2100: ! 2101: rtx ! 2102: emit_barrier () ! 2103: { ! 2104: register rtx barrier = rtx_alloc (BARRIER); ! 2105: INSN_UID (barrier) = cur_insn_uid++; ! 2106: add_insn (barrier); ! 2107: return barrier; ! 2108: } ! 2109: ! 2110: /* Make an insn of code NOTE ! 2111: with data-fields specified by FILE and LINE ! 2112: and add it to the end of the doubly-linked list, ! 2113: but only if line-numbers are desired for debugging info. */ ! 2114: ! 2115: rtx ! 2116: emit_line_note (file, line) ! 2117: char *file; ! 2118: int line; ! 2119: { ! 2120: emit_filename = file; ! 2121: emit_lineno = line; ! 2122: ! 2123: #if 0 ! 2124: if (no_line_numbers) ! 2125: return 0; ! 2126: #endif ! 2127: ! 2128: return emit_note (file, line); ! 2129: } ! 2130: ! 2131: /* Make an insn of code NOTE ! 2132: with data-fields specified by FILE and LINE ! 2133: and add it to the end of the doubly-linked list. ! 2134: If it is a line-number NOTE, omit it if it matches the previous one. */ ! 2135: ! 2136: rtx ! 2137: emit_note (file, line) ! 2138: char *file; ! 2139: int line; ! 2140: { ! 2141: register rtx note; ! 2142: ! 2143: if (line > 0) ! 2144: { ! 2145: if (file && last_filename && !strcmp (file, last_filename) ! 2146: && line == last_linenum) ! 2147: return 0; ! 2148: last_filename = file; ! 2149: last_linenum = line; ! 2150: } ! 2151: ! 2152: if (no_line_numbers && line > 0) ! 2153: { ! 2154: cur_insn_uid++; ! 2155: return 0; ! 2156: } ! 2157: ! 2158: note = rtx_alloc (NOTE); ! 2159: INSN_UID (note) = cur_insn_uid++; ! 2160: NOTE_SOURCE_FILE (note) = file; ! 2161: NOTE_LINE_NUMBER (note) = line; ! 2162: add_insn (note); ! 2163: return note; ! 2164: } ! 2165: ! 2166: /* Emit a NOTE, and don't omit it even if LINE it the previous note. */ ! 2167: ! 2168: rtx ! 2169: emit_line_note_force (file, line) ! 2170: char *file; ! 2171: int line; ! 2172: { ! 2173: last_linenum = -1; ! 2174: return emit_line_note (file, line); ! 2175: } ! 2176: ! 2177: /* Cause next statement to emit a line note even if the line number ! 2178: has not changed. This is used at the beginning of a function. */ ! 2179: ! 2180: void ! 2181: force_next_line_note () ! 2182: { ! 2183: last_linenum = -1; ! 2184: } ! 2185: ! 2186: /* Return an indication of which type of insn should have X as a body. ! 2187: The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */ ! 2188: ! 2189: enum rtx_code ! 2190: classify_insn (x) ! 2191: rtx x; ! 2192: { ! 2193: if (GET_CODE (x) == CODE_LABEL) ! 2194: return CODE_LABEL; ! 2195: if (GET_CODE (x) == CALL) ! 2196: return CALL_INSN; ! 2197: if (GET_CODE (x) == RETURN) ! 2198: return JUMP_INSN; ! 2199: if (GET_CODE (x) == SET) ! 2200: { ! 2201: if (SET_DEST (x) == pc_rtx) ! 2202: return JUMP_INSN; ! 2203: else if (GET_CODE (SET_SRC (x)) == CALL) ! 2204: return CALL_INSN; ! 2205: else ! 2206: return INSN; ! 2207: } ! 2208: if (GET_CODE (x) == PARALLEL) ! 2209: { ! 2210: register int j; ! 2211: for (j = XVECLEN (x, 0) - 1; j >= 0; j--) ! 2212: if (GET_CODE (XVECEXP (x, 0, j)) == CALL) ! 2213: return CALL_INSN; ! 2214: else if (GET_CODE (XVECEXP (x, 0, j)) == SET ! 2215: && SET_DEST (XVECEXP (x, 0, j)) == pc_rtx) ! 2216: return JUMP_INSN; ! 2217: else if (GET_CODE (XVECEXP (x, 0, j)) == SET ! 2218: && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) ! 2219: return CALL_INSN; ! 2220: } ! 2221: return INSN; ! 2222: } ! 2223: ! 2224: /* Emit the rtl pattern X as an appropriate kind of insn. ! 2225: If X is a label, it is simply added into the insn chain. */ ! 2226: ! 2227: rtx ! 2228: emit (x) ! 2229: rtx x; ! 2230: { ! 2231: enum rtx_code code = classify_insn (x); ! 2232: ! 2233: if (code == CODE_LABEL) ! 2234: return emit_label (x); ! 2235: else if (code == INSN) ! 2236: return emit_insn (x); ! 2237: else if (code == JUMP_INSN) ! 2238: { ! 2239: register rtx insn = emit_jump_insn (x); ! 2240: if (simplejump_p (insn) || GET_CODE (x) == RETURN) ! 2241: return emit_barrier (); ! 2242: return insn; ! 2243: } ! 2244: else if (code == CALL_INSN) ! 2245: return emit_call_insn (x); ! 2246: else ! 2247: abort (); ! 2248: } ! 2249: ! 2250: /* Begin emitting insns to a sequence which can be packaged in an RTL_EXPR. */ ! 2251: ! 2252: void ! 2253: start_sequence () ! 2254: { ! 2255: struct sequence_stack *tem; ! 2256: ! 2257: if (sequence_element_free_list) ! 2258: { ! 2259: /* Reuse a previously-saved struct sequence_stack. */ ! 2260: tem = sequence_element_free_list; ! 2261: sequence_element_free_list = tem->next; ! 2262: } ! 2263: else ! 2264: tem = (struct sequence_stack *) permalloc (sizeof (struct sequence_stack)); ! 2265: ! 2266: tem->next = sequence_stack; ! 2267: tem->first = first_insn; ! 2268: tem->last = last_insn; ! 2269: ! 2270: sequence_stack = tem; ! 2271: ! 2272: first_insn = 0; ! 2273: last_insn = 0; ! 2274: } ! 2275: ! 2276: /* Set up the insn chain starting with FIRST ! 2277: as the current sequence, saving the previously current one. */ ! 2278: ! 2279: void ! 2280: push_to_sequence (first) ! 2281: rtx first; ! 2282: { ! 2283: rtx last; ! 2284: ! 2285: start_sequence (); ! 2286: ! 2287: for (last = first; last && NEXT_INSN (last); last = NEXT_INSN (last)); ! 2288: ! 2289: first_insn = first; ! 2290: last_insn = last; ! 2291: } ! 2292: ! 2293: /* After emitting to a sequence, restore previous saved state. ! 2294: ! 2295: To get the contents of the sequence just made, ! 2296: you must call `gen_sequence' *before* calling here. */ ! 2297: ! 2298: void ! 2299: end_sequence () ! 2300: { ! 2301: struct sequence_stack *tem = sequence_stack; ! 2302: ! 2303: first_insn = tem->first; ! 2304: last_insn = tem->last; ! 2305: sequence_stack = tem->next; ! 2306: ! 2307: tem->next = sequence_element_free_list; ! 2308: sequence_element_free_list = tem; ! 2309: } ! 2310: ! 2311: /* Return 1 if currently emitting into a sequence. */ ! 2312: ! 2313: int ! 2314: in_sequence_p () ! 2315: { ! 2316: return sequence_stack != 0; ! 2317: } ! 2318: ! 2319: /* Generate a SEQUENCE rtx containing the insns already emitted ! 2320: to the current sequence. ! 2321: ! 2322: This is how the gen_... function from a DEFINE_EXPAND ! 2323: constructs the SEQUENCE that it returns. */ ! 2324: ! 2325: rtx ! 2326: gen_sequence () ! 2327: { ! 2328: rtx result; ! 2329: rtx tem; ! 2330: rtvec newvec; ! 2331: int i; ! 2332: int len; ! 2333: ! 2334: /* Count the insns in the chain. */ ! 2335: len = 0; ! 2336: for (tem = first_insn; tem; tem = NEXT_INSN (tem)) ! 2337: len++; ! 2338: ! 2339: /* If only one insn, return its pattern rather than a SEQUENCE. ! 2340: (Now that we cache SEQUENCE expressions, it isn't worth special-casing ! 2341: the case of an empty list.) */ ! 2342: if (len == 1 ! 2343: && (GET_CODE (first_insn) == INSN ! 2344: || GET_CODE (first_insn) == JUMP_INSN ! 2345: || GET_CODE (first_insn) == CALL_INSN)) ! 2346: return PATTERN (first_insn); ! 2347: ! 2348: /* Put them in a vector. See if we already have a SEQUENCE of the ! 2349: appropriate length around. */ ! 2350: if (len < SEQUENCE_RESULT_SIZE && (result = sequence_result[len]) != 0) ! 2351: sequence_result[len] = 0; ! 2352: else ! 2353: { ! 2354: /* Ensure that this rtl goes in saveable_obstack, since we may be ! 2355: caching it. */ ! 2356: int in_current_obstack = rtl_in_saveable_obstack (); ! 2357: result = gen_rtx (SEQUENCE, VOIDmode, rtvec_alloc (len)); ! 2358: if (in_current_obstack) ! 2359: rtl_in_current_obstack (); ! 2360: } ! 2361: ! 2362: for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++) ! 2363: XVECEXP (result, 0, i) = tem; ! 2364: ! 2365: return result; ! 2366: } ! 2367: ! 2368: /* Set up regno_reg_rtx, reg_rtx_no and regno_pointer_flag ! 2369: according to the chain of insns starting with FIRST. ! 2370: ! 2371: Also set cur_insn_uid to exceed the largest uid in that chain. ! 2372: ! 2373: This is used when an inline function's rtl is saved ! 2374: and passed to rest_of_compilation later. */ ! 2375: ! 2376: static void restore_reg_data_1 (); ! 2377: ! 2378: void ! 2379: restore_reg_data (first) ! 2380: rtx first; ! 2381: { ! 2382: register rtx insn; ! 2383: int i; ! 2384: register int max_uid = 0; ! 2385: ! 2386: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 2387: { ! 2388: if (INSN_UID (insn) >= max_uid) ! 2389: max_uid = INSN_UID (insn); ! 2390: ! 2391: switch (GET_CODE (insn)) ! 2392: { ! 2393: case NOTE: ! 2394: case CODE_LABEL: ! 2395: case BARRIER: ! 2396: break; ! 2397: ! 2398: case JUMP_INSN: ! 2399: case CALL_INSN: ! 2400: case INSN: ! 2401: restore_reg_data_1 (PATTERN (insn)); ! 2402: break; ! 2403: } ! 2404: } ! 2405: ! 2406: /* Don't duplicate the uids already in use. */ ! 2407: cur_insn_uid = max_uid + 1; ! 2408: ! 2409: /* If any regs are missing, make them up. ! 2410: ! 2411: ??? word_mode is not necessarily the right mode. Most likely these REGs ! 2412: are never used. At some point this should be checked. */ ! 2413: ! 2414: for (i = FIRST_PSEUDO_REGISTER; i < reg_rtx_no; i++) ! 2415: if (regno_reg_rtx[i] == 0) ! 2416: regno_reg_rtx[i] = gen_rtx (REG, word_mode, i); ! 2417: } ! 2418: ! 2419: static void ! 2420: restore_reg_data_1 (orig) ! 2421: rtx orig; ! 2422: { ! 2423: register rtx x = orig; ! 2424: register int i; ! 2425: register enum rtx_code code; ! 2426: register char *format_ptr; ! 2427: ! 2428: code = GET_CODE (x); ! 2429: ! 2430: switch (code) ! 2431: { ! 2432: case QUEUED: ! 2433: case CONST_INT: ! 2434: case CONST_DOUBLE: ! 2435: case SYMBOL_REF: ! 2436: case CODE_LABEL: ! 2437: case PC: ! 2438: case CC0: ! 2439: case LABEL_REF: ! 2440: return; ! 2441: ! 2442: case REG: ! 2443: if (REGNO (x) >= FIRST_PSEUDO_REGISTER) ! 2444: { ! 2445: /* Make sure regno_pointer_flag and regno_reg_rtx are large ! 2446: enough to have an element for this pseudo reg number. */ ! 2447: if (REGNO (x) >= reg_rtx_no) ! 2448: { ! 2449: reg_rtx_no = REGNO (x); ! 2450: ! 2451: if (reg_rtx_no >= regno_pointer_flag_length) ! 2452: { ! 2453: int newlen = MAX (regno_pointer_flag_length * 2, ! 2454: reg_rtx_no + 30); ! 2455: rtx *new1; ! 2456: char *new = (char *) oballoc (newlen); ! 2457: bzero (new, newlen); ! 2458: bcopy (regno_pointer_flag, new, regno_pointer_flag_length); ! 2459: ! 2460: new1 = (rtx *) oballoc (newlen * sizeof (rtx)); ! 2461: bzero (new1, newlen * sizeof (rtx)); ! 2462: bcopy (regno_reg_rtx, new1, regno_pointer_flag_length * sizeof (rtx)); ! 2463: ! 2464: regno_pointer_flag = new; ! 2465: regno_reg_rtx = new1; ! 2466: regno_pointer_flag_length = newlen; ! 2467: } ! 2468: reg_rtx_no ++; ! 2469: } ! 2470: regno_reg_rtx[REGNO (x)] = x; ! 2471: } ! 2472: return; ! 2473: ! 2474: case MEM: ! 2475: if (GET_CODE (XEXP (x, 0)) == REG) ! 2476: mark_reg_pointer (XEXP (x, 0)); ! 2477: restore_reg_data_1 (XEXP (x, 0)); ! 2478: return; ! 2479: } ! 2480: ! 2481: /* Now scan the subexpressions recursively. */ ! 2482: ! 2483: format_ptr = GET_RTX_FORMAT (code); ! 2484: ! 2485: for (i = 0; i < GET_RTX_LENGTH (code); i++) ! 2486: { ! 2487: switch (*format_ptr++) ! 2488: { ! 2489: case 'e': ! 2490: restore_reg_data_1 (XEXP (x, i)); ! 2491: break; ! 2492: ! 2493: case 'E': ! 2494: if (XVEC (x, i) != NULL) ! 2495: { ! 2496: register int j; ! 2497: ! 2498: for (j = 0; j < XVECLEN (x, i); j++) ! 2499: restore_reg_data_1 (XVECEXP (x, i, j)); ! 2500: } ! 2501: break; ! 2502: } ! 2503: } ! 2504: } ! 2505: ! 2506: /* Initialize data structures and variables in this file ! 2507: before generating rtl for each function. */ ! 2508: ! 2509: void ! 2510: init_emit () ! 2511: { ! 2512: int i; ! 2513: ! 2514: first_insn = NULL; ! 2515: last_insn = NULL; ! 2516: cur_insn_uid = 1; ! 2517: reg_rtx_no = LAST_VIRTUAL_REGISTER + 1; ! 2518: last_linenum = 0; ! 2519: last_filename = 0; ! 2520: first_label_num = label_num; ! 2521: last_label_num = 0; ! 2522: ! 2523: /* Clear the start_sequence/gen_sequence cache. */ ! 2524: sequence_element_free_list = 0; ! 2525: for (i = 0; i < SEQUENCE_RESULT_SIZE; i++) ! 2526: sequence_result[i] = 0; ! 2527: ! 2528: /* Init the tables that describe all the pseudo regs. */ ! 2529: ! 2530: regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101; ! 2531: ! 2532: regno_pointer_flag ! 2533: = (char *) oballoc (regno_pointer_flag_length); ! 2534: bzero (regno_pointer_flag, regno_pointer_flag_length); ! 2535: ! 2536: regno_reg_rtx ! 2537: = (rtx *) oballoc (regno_pointer_flag_length * sizeof (rtx)); ! 2538: bzero (regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx)); ! 2539: ! 2540: /* Put copies of all the virtual register rtx into regno_reg_rtx. */ ! 2541: regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx; ! 2542: regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx; ! 2543: regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx; ! 2544: regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx; ! 2545: } ! 2546: ! 2547: /* Create some permanent unique rtl objects shared between all functions. ! 2548: LINE_NUMBERS is nonzero if line numbers are to be generated. */ ! 2549: ! 2550: void ! 2551: init_emit_once (line_numbers) ! 2552: int line_numbers; ! 2553: { ! 2554: int i; ! 2555: enum machine_mode mode; ! 2556: ! 2557: no_line_numbers = ! line_numbers; ! 2558: ! 2559: sequence_stack = NULL; ! 2560: ! 2561: /* Create the unique rtx's for certain rtx codes and operand values. */ ! 2562: ! 2563: pc_rtx = gen_rtx (PC, VOIDmode); ! 2564: cc0_rtx = gen_rtx (CC0, VOIDmode); ! 2565: ! 2566: /* Don't use gen_rtx here since gen_rtx in this case ! 2567: tries to use these variables. */ ! 2568: for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++) ! 2569: { ! 2570: const_int_rtx[i + MAX_SAVED_CONST_INT] = rtx_alloc (CONST_INT); ! 2571: PUT_MODE (const_int_rtx[i + MAX_SAVED_CONST_INT], VOIDmode); ! 2572: INTVAL (const_int_rtx[i + MAX_SAVED_CONST_INT]) = i; ! 2573: } ! 2574: ! 2575: /* These four calls obtain some of the rtx expressions made above. */ ! 2576: const0_rtx = gen_rtx (CONST_INT, VOIDmode, 0); ! 2577: const1_rtx = gen_rtx (CONST_INT, VOIDmode, 1); ! 2578: const2_rtx = gen_rtx (CONST_INT, VOIDmode, 2); ! 2579: constm1_rtx = gen_rtx (CONST_INT, VOIDmode, -1); ! 2580: ! 2581: /* This will usually be one of the above constants, but may be a new rtx. */ ! 2582: const_true_rtx = gen_rtx (CONST_INT, VOIDmode, STORE_FLAG_VALUE); ! 2583: ! 2584: dconst0 = REAL_VALUE_ATOF ("0"); ! 2585: dconst1 = REAL_VALUE_ATOF ("1"); ! 2586: dconst2 = REAL_VALUE_ATOF ("2"); ! 2587: dconstm1 = REAL_VALUE_ATOF ("-1"); ! 2588: ! 2589: for (i = 0; i <= 2; i++) ! 2590: { ! 2591: for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; ! 2592: mode = GET_MODE_WIDER_MODE (mode)) ! 2593: { ! 2594: rtx tem = rtx_alloc (CONST_DOUBLE); ! 2595: union real_extract u; ! 2596: ! 2597: bzero (&u, sizeof u); /* Zero any holes in a structure. */ ! 2598: u.d = i == 0 ? dconst0 : i == 1 ? dconst1 : dconst2; ! 2599: ! 2600: bcopy (&u, &CONST_DOUBLE_LOW (tem), sizeof u); ! 2601: CONST_DOUBLE_MEM (tem) = cc0_rtx; ! 2602: PUT_MODE (tem, mode); ! 2603: ! 2604: const_tiny_rtx[i][(int) mode] = tem; ! 2605: } ! 2606: ! 2607: const_tiny_rtx[i][VOIDmode] = gen_rtx (CONST_INT, VOIDmode, i); ! 2608: ! 2609: for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; ! 2610: mode = GET_MODE_WIDER_MODE (mode)) ! 2611: const_tiny_rtx[i][(int) mode] = gen_rtx (CONST_INT, VOIDmode, i); ! 2612: } ! 2613: ! 2614: stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM); ! 2615: frame_pointer_rtx = gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM); ! 2616: ! 2617: if (FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM) ! 2618: arg_pointer_rtx = frame_pointer_rtx; ! 2619: else if (STACK_POINTER_REGNUM == ARG_POINTER_REGNUM) ! 2620: arg_pointer_rtx = stack_pointer_rtx; ! 2621: else ! 2622: arg_pointer_rtx = gen_rtx (REG, Pmode, ARG_POINTER_REGNUM); ! 2623: ! 2624: /* Create the virtual registers. Do so here since the following objects ! 2625: might reference them. */ ! 2626: ! 2627: virtual_incoming_args_rtx = gen_rtx (REG, Pmode, ! 2628: VIRTUAL_INCOMING_ARGS_REGNUM); ! 2629: virtual_stack_vars_rtx = gen_rtx (REG, Pmode, ! 2630: VIRTUAL_STACK_VARS_REGNUM); ! 2631: virtual_stack_dynamic_rtx = gen_rtx (REG, Pmode, ! 2632: VIRTUAL_STACK_DYNAMIC_REGNUM); ! 2633: virtual_outgoing_args_rtx = gen_rtx (REG, Pmode, ! 2634: VIRTUAL_OUTGOING_ARGS_REGNUM); ! 2635: ! 2636: #ifdef STRUCT_VALUE ! 2637: struct_value_rtx = STRUCT_VALUE; ! 2638: #else ! 2639: struct_value_rtx = gen_rtx (REG, Pmode, STRUCT_VALUE_REGNUM); ! 2640: #endif ! 2641: ! 2642: #ifdef STRUCT_VALUE_INCOMING ! 2643: struct_value_incoming_rtx = STRUCT_VALUE_INCOMING; ! 2644: #else ! 2645: #ifdef STRUCT_VALUE_INCOMING_REGNUM ! 2646: struct_value_incoming_rtx ! 2647: = gen_rtx (REG, Pmode, STRUCT_VALUE_INCOMING_REGNUM); ! 2648: #else ! 2649: struct_value_incoming_rtx = struct_value_rtx; ! 2650: #endif ! 2651: #endif ! 2652: ! 2653: #ifdef STATIC_CHAIN_REGNUM ! 2654: static_chain_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM); ! 2655: ! 2656: #ifdef STATIC_CHAIN_INCOMING_REGNUM ! 2657: if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM) ! 2658: static_chain_incoming_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_INCOMING_REGNUM); ! 2659: else ! 2660: #endif ! 2661: static_chain_incoming_rtx = static_chain_rtx; ! 2662: #endif ! 2663: ! 2664: #ifdef STATIC_CHAIN ! 2665: static_chain_rtx = STATIC_CHAIN; ! 2666: ! 2667: #ifdef STATIC_CHAIN_INCOMING ! 2668: static_chain_incoming_rtx = STATIC_CHAIN_INCOMING; ! 2669: #else ! 2670: static_chain_incoming_rtx = static_chain_rtx; ! 2671: #endif ! 2672: #endif ! 2673: ! 2674: #ifdef PIC_OFFSET_TABLE_REGNUM ! 2675: pic_offset_table_rtx = gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM); ! 2676: #endif ! 2677: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.