|
|
1.1 ! root 1: /* Convert RTL to assembler code and output it, for GNU compiler. ! 2: Copyright (C) 1987, 1988, 1989, 1992, 1993 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: /* This is the final pass of the compiler. ! 22: It looks at the rtl code for a function and outputs assembler code. ! 23: ! 24: Call `final_start_function' to output the assembler code for function entry, ! 25: `final' to output assembler code for some RTL code, ! 26: `final_end_function' to output assembler code for function exit. ! 27: If a function is compiled in several pieces, each piece is ! 28: output separately with `final'. ! 29: ! 30: Some optimizations are also done at this level. ! 31: Move instructions that were made unnecessary by good register allocation ! 32: are detected and omitted from the output. (Though most of these ! 33: are removed by the last jump pass.) ! 34: ! 35: Instructions to set the condition codes are omitted when it can be ! 36: seen that the condition codes already had the desired values. ! 37: ! 38: In some cases it is sufficient if the inherited condition codes ! 39: have related values, but this may require the following insn ! 40: (the one that tests the condition codes) to be modified. ! 41: ! 42: The code for the function prologue and epilogue are generated ! 43: directly as assembler code by the macros FUNCTION_PROLOGUE and ! 44: FUNCTION_EPILOGUE. Those instructions never exist as rtl. */ ! 45: ! 46: #include "config.h" ! 47: #include "gvarargs.h" ! 48: #include "tree.h" ! 49: #include "rtl.h" ! 50: #include "regs.h" ! 51: #include "insn-config.h" ! 52: #include "insn-flags.h" ! 53: #include "insn-attr.h" ! 54: #include "insn-codes.h" ! 55: #include "recog.h" ! 56: #include "conditions.h" ! 57: #include "flags.h" ! 58: #include "real.h" ! 59: #include "hard-reg-set.h" ! 60: #include "defaults.h" ! 61: ! 62: #include <stdio.h> ! 63: #include <ctype.h> ! 64: ! 65: #include "output.h" ! 66: ! 67: /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ ! 68: #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) ! 69: #if defined (USG) || defined (NO_STAB_H) ! 70: #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */ ! 71: #else ! 72: #include <stab.h> /* On BSD, use the system's stab.h. */ ! 73: #endif /* not USG */ ! 74: #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ ! 75: ! 76: #ifdef XCOFF_DEBUGGING_INFO ! 77: #include "xcoffout.h" ! 78: #endif ! 79: ! 80: /* .stabd code for line number. */ ! 81: #ifndef N_SLINE ! 82: #define N_SLINE 0x44 ! 83: #endif ! 84: ! 85: /* .stabs code for included file name. */ ! 86: #ifndef N_SOL ! 87: #define N_SOL 0x84 ! 88: #endif ! 89: ! 90: #ifndef INT_TYPE_SIZE ! 91: #define INT_TYPE_SIZE BITS_PER_WORD ! 92: #endif ! 93: ! 94: /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a ! 95: null default for it to save conditionalization later. */ ! 96: #ifndef CC_STATUS_INIT ! 97: #define CC_STATUS_INIT ! 98: #endif ! 99: ! 100: /* How to start an assembler comment. */ ! 101: #ifndef ASM_COMMENT_START ! 102: #define ASM_COMMENT_START ";#" ! 103: #endif ! 104: ! 105: rtx peephole (); ! 106: void output_asm_insn (); ! 107: rtx alter_subreg (); ! 108: static rtx walk_alter_subreg (); ! 109: static int alter_cond (); ! 110: void output_asm_label (); ! 111: static void output_operand (); ! 112: void output_address (); ! 113: void output_addr_const (); ! 114: static void output_source_line (); ! 115: rtx final_scan_insn (); ! 116: void profile_function (); ! 117: static void profile_after_prologue (); ! 118: ! 119: #ifdef HAVE_ATTR_length ! 120: static int asm_insn_count (); ! 121: #endif ! 122: ! 123: /* Nonzero means this function is a leaf function, with no function calls. ! 124: This variable exists to be examined in FUNCTION_PROLOGUE ! 125: and FUNCTION_EPILOGUE. Always zero, unless set by some action. */ ! 126: int leaf_function; ! 127: ! 128: int leaf_function_p (); ! 129: ! 130: #ifdef LEAF_REGISTERS ! 131: int only_leaf_regs_used (); ! 132: static void leaf_renumber_regs (); ! 133: void leaf_renumber_regs_insn (); ! 134: #endif ! 135: ! 136: #ifdef OUTPUT_COMPILER_STUB ! 137: extern void output_compiler_stub(); ! 138: #endif ! 139: ! 140: /* Last insn processed by final_scan_insn. */ ! 141: static rtx debug_insn = 0; ! 142: ! 143: /* Line number of last NOTE. */ ! 144: static int last_linenum; ! 145: ! 146: /* Filename of last NOTE. */ ! 147: static char *last_filename; ! 148: ! 149: /* Number of basic blocks seen so far; ! 150: used if profile_block_flag is set. */ ! 151: static int count_basic_blocks; ! 152: ! 153: /* Nonzero while outputting an `asm' with operands. ! 154: This means that inconsistencies are the user's fault, so don't abort. ! 155: The precise value is the insn being output, to pass to error_for_asm. */ ! 156: static rtx this_is_asm_operands; ! 157: ! 158: /* Number of operands of this insn, for an `asm' with operands. */ ! 159: static int insn_noperands; ! 160: ! 161: /* Compare optimization flag. */ ! 162: ! 163: static rtx last_ignored_compare = 0; ! 164: ! 165: /* Flag indicating this insn is the start of a new basic block. */ ! 166: ! 167: static int new_block = 1; ! 168: ! 169: /* All the symbol-blocks (levels of scoping) in the compilation ! 170: are assigned sequence numbers in order of appearance of the ! 171: beginnings of the symbol-blocks. Both final and dbxout do this, ! 172: and assume that they will both give the same number to each block. ! 173: Final uses these sequence numbers to generate assembler label names ! 174: LBBnnn and LBEnnn for the beginning and end of the symbol-block. ! 175: Dbxout uses the sequence numbers to generate references to the same labels ! 176: from the dbx debugging information. ! 177: ! 178: Sdb records this level at the beginning of each function, ! 179: in order to find the current level when recursing down declarations. ! 180: It outputs the block beginning and endings ! 181: at the point in the asm file where the blocks would begin and end. */ ! 182: ! 183: int next_block_index; ! 184: ! 185: /* Assign a unique number to each insn that is output. ! 186: This can be used to generate unique local labels. */ ! 187: ! 188: static int insn_counter = 0; ! 189: ! 190: #ifdef HAVE_cc0 ! 191: /* This variable contains machine-dependent flags (defined in tm.h) ! 192: set and examined by output routines ! 193: that describe how to interpret the condition codes properly. */ ! 194: ! 195: CC_STATUS cc_status; ! 196: ! 197: /* During output of an insn, this contains a copy of cc_status ! 198: from before the insn. */ ! 199: ! 200: CC_STATUS cc_prev_status; ! 201: #endif ! 202: ! 203: /* Indexed by hardware reg number, is 1 if that register is ever ! 204: used in the current function. ! 205: ! 206: In life_analysis, or in stupid_life_analysis, this is set ! 207: up to record the hard regs used explicitly. Reload adds ! 208: in the hard regs used for holding pseudo regs. Final uses ! 209: it to generate the code in the function prologue and epilogue ! 210: to save and restore registers as needed. */ ! 211: ! 212: char regs_ever_live[FIRST_PSEUDO_REGISTER]; ! 213: ! 214: /* Nonzero means current function must be given a frame pointer. ! 215: Set in stmt.c if anything is allocated on the stack there. ! 216: Set in reload1.c if anything is allocated on the stack there. */ ! 217: ! 218: int frame_pointer_needed; ! 219: ! 220: /* Assign unique numbers to labels generated for profiling. */ ! 221: ! 222: int profile_label_no; ! 223: ! 224: /* Length so far allocated in PENDING_BLOCKS. */ ! 225: ! 226: static int max_block_depth; ! 227: ! 228: /* Stack of sequence numbers of symbol-blocks of which we have seen the ! 229: beginning but not yet the end. Sequence numbers are assigned at ! 230: the beginning; this stack allows us to find the sequence number ! 231: of a block that is ending. */ ! 232: ! 233: static int *pending_blocks; ! 234: ! 235: /* Number of elements currently in use in PENDING_BLOCKS. */ ! 236: ! 237: static int block_depth; ! 238: ! 239: /* Nonzero if have enabled APP processing of our assembler output. */ ! 240: ! 241: static int app_on; ! 242: ! 243: /* If we are outputting an insn sequence, this contains the sequence rtx. ! 244: Zero otherwise. */ ! 245: ! 246: rtx final_sequence; ! 247: ! 248: #ifdef ASSEMBLER_DIALECT ! 249: ! 250: /* Number of the assembler dialect to use, starting at 0. */ ! 251: static int dialect_number; ! 252: #endif ! 253: ! 254: /* Indexed by line number, nonzero if there is a note for that line. */ ! 255: ! 256: static char *line_note_exists; ! 257: ! 258: /* Linked list to hold line numbers for each basic block. */ ! 259: ! 260: struct bb_list { ! 261: struct bb_list *next; /* pointer to next basic block */ ! 262: int line_num; /* line number */ ! 263: int file_label_num; /* LPBC<n> label # for stored filename */ ! 264: int func_label_num; /* LPBC<n> label # for stored function name */ ! 265: }; ! 266: ! 267: static struct bb_list *bb_head = 0; /* Head of basic block list */ ! 268: static struct bb_list **bb_tail = &bb_head; /* Ptr to store next bb ptr */ ! 269: static int bb_file_label_num = -1; /* Current label # for file */ ! 270: static int bb_func_label_num = -1; /* Current label # for func */ ! 271: ! 272: /* Linked list to hold the strings for each file and function name output. */ ! 273: ! 274: struct bb_str { ! 275: struct bb_str *next; /* pointer to next string */ ! 276: char *string; /* string */ ! 277: int label_num; /* label number */ ! 278: int length; /* string length */ ! 279: }; ! 280: ! 281: static struct bb_str *sbb_head = 0; /* Head of string list. */ ! 282: static struct bb_str **sbb_tail = &sbb_head; /* Ptr to store next bb str */ ! 283: static int sbb_label_num = 0; /* Last label used */ ! 284: ! 285: static int add_bb_string PROTO((char *, int)); ! 286: static void add_bb PROTO((FILE *)); ! 287: ! 288: ! 289: /* Initialize data in final at the beginning of a compilation. */ ! 290: ! 291: void ! 292: init_final (filename) ! 293: char *filename; ! 294: { ! 295: next_block_index = 2; ! 296: app_on = 0; ! 297: max_block_depth = 20; ! 298: pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks); ! 299: final_sequence = 0; ! 300: ! 301: #ifdef ASSEMBLER_DIALECT ! 302: dialect_number = ASSEMBLER_DIALECT; ! 303: #endif ! 304: } ! 305: ! 306: /* Called at end of source file, ! 307: to output the block-profiling table for this entire compilation. */ ! 308: ! 309: void ! 310: end_final (filename) ! 311: char *filename; ! 312: { ! 313: int i; ! 314: ! 315: if (profile_block_flag) ! 316: { ! 317: char name[20]; ! 318: int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); ! 319: int size = (INT_TYPE_SIZE / BITS_PER_UNIT) * count_basic_blocks; ! 320: int rounded = size; ! 321: struct bb_list *ptr; ! 322: struct bb_str *sptr; ! 323: ! 324: rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; ! 325: rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) ! 326: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ! 327: ! 328: data_section (); ! 329: ! 330: /* Output the main header, of 10 words: ! 331: 0: 1 if this file's initialized, else 0. ! 332: 1: address of file name (LPBX1). ! 333: 2: address of table of counts (LPBX2). ! 334: 3: number of counts in the table. ! 335: 4: always 0, for compatibility with Sun. ! 336: ! 337: The following are GNU extensions: ! 338: ! 339: 5: address of table of start addrs of basic blocks (LPBX3). ! 340: 6: Number of bytes in this header. ! 341: 7: address of table of function names (LPBX4). ! 342: 8: address of table of line numbers (LPBX5) or 0. ! 343: 9: address of table of file names (LPBX6) or 0. */ ! 344: ! 345: ASM_OUTPUT_ALIGN (asm_out_file, align); ! 346: ! 347: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0); ! 348: /* zero word */ ! 349: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 350: ! 351: /* address of filename */ ! 352: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1); ! 353: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 354: ! 355: /* address of count table */ ! 356: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); ! 357: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 358: ! 359: /* count of the # of basic blocks */ ! 360: assemble_integer (GEN_INT (count_basic_blocks), UNITS_PER_WORD, 1); ! 361: ! 362: /* zero word (link field) */ ! 363: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 364: ! 365: /* address of basic block start address table */ ! 366: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); ! 367: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 368: ! 369: /* byte count for extended structure. */ ! 370: assemble_integer (GEN_INT (10 * UNITS_PER_WORD), UNITS_PER_WORD, 1); ! 371: ! 372: /* address of function name table */ ! 373: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 4); ! 374: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 375: ! 376: /* address of line number and filename tables if debugging. */ ! 377: if (write_symbols != NO_DEBUG) ! 378: { ! 379: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 5); ! 380: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 381: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 6); ! 382: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 383: } ! 384: else ! 385: { ! 386: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 387: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 388: } ! 389: ! 390: /* Output the file name changing the suffix to .d for Sun tcov ! 391: compatibility. */ ! 392: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1); ! 393: { ! 394: int len = strlen (filename); ! 395: char *data_file = (char *) alloca (len + 3); ! 396: strcpy (data_file, filename); ! 397: strip_off_ending (data_file, len); ! 398: strcat (data_file, ".d"); ! 399: assemble_string (data_file, strlen (data_file) + 1); ! 400: } ! 401: ! 402: /* Make space for the table of counts. */ ! 403: if (flag_no_common || size == 0) ! 404: { ! 405: /* Realign data section. */ ! 406: ASM_OUTPUT_ALIGN (asm_out_file, align); ! 407: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2); ! 408: if (size != 0) ! 409: assemble_zeros (size); ! 410: } ! 411: else ! 412: { ! 413: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); ! 414: #ifdef ASM_OUTPUT_SHARED_LOCAL ! 415: if (flag_shared_data) ! 416: ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded); ! 417: else ! 418: #endif ! 419: #ifdef ASM_OUTPUT_ALIGNED_LOCAL ! 420: ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, align); ! 421: #else ! 422: ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); ! 423: #endif ! 424: } ! 425: ! 426: /* Output any basic block strings */ ! 427: readonly_data_section (); ! 428: if (sbb_head) ! 429: { ! 430: ASM_OUTPUT_ALIGN (asm_out_file, align); ! 431: for (sptr = sbb_head; sptr != 0; sptr = sptr->next) ! 432: { ! 433: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBC", sptr->label_num); ! 434: assemble_string (sptr->string, sptr->length); ! 435: } ! 436: } ! 437: ! 438: /* Output the table of addresses. */ ! 439: /* Realign in new section */ ! 440: ASM_OUTPUT_ALIGN (asm_out_file, align); ! 441: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3); ! 442: for (i = 0; i < count_basic_blocks; i++) ! 443: { ! 444: ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i); ! 445: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), ! 446: UNITS_PER_WORD, 1); ! 447: } ! 448: ! 449: /* Output the table of function names. */ ! 450: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 4); ! 451: for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++) ! 452: { ! 453: if (ptr->func_label_num >= 0) ! 454: { ! 455: ASM_GENERATE_INTERNAL_LABEL (name, "LPBC", ptr->func_label_num); ! 456: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), ! 457: UNITS_PER_WORD, 1); ! 458: } ! 459: else ! 460: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 461: } ! 462: ! 463: for ( ; i < count_basic_blocks; i++) ! 464: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 465: ! 466: if (write_symbols != NO_DEBUG) ! 467: { ! 468: /* Output the table of line numbers. */ ! 469: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 5); ! 470: for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++) ! 471: assemble_integer (GEN_INT (ptr->line_num), UNITS_PER_WORD, 1); ! 472: ! 473: for ( ; i < count_basic_blocks; i++) ! 474: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 475: ! 476: /* Output the table of file names. */ ! 477: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 6); ! 478: for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++) ! 479: { ! 480: if (ptr->file_label_num >= 0) ! 481: { ! 482: ASM_GENERATE_INTERNAL_LABEL (name, "LPBC", ptr->file_label_num); ! 483: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), ! 484: UNITS_PER_WORD, 1); ! 485: } ! 486: else ! 487: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 488: } ! 489: ! 490: for ( ; i < count_basic_blocks; i++) ! 491: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 492: } ! 493: ! 494: /* End with the address of the table of addresses, ! 495: so we can find it easily, as the last word in the file's text. */ ! 496: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); ! 497: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 498: } ! 499: } ! 500: ! 501: /* Enable APP processing of subsequent output. ! 502: Used before the output from an `asm' statement. */ ! 503: ! 504: void ! 505: app_enable () ! 506: { ! 507: if (! app_on) ! 508: { ! 509: fprintf (asm_out_file, ASM_APP_ON); ! 510: app_on = 1; ! 511: } ! 512: } ! 513: ! 514: /* Enable APP processing of subsequent output. ! 515: Called from varasm.c before most kinds of output. */ ! 516: ! 517: void ! 518: app_disable () ! 519: { ! 520: if (app_on) ! 521: { ! 522: fprintf (asm_out_file, ASM_APP_OFF); ! 523: app_on = 0; ! 524: } ! 525: } ! 526: ! 527: /* Return the number of slots filled in the current ! 528: delayed branch sequence (we don't count the insn needing the ! 529: delay slot). Zero if not in a delayed branch sequence. */ ! 530: ! 531: #ifdef DELAY_SLOTS ! 532: int ! 533: dbr_sequence_length () ! 534: { ! 535: if (final_sequence != 0) ! 536: return XVECLEN (final_sequence, 0) - 1; ! 537: else ! 538: return 0; ! 539: } ! 540: #endif ! 541: ! 542: /* The next two pages contain routines used to compute the length of an insn ! 543: and to shorten branches. */ ! 544: ! 545: /* Arrays for insn lengths, and addresses. The latter is referenced by ! 546: `insn_current_length'. */ ! 547: ! 548: static short *insn_lengths; ! 549: int *insn_addresses; ! 550: ! 551: /* Address of insn being processed. Used by `insn_current_length'. */ ! 552: int insn_current_address; ! 553: ! 554: /* Indicate the branch shortening hasn't yet been done. */ ! 555: ! 556: void ! 557: init_insn_lengths () ! 558: { ! 559: insn_lengths = 0; ! 560: } ! 561: ! 562: /* Obtain the current length of an insn. If branch shortening has been done, ! 563: get its actual length. Otherwise, get its maximum length. */ ! 564: ! 565: int ! 566: get_attr_length (insn) ! 567: rtx insn; ! 568: { ! 569: #ifdef HAVE_ATTR_length ! 570: rtx body; ! 571: int i; ! 572: int length = 0; ! 573: ! 574: if (insn_lengths) ! 575: return insn_lengths[INSN_UID (insn)]; ! 576: else ! 577: switch (GET_CODE (insn)) ! 578: { ! 579: case NOTE: ! 580: case BARRIER: ! 581: case CODE_LABEL: ! 582: return 0; ! 583: ! 584: case CALL_INSN: ! 585: length = insn_default_length (insn); ! 586: break; ! 587: ! 588: case JUMP_INSN: ! 589: body = PATTERN (insn); ! 590: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) ! 591: { ! 592: /* This only takes room if jump tables go into the text section. */ ! 593: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION) ! 594: length = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) ! 595: * GET_MODE_SIZE (GET_MODE (body))); ! 596: ! 597: /* Be pessimistic and assume worst-case alignment. */ ! 598: length += (GET_MODE_SIZE (GET_MODE (body)) - 1); ! 599: #else ! 600: return 0; ! 601: #endif ! 602: } ! 603: else ! 604: length = insn_default_length (insn); ! 605: break; ! 606: ! 607: case INSN: ! 608: body = PATTERN (insn); ! 609: if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER) ! 610: return 0; ! 611: ! 612: else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) ! 613: length = asm_insn_count (body) * insn_default_length (insn); ! 614: else if (GET_CODE (body) == SEQUENCE) ! 615: for (i = 0; i < XVECLEN (body, 0); i++) ! 616: length += get_attr_length (XVECEXP (body, 0, i)); ! 617: else ! 618: length = insn_default_length (insn); ! 619: } ! 620: ! 621: #ifdef ADJUST_INSN_LENGTH ! 622: ADJUST_INSN_LENGTH (insn, length); ! 623: #endif ! 624: return length; ! 625: #else /* not HAVE_ATTR_length */ ! 626: return 0; ! 627: #endif /* not HAVE_ATTR_length */ ! 628: } ! 629: ! 630: /* Make a pass over all insns and compute their actual lengths by shortening ! 631: any branches of variable length if possible. */ ! 632: ! 633: /* Give a default value for the lowest address in a function. */ ! 634: ! 635: #ifndef FIRST_INSN_ADDRESS ! 636: #define FIRST_INSN_ADDRESS 0 ! 637: #endif ! 638: ! 639: void ! 640: shorten_branches (first) ! 641: rtx first; ! 642: { ! 643: #ifdef HAVE_ATTR_length ! 644: rtx insn; ! 645: int something_changed = 1; ! 646: int max_uid = 0; ! 647: char *varying_length; ! 648: rtx body; ! 649: int uid; ! 650: ! 651: /* Compute maximum UID and allocate arrays. */ ! 652: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 653: if (INSN_UID (insn) > max_uid) ! 654: max_uid = INSN_UID (insn); ! 655: ! 656: max_uid++; ! 657: insn_lengths = (short *) oballoc (max_uid * sizeof (short)); ! 658: insn_addresses = (int *) oballoc (max_uid * sizeof (int)); ! 659: varying_length = (char *) oballoc (max_uid * sizeof (char)); ! 660: ! 661: /* Compute initial lengths, addresses, and varying flags for each insn. */ ! 662: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; ! 663: insn != 0; ! 664: insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) ! 665: { ! 666: uid = INSN_UID (insn); ! 667: insn_addresses[uid] = insn_current_address; ! 668: insn_lengths[uid] = 0; ! 669: varying_length[uid] = 0; ! 670: ! 671: if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER ! 672: || GET_CODE (insn) == CODE_LABEL) ! 673: continue; ! 674: ! 675: body = PATTERN (insn); ! 676: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) ! 677: { ! 678: /* This only takes room if read-only data goes into the text ! 679: section. */ ! 680: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION) ! 681: int unitsize = GET_MODE_SIZE (GET_MODE (body)); ! 682: ! 683: insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) ! 684: * GET_MODE_SIZE (GET_MODE (body))); ! 685: ! 686: /* Account for possible alignment. */ ! 687: insn_lengths[uid] ! 688: += unitsize - (insn_current_address & (unitsize - 1)); ! 689: #else ! 690: ; ! 691: #endif ! 692: } ! 693: else if (asm_noperands (body) >= 0) ! 694: insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn); ! 695: else if (GET_CODE (body) == SEQUENCE) ! 696: { ! 697: int i; ! 698: int const_delay_slots; ! 699: #ifdef DELAY_SLOTS ! 700: const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0)); ! 701: #else ! 702: const_delay_slots = 0; ! 703: #endif ! 704: /* Inside a delay slot sequence, we do not do any branch shortening ! 705: if the shortening could change the number of delay slots ! 706: of the branch. */ ! 707: for (i = 0; i < XVECLEN (body, 0); i++) ! 708: { ! 709: rtx inner_insn = XVECEXP (body, 0, i); ! 710: int inner_uid = INSN_UID (inner_insn); ! 711: int inner_length; ! 712: ! 713: if (asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0) ! 714: inner_length = (asm_insn_count (PATTERN (inner_insn)) ! 715: * insn_default_length (inner_insn)); ! 716: else ! 717: inner_length = insn_default_length (inner_insn); ! 718: ! 719: insn_lengths[inner_uid] = inner_length; ! 720: if (const_delay_slots) ! 721: { ! 722: if ((varying_length[inner_uid] ! 723: = insn_variable_length_p (inner_insn)) != 0) ! 724: varying_length[uid] = 1; ! 725: insn_addresses[inner_uid] = (insn_current_address + ! 726: insn_lengths[uid]); ! 727: } ! 728: else ! 729: varying_length[inner_uid] = 0; ! 730: insn_lengths[uid] += inner_length; ! 731: } ! 732: } ! 733: else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER) ! 734: { ! 735: insn_lengths[uid] = insn_default_length (insn); ! 736: varying_length[uid] = insn_variable_length_p (insn); ! 737: } ! 738: ! 739: /* If needed, do any adjustment. */ ! 740: #ifdef ADJUST_INSN_LENGTH ! 741: ADJUST_INSN_LENGTH (insn, insn_lengths[uid]); ! 742: #endif ! 743: } ! 744: ! 745: /* Now loop over all the insns finding varying length insns. For each, ! 746: get the current insn length. If it has changed, reflect the change. ! 747: When nothing changes for a full pass, we are done. */ ! 748: ! 749: while (something_changed) ! 750: { ! 751: something_changed = 0; ! 752: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; ! 753: insn != 0; ! 754: insn = NEXT_INSN (insn)) ! 755: { ! 756: int new_length; ! 757: int tmp_length; ! 758: ! 759: uid = INSN_UID (insn); ! 760: insn_addresses[uid] = insn_current_address; ! 761: if (! varying_length[uid]) ! 762: { ! 763: insn_current_address += insn_lengths[uid]; ! 764: continue; ! 765: } ! 766: if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) ! 767: { ! 768: int i; ! 769: ! 770: body = PATTERN (insn); ! 771: new_length = 0; ! 772: for (i = 0; i < XVECLEN (body, 0); i++) ! 773: { ! 774: rtx inner_insn = XVECEXP (body, 0, i); ! 775: int inner_uid = INSN_UID (inner_insn); ! 776: int inner_length; ! 777: ! 778: insn_addresses[inner_uid] = insn_current_address; ! 779: ! 780: /* insn_current_length returns 0 for insns with a ! 781: non-varying length. */ ! 782: if (! varying_length[inner_uid]) ! 783: inner_length = insn_lengths[inner_uid]; ! 784: else ! 785: inner_length = insn_current_length (inner_insn); ! 786: ! 787: if (inner_length != insn_lengths[inner_uid]) ! 788: { ! 789: insn_lengths[inner_uid] = inner_length; ! 790: something_changed = 1; ! 791: } ! 792: insn_current_address += insn_lengths[inner_uid]; ! 793: new_length += inner_length; ! 794: } ! 795: } ! 796: else ! 797: { ! 798: new_length = insn_current_length (insn); ! 799: insn_current_address += new_length; ! 800: } ! 801: ! 802: #ifdef SHORTEN_WITH_ADJUST_INSN_LENGTH ! 803: #ifdef ADJUST_INSN_LENGTH ! 804: /* If needed, do any adjustment. */ ! 805: tmp_length = new_length; ! 806: ADJUST_INSN_LENGTH (insn, new_length); ! 807: insn_current_address += (new_length - tmp_length); ! 808: #endif ! 809: #endif ! 810: ! 811: if (new_length != insn_lengths[uid]) ! 812: { ! 813: insn_lengths[uid] = new_length; ! 814: something_changed = 1; ! 815: } ! 816: } ! 817: } ! 818: #endif /* HAVE_ATTR_length */ ! 819: } ! 820: ! 821: #ifdef HAVE_ATTR_length ! 822: /* Given the body of an INSN known to be generated by an ASM statement, return ! 823: the number of machine instructions likely to be generated for this insn. ! 824: This is used to compute its length. */ ! 825: ! 826: static int ! 827: asm_insn_count (body) ! 828: rtx body; ! 829: { ! 830: char *template; ! 831: int count = 1; ! 832: ! 833: for (template = decode_asm_operands (body, NULL_PTR, NULL_PTR, ! 834: NULL_PTR, NULL_PTR); ! 835: *template; template++) ! 836: if (*template == ';' || *template == '\n') ! 837: count++; ! 838: ! 839: return count; ! 840: } ! 841: #endif ! 842: ! 843: /* Output assembler code for the start of a function, ! 844: and initialize some of the variables in this file ! 845: for the new function. The label for the function and associated ! 846: assembler pseudo-ops have already been output in `assemble_start_function'. ! 847: ! 848: FIRST is the first insn of the rtl for the function being compiled. ! 849: FILE is the file to write assembler code to. ! 850: OPTIMIZE is nonzero if we should eliminate redundant ! 851: test and compare insns. */ ! 852: ! 853: void ! 854: final_start_function (first, file, optimize) ! 855: rtx first; ! 856: FILE *file; ! 857: int optimize; ! 858: { ! 859: block_depth = 0; ! 860: ! 861: this_is_asm_operands = 0; ! 862: ! 863: #ifdef NON_SAVING_SETJMP ! 864: /* A function that calls setjmp should save and restore all the ! 865: call-saved registers on a system where longjmp clobbers them. */ ! 866: if (NON_SAVING_SETJMP && current_function_calls_setjmp) ! 867: { ! 868: int i; ! 869: ! 870: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 871: if (!call_used_regs[i] && !call_fixed_regs[i]) ! 872: regs_ever_live[i] = 1; ! 873: } ! 874: #endif ! 875: ! 876: /* Initial line number is supposed to be output ! 877: before the function's prologue and label ! 878: so that the function's address will not appear to be ! 879: in the last statement of the preceding function. */ ! 880: if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED) ! 881: { ! 882: if (write_symbols == SDB_DEBUG) ! 883: /* For sdb, let's not, but say we did. ! 884: We need to set last_linenum for sdbout_function_begin, ! 885: but we can't have an actual line number before the .bf symbol. ! 886: (sdb_begin_function_line is not set, ! 887: and other compilers don't do it.) */ ! 888: last_linenum = NOTE_LINE_NUMBER (first); ! 889: #ifdef XCOFF_DEBUGGING_INFO ! 890: else if (write_symbols == XCOFF_DEBUG) ! 891: { ! 892: last_linenum = NOTE_LINE_NUMBER (first); ! 893: xcoffout_output_first_source_line (file, last_linenum); ! 894: } ! 895: #endif ! 896: else ! 897: output_source_line (file, first); ! 898: } ! 899: ! 900: #ifdef LEAF_REG_REMAP ! 901: if (leaf_function) ! 902: leaf_renumber_regs (first); ! 903: #endif ! 904: ! 905: /* The Sun386i and perhaps other machines don't work right ! 906: if the profiling code comes after the prologue. */ ! 907: #ifdef PROFILE_BEFORE_PROLOGUE ! 908: if (profile_flag) ! 909: profile_function (file); ! 910: #endif /* PROFILE_BEFORE_PROLOGUE */ ! 911: ! 912: #ifdef FUNCTION_PROLOGUE ! 913: /* First output the function prologue: code to set up the stack frame. */ ! 914: FUNCTION_PROLOGUE (file, get_frame_size ()); ! 915: #endif ! 916: ! 917: #if defined (SDB_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) ! 918: if (write_symbols == SDB_DEBUG || write_symbols == XCOFF_DEBUG) ! 919: next_block_index = 1; ! 920: #endif ! 921: ! 922: /* If the machine represents the prologue as RTL, the profiling code must ! 923: be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ ! 924: #ifdef HAVE_prologue ! 925: if (! HAVE_prologue) ! 926: #endif ! 927: profile_after_prologue (file); ! 928: ! 929: profile_label_no++; ! 930: ! 931: /* If we are doing basic block profiling, remember a printable version ! 932: of the function name. */ ! 933: if (profile_block_flag) ! 934: { ! 935: char *junk = "function"; ! 936: bb_func_label_num = ! 937: add_bb_string ((*decl_printable_name) (current_function_decl, &junk), FALSE); ! 938: } ! 939: } ! 940: ! 941: static void ! 942: profile_after_prologue (file) ! 943: FILE *file; ! 944: { ! 945: #ifdef FUNCTION_BLOCK_PROFILER ! 946: if (profile_block_flag) ! 947: { ! 948: FUNCTION_BLOCK_PROFILER (file, profile_label_no); ! 949: } ! 950: #endif /* FUNCTION_BLOCK_PROFILER */ ! 951: ! 952: #ifndef PROFILE_BEFORE_PROLOGUE ! 953: if (profile_flag) ! 954: profile_function (file); ! 955: #endif /* not PROFILE_BEFORE_PROLOGUE */ ! 956: } ! 957: ! 958: void ! 959: profile_function (file) ! 960: FILE *file; ! 961: { ! 962: int align = MIN (BIGGEST_ALIGNMENT, INT_TYPE_SIZE); ! 963: int sval = current_function_returns_struct; ! 964: int cxt = current_function_needs_context; ! 965: ! 966: data_section (); ! 967: ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); ! 968: #ifdef PROFILE_LABEL_PREFIX ! 969: ASM_OUTPUT_INTERNAL_LABEL (file, "_LP", profile_label_no); ! 970: #else ! 971: ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no); ! 972: #endif ! 973: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 974: ! 975: text_section (); ! 976: ! 977: #ifdef STRUCT_VALUE_INCOMING_REGNUM ! 978: if (sval) ! 979: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM); ! 980: #else ! 981: #ifdef STRUCT_VALUE_REGNUM ! 982: if (sval) ! 983: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM); ! 984: #endif ! 985: #endif ! 986: ! 987: #if 0 ! 988: #ifdef STATIC_CHAIN_INCOMING_REGNUM ! 989: if (cxt) ! 990: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM); ! 991: #else ! 992: #ifdef STATIC_CHAIN_REGNUM ! 993: if (cxt) ! 994: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM); ! 995: #endif ! 996: #endif ! 997: #endif /* 0 */ ! 998: ! 999: FUNCTION_PROFILER (file, profile_label_no); ! 1000: ! 1001: #if 0 ! 1002: #ifdef STATIC_CHAIN_INCOMING_REGNUM ! 1003: if (cxt) ! 1004: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM); ! 1005: #else ! 1006: #ifdef STATIC_CHAIN_REGNUM ! 1007: if (cxt) ! 1008: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM); ! 1009: #endif ! 1010: #endif ! 1011: #endif /* 0 */ ! 1012: ! 1013: #ifdef STRUCT_VALUE_INCOMING_REGNUM ! 1014: if (sval) ! 1015: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM); ! 1016: #else ! 1017: #ifdef STRUCT_VALUE_REGNUM ! 1018: if (sval) ! 1019: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM); ! 1020: #endif ! 1021: #endif ! 1022: } ! 1023: ! 1024: /* Output assembler code for the end of a function. ! 1025: For clarity, args are same as those of `final_start_function' ! 1026: even though not all of them are needed. */ ! 1027: ! 1028: void ! 1029: final_end_function (first, file, optimize) ! 1030: rtx first; ! 1031: FILE *file; ! 1032: int optimize; ! 1033: { ! 1034: if (app_on) ! 1035: { ! 1036: fprintf (file, ASM_APP_OFF); ! 1037: app_on = 0; ! 1038: } ! 1039: ! 1040: #ifdef SDB_DEBUGGING_INFO ! 1041: if (write_symbols == SDB_DEBUG) ! 1042: sdbout_end_function (last_linenum); ! 1043: #endif ! 1044: ! 1045: #ifdef DWARF_DEBUGGING_INFO ! 1046: if (write_symbols == DWARF_DEBUG) ! 1047: dwarfout_end_function (); ! 1048: #endif ! 1049: ! 1050: #ifdef XCOFF_DEBUGGING_INFO ! 1051: if (write_symbols == XCOFF_DEBUG) ! 1052: xcoffout_end_function (file, last_linenum); ! 1053: #endif ! 1054: ! 1055: #ifdef FUNCTION_EPILOGUE ! 1056: /* Finally, output the function epilogue: ! 1057: code to restore the stack frame and return to the caller. */ ! 1058: FUNCTION_EPILOGUE (file, get_frame_size ()); ! 1059: #endif ! 1060: ! 1061: #ifdef OUTPUT_COMPILER_STUB ! 1062: output_compiler_stub(); ! 1063: #endif ! 1064: ! 1065: #ifdef SDB_DEBUGGING_INFO ! 1066: if (write_symbols == SDB_DEBUG) ! 1067: sdbout_end_epilogue (); ! 1068: #endif ! 1069: ! 1070: #ifdef DWARF_DEBUGGING_INFO ! 1071: if (write_symbols == DWARF_DEBUG) ! 1072: dwarfout_end_epilogue (); ! 1073: #endif ! 1074: ! 1075: #ifdef XCOFF_DEBUGGING_INFO ! 1076: if (write_symbols == XCOFF_DEBUG) ! 1077: xcoffout_end_epilogue (file); ! 1078: #endif ! 1079: ! 1080: bb_func_label_num = -1; /* not in function, nuke label # */ ! 1081: ! 1082: /* If FUNCTION_EPILOGUE is not defined, then the function body ! 1083: itself contains return instructions wherever needed. */ ! 1084: } ! 1085: ! 1086: /* Add a block to the linked list that remembers the current line/file/function ! 1087: for basic block profiling. Emit the label in front of the basic block and ! 1088: the instructions that increment the count field. */ ! 1089: ! 1090: static void ! 1091: add_bb (file) ! 1092: FILE *file; ! 1093: { ! 1094: struct bb_list *ptr = (struct bb_list *) permalloc (sizeof (struct bb_list)); ! 1095: ! 1096: /* Add basic block to linked list. */ ! 1097: ptr->next = 0; ! 1098: ptr->line_num = last_linenum; ! 1099: ptr->file_label_num = bb_file_label_num; ! 1100: ptr->func_label_num = bb_func_label_num; ! 1101: *bb_tail = ptr; ! 1102: bb_tail = &ptr->next; ! 1103: ! 1104: /* Enable the table of basic-block use counts ! 1105: to point at the code it applies to. */ ! 1106: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks); ! 1107: ! 1108: /* Before first insn of this basic block, increment the ! 1109: count of times it was entered. */ ! 1110: #ifdef BLOCK_PROFILER ! 1111: BLOCK_PROFILER (file, count_basic_blocks); ! 1112: CC_STATUS_INIT; ! 1113: #endif ! 1114: ! 1115: new_block = 0; ! 1116: count_basic_blocks++; ! 1117: } ! 1118: ! 1119: /* Add a string to be used for basic block profiling. */ ! 1120: ! 1121: static int ! 1122: add_bb_string (string, perm_p) ! 1123: char *string; ! 1124: int perm_p; ! 1125: { ! 1126: int len; ! 1127: struct bb_str *ptr = 0; ! 1128: ! 1129: if (!string) ! 1130: { ! 1131: string = "<unknown>"; ! 1132: perm_p = TRUE; ! 1133: } ! 1134: ! 1135: /* Allocate a new string if the current string isn't permanent. If ! 1136: the string is permanent search for the same string in other ! 1137: allocations. */ ! 1138: ! 1139: len = strlen (string) + 1; ! 1140: if (!perm_p) ! 1141: { ! 1142: char *p = (char *) permalloc (len); ! 1143: bcopy (string, p, len); ! 1144: string = p; ! 1145: } ! 1146: else ! 1147: for (ptr = sbb_head; ptr != (struct bb_str *)0; ptr = ptr->next) ! 1148: if (ptr->string == string) ! 1149: break; ! 1150: ! 1151: /* Allocate a new string block if we need to. */ ! 1152: if (!ptr) ! 1153: { ! 1154: ptr = (struct bb_str *) permalloc (sizeof (*ptr)); ! 1155: ptr->next = 0; ! 1156: ptr->length = len; ! 1157: ptr->label_num = sbb_label_num++; ! 1158: ptr->string = string; ! 1159: *sbb_tail = ptr; ! 1160: sbb_tail = &ptr->next; ! 1161: } ! 1162: ! 1163: return ptr->label_num; ! 1164: } ! 1165: ! 1166: ! 1167: /* Output assembler code for some insns: all or part of a function. ! 1168: For description of args, see `final_start_function', above. ! 1169: ! 1170: PRESCAN is 1 if we are not really outputting, ! 1171: just scanning as if we were outputting. ! 1172: Prescanning deletes and rearranges insns just like ordinary output. ! 1173: PRESCAN is -2 if we are outputting after having prescanned. ! 1174: In this case, don't try to delete or rearrange insns ! 1175: because that has already been done. ! 1176: Prescanning is done only on certain machines. */ ! 1177: ! 1178: void ! 1179: final (first, file, optimize, prescan) ! 1180: rtx first; ! 1181: FILE *file; ! 1182: int optimize; ! 1183: int prescan; ! 1184: { ! 1185: register rtx insn; ! 1186: int max_line = 0; ! 1187: ! 1188: last_ignored_compare = 0; ! 1189: new_block = 1; ! 1190: ! 1191: /* Make a map indicating which line numbers appear in this function. ! 1192: When producing SDB debugging info, delete troublesome line number ! 1193: notes from inlined functions in other files as well as duplicate ! 1194: line number notes. */ ! 1195: #ifdef SDB_DEBUGGING_INFO ! 1196: if (write_symbols == SDB_DEBUG) ! 1197: { ! 1198: rtx last = 0; ! 1199: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 1200: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) ! 1201: { ! 1202: if ((RTX_INTEGRATED_P (insn) ! 1203: && strcmp (NOTE_SOURCE_FILE (insn), main_input_filename) != 0) ! 1204: || (last != 0 ! 1205: && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last) ! 1206: && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last))) ! 1207: { ! 1208: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; ! 1209: NOTE_SOURCE_FILE (insn) = 0; ! 1210: continue; ! 1211: } ! 1212: last = insn; ! 1213: if (NOTE_LINE_NUMBER (insn) > max_line) ! 1214: max_line = NOTE_LINE_NUMBER (insn); ! 1215: } ! 1216: } ! 1217: else ! 1218: #endif ! 1219: { ! 1220: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 1221: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line) ! 1222: max_line = NOTE_LINE_NUMBER (insn); ! 1223: } ! 1224: ! 1225: line_note_exists = (char *) oballoc (max_line + 1); ! 1226: bzero (line_note_exists, max_line + 1); ! 1227: ! 1228: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 1229: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) ! 1230: line_note_exists[NOTE_LINE_NUMBER (insn)] = 1; ! 1231: ! 1232: init_recog (); ! 1233: ! 1234: CC_STATUS_INIT; ! 1235: ! 1236: /* Output the insns. */ ! 1237: for (insn = NEXT_INSN (first); insn;) ! 1238: insn = final_scan_insn (insn, file, optimize, prescan, 0); ! 1239: ! 1240: /* Do basic-block profiling here ! 1241: if the last insn was a conditional branch. */ ! 1242: if (profile_block_flag && new_block) ! 1243: add_bb (file); ! 1244: } ! 1245: ! 1246: /* The final scan for one insn, INSN. ! 1247: Args are same as in `final', except that INSN ! 1248: is the insn being scanned. ! 1249: Value returned is the next insn to be scanned. ! 1250: ! 1251: NOPEEPHOLES is the flag to disallow peephole processing (currently ! 1252: used for within delayed branch sequence output). */ ! 1253: ! 1254: rtx ! 1255: final_scan_insn (insn, file, optimize, prescan, nopeepholes) ! 1256: rtx insn; ! 1257: FILE *file; ! 1258: int optimize; ! 1259: int prescan; ! 1260: int nopeepholes; ! 1261: { ! 1262: register int i; ! 1263: insn_counter++; ! 1264: ! 1265: /* Ignore deleted insns. These can occur when we split insns (due to a ! 1266: template of "#") while not optimizing. */ ! 1267: if (INSN_DELETED_P (insn)) ! 1268: return NEXT_INSN (insn); ! 1269: ! 1270: switch (GET_CODE (insn)) ! 1271: { ! 1272: case NOTE: ! 1273: if (prescan > 0) ! 1274: break; ! 1275: ! 1276: /* Align the beginning of a loop, for higher speed ! 1277: on certain machines. */ ! 1278: ! 1279: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0) ! 1280: { ! 1281: #ifdef ASM_OUTPUT_LOOP_ALIGN ! 1282: rtx next = next_nonnote_insn (insn); ! 1283: if (next && GET_CODE (next) == CODE_LABEL) ! 1284: { ! 1285: ASM_OUTPUT_LOOP_ALIGN (asm_out_file); ! 1286: } ! 1287: #endif ! 1288: break; ! 1289: } ! 1290: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) ! 1291: break; ! 1292: ! 1293: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) ! 1294: { ! 1295: #ifdef FUNCTION_END_PROLOGUE ! 1296: FUNCTION_END_PROLOGUE (file); ! 1297: #endif ! 1298: profile_after_prologue (file); ! 1299: break; ! 1300: } ! 1301: ! 1302: #ifdef FUNCTION_BEGIN_EPILOGUE ! 1303: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG) ! 1304: { ! 1305: FUNCTION_BEGIN_EPILOGUE (file); ! 1306: break; ! 1307: } ! 1308: #endif ! 1309: ! 1310: if (write_symbols == NO_DEBUG) ! 1311: break; ! 1312: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) ! 1313: { ! 1314: #ifdef SDB_DEBUGGING_INFO ! 1315: if (write_symbols == SDB_DEBUG) ! 1316: sdbout_begin_function (last_linenum); ! 1317: #endif ! 1318: #ifdef XCOFF_DEBUGGING_INFO ! 1319: if (write_symbols == XCOFF_DEBUG) ! 1320: xcoffout_begin_function (file, last_linenum); ! 1321: #endif ! 1322: #ifdef DWARF_DEBUGGING_INFO ! 1323: if (write_symbols == DWARF_DEBUG) ! 1324: dwarfout_begin_function (); ! 1325: #endif ! 1326: break; ! 1327: } ! 1328: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED) ! 1329: break; /* An insn that was "deleted" */ ! 1330: if (app_on) ! 1331: { ! 1332: fprintf (file, ASM_APP_OFF); ! 1333: app_on = 0; ! 1334: } ! 1335: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG ! 1336: && (debug_info_level == DINFO_LEVEL_NORMAL ! 1337: || debug_info_level == DINFO_LEVEL_VERBOSE ! 1338: #ifdef DWARF_DEBUGGING_INFO ! 1339: || write_symbols == DWARF_DEBUG ! 1340: #endif ! 1341: ) ! 1342: ) ! 1343: { ! 1344: /* Beginning of a symbol-block. Assign it a sequence number ! 1345: and push the number onto the stack PENDING_BLOCKS. */ ! 1346: ! 1347: if (block_depth == max_block_depth) ! 1348: { ! 1349: /* PENDING_BLOCKS is full; make it longer. */ ! 1350: max_block_depth *= 2; ! 1351: pending_blocks ! 1352: = (int *) xrealloc (pending_blocks, ! 1353: max_block_depth * sizeof (int)); ! 1354: } ! 1355: pending_blocks[block_depth++] = next_block_index; ! 1356: ! 1357: /* Output debugging info about the symbol-block beginning. */ ! 1358: ! 1359: #ifdef SDB_DEBUGGING_INFO ! 1360: if (write_symbols == SDB_DEBUG) ! 1361: sdbout_begin_block (file, last_linenum, next_block_index); ! 1362: #endif ! 1363: #ifdef XCOFF_DEBUGGING_INFO ! 1364: if (write_symbols == XCOFF_DEBUG) ! 1365: xcoffout_begin_block (file, last_linenum, next_block_index); ! 1366: #endif ! 1367: #ifdef DBX_DEBUGGING_INFO ! 1368: if (write_symbols == DBX_DEBUG) ! 1369: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index); ! 1370: #endif ! 1371: #ifdef DWARF_DEBUGGING_INFO ! 1372: if (write_symbols == DWARF_DEBUG && block_depth > 1) ! 1373: dwarfout_begin_block (next_block_index); ! 1374: #endif ! 1375: ! 1376: next_block_index++; ! 1377: } ! 1378: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END ! 1379: && (debug_info_level == DINFO_LEVEL_NORMAL ! 1380: || debug_info_level == DINFO_LEVEL_VERBOSE ! 1381: #ifdef DWARF_DEBUGGING_INFO ! 1382: || write_symbols == DWARF_DEBUG ! 1383: #endif ! 1384: ) ! 1385: ) ! 1386: { ! 1387: /* End of a symbol-block. Pop its sequence number off ! 1388: PENDING_BLOCKS and output debugging info based on that. */ ! 1389: ! 1390: --block_depth; ! 1391: ! 1392: #ifdef XCOFF_DEBUGGING_INFO ! 1393: if (write_symbols == XCOFF_DEBUG && block_depth >= 0) ! 1394: xcoffout_end_block (file, last_linenum, pending_blocks[block_depth]); ! 1395: #endif ! 1396: #ifdef DBX_DEBUGGING_INFO ! 1397: if (write_symbols == DBX_DEBUG && block_depth >= 0) ! 1398: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", ! 1399: pending_blocks[block_depth]); ! 1400: #endif ! 1401: #ifdef SDB_DEBUGGING_INFO ! 1402: if (write_symbols == SDB_DEBUG && block_depth >= 0) ! 1403: sdbout_end_block (file, last_linenum); ! 1404: #endif ! 1405: #ifdef DWARF_DEBUGGING_INFO ! 1406: if (write_symbols == DWARF_DEBUG && block_depth >= 1) ! 1407: dwarfout_end_block (pending_blocks[block_depth]); ! 1408: #endif ! 1409: } ! 1410: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL ! 1411: && (debug_info_level == DINFO_LEVEL_NORMAL ! 1412: || debug_info_level == DINFO_LEVEL_VERBOSE)) ! 1413: { ! 1414: #ifdef DWARF_DEBUGGING_INFO ! 1415: if (write_symbols == DWARF_DEBUG) ! 1416: dwarfout_label (insn); ! 1417: #endif ! 1418: } ! 1419: else if (NOTE_LINE_NUMBER (insn) > 0) ! 1420: /* This note is a line-number. */ ! 1421: { ! 1422: register rtx note; ! 1423: ! 1424: #if 0 /* This is what we used to do. */ ! 1425: output_source_line (file, insn); ! 1426: #endif ! 1427: int note_after = 0; ! 1428: ! 1429: /* If there is anything real after this note, ! 1430: output it. If another line note follows, omit this one. */ ! 1431: for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note)) ! 1432: { ! 1433: if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL) ! 1434: break; ! 1435: /* These types of notes can be significant ! 1436: so make sure the preceding line number stays. */ ! 1437: else if (GET_CODE (note) == NOTE ! 1438: && (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG ! 1439: || NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_END ! 1440: || NOTE_LINE_NUMBER (note) == NOTE_INSN_FUNCTION_BEG)) ! 1441: break; ! 1442: else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0) ! 1443: { ! 1444: /* Another line note follows; we can delete this note ! 1445: if no intervening line numbers have notes elsewhere. */ ! 1446: int num; ! 1447: for (num = NOTE_LINE_NUMBER (insn) + 1; ! 1448: num < NOTE_LINE_NUMBER (note); ! 1449: num++) ! 1450: if (line_note_exists[num]) ! 1451: break; ! 1452: ! 1453: if (num >= NOTE_LINE_NUMBER (note)) ! 1454: note_after = 1; ! 1455: break; ! 1456: } ! 1457: } ! 1458: ! 1459: /* Output this line note ! 1460: if it is the first or the last line note in a row. */ ! 1461: if (!note_after) ! 1462: output_source_line (file, insn); ! 1463: } ! 1464: break; ! 1465: ! 1466: case BARRIER: ! 1467: #ifdef ASM_OUTPUT_ALIGN_CODE ! 1468: /* Don't litter the assembler output with needless alignments. A ! 1469: BARRIER will be placed at the end of every function if HAVE_epilogue ! 1470: is true. */ ! 1471: if (NEXT_INSN (insn)) ! 1472: ASM_OUTPUT_ALIGN_CODE (file); ! 1473: #endif ! 1474: break; ! 1475: ! 1476: case CODE_LABEL: ! 1477: CC_STATUS_INIT; ! 1478: if (prescan > 0) ! 1479: break; ! 1480: new_block = 1; ! 1481: #ifdef SDB_DEBUGGING_INFO ! 1482: if (write_symbols == SDB_DEBUG && LABEL_NAME (insn)) ! 1483: sdbout_label (insn); ! 1484: #endif ! 1485: #ifdef DWARF_DEBUGGING_INFO ! 1486: if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn)) ! 1487: dwarfout_label (insn); ! 1488: #endif ! 1489: if (app_on) ! 1490: { ! 1491: fprintf (file, ASM_APP_OFF); ! 1492: app_on = 0; ! 1493: } ! 1494: if (NEXT_INSN (insn) != 0 ! 1495: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN) ! 1496: { ! 1497: rtx nextbody = PATTERN (NEXT_INSN (insn)); ! 1498: ! 1499: /* If this label is followed by a jump-table, ! 1500: make sure we put the label in the read-only section. Also ! 1501: possibly write the label and jump table together. */ ! 1502: ! 1503: if (GET_CODE (nextbody) == ADDR_VEC ! 1504: || GET_CODE (nextbody) == ADDR_DIFF_VEC) ! 1505: { ! 1506: #ifndef JUMP_TABLES_IN_TEXT_SECTION ! 1507: readonly_data_section (); ! 1508: #ifdef READONLY_DATA_SECTION ! 1509: ASM_OUTPUT_ALIGN (file, ! 1510: exact_log2 (BIGGEST_ALIGNMENT ! 1511: / BITS_PER_UNIT)); ! 1512: #endif /* READONLY_DATA_SECTION */ ! 1513: #else /* JUMP_TABLES_IN_TEXT_SECTION */ ! 1514: text_section (); ! 1515: #endif /* JUMP_TABLES_IN_TEXT_SECTION */ ! 1516: #ifdef ASM_OUTPUT_CASE_LABEL ! 1517: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), ! 1518: NEXT_INSN (insn)); ! 1519: #else ! 1520: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); ! 1521: #endif ! 1522: break; ! 1523: } ! 1524: } ! 1525: ! 1526: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); ! 1527: if (XSTR (insn, 4) && (XSTR (insn, 4))[0] == '*') ! 1528: assemble_label (XSTR (insn, 4)); ! 1529: break; ! 1530: ! 1531: default: ! 1532: { ! 1533: register rtx body = PATTERN (insn); ! 1534: int insn_code_number; ! 1535: char *template; ! 1536: rtx note; ! 1537: ! 1538: /* An INSN, JUMP_INSN or CALL_INSN. ! 1539: First check for special kinds that recog doesn't recognize. */ ! 1540: ! 1541: if (GET_CODE (body) == USE /* These are just declarations */ ! 1542: || GET_CODE (body) == CLOBBER) ! 1543: break; ! 1544: ! 1545: #ifdef HAVE_cc0 ! 1546: /* If there is a REG_CC_SETTER note on this insn, it means that ! 1547: the setting of the condition code was done in the delay slot ! 1548: of the insn that branched here. So recover the cc status ! 1549: from the insn that set it. */ ! 1550: ! 1551: note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); ! 1552: if (note) ! 1553: { ! 1554: NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0)); ! 1555: cc_prev_status = cc_status; ! 1556: } ! 1557: #endif ! 1558: ! 1559: /* Detect insns that are really jump-tables ! 1560: and output them as such. */ ! 1561: ! 1562: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) ! 1563: { ! 1564: register int vlen, idx; ! 1565: ! 1566: if (prescan > 0) ! 1567: break; ! 1568: ! 1569: if (app_on) ! 1570: { ! 1571: fprintf (file, ASM_APP_OFF); ! 1572: app_on = 0; ! 1573: } ! 1574: ! 1575: vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC); ! 1576: for (idx = 0; idx < vlen; idx++) ! 1577: { ! 1578: if (GET_CODE (body) == ADDR_VEC) ! 1579: { ! 1580: #ifdef ASM_OUTPUT_ADDR_VEC_ELT ! 1581: ASM_OUTPUT_ADDR_VEC_ELT ! 1582: (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); ! 1583: #else ! 1584: abort (); ! 1585: #endif ! 1586: } ! 1587: else ! 1588: { ! 1589: #ifdef ASM_OUTPUT_ADDR_DIFF_ELT ! 1590: ASM_OUTPUT_ADDR_DIFF_ELT ! 1591: (file, ! 1592: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), ! 1593: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); ! 1594: #else ! 1595: abort (); ! 1596: #endif ! 1597: } ! 1598: } ! 1599: #ifdef ASM_OUTPUT_CASE_END ! 1600: ASM_OUTPUT_CASE_END (file, ! 1601: CODE_LABEL_NUMBER (PREV_INSN (insn)), ! 1602: insn); ! 1603: #endif ! 1604: ! 1605: text_section (); ! 1606: ! 1607: break; ! 1608: } ! 1609: ! 1610: /* Do basic-block profiling when we reach a new block. ! 1611: Done here to avoid jump tables. */ ! 1612: if (profile_block_flag && new_block) ! 1613: add_bb (file); ! 1614: ! 1615: if (GET_CODE (body) == ASM_INPUT) ! 1616: { ! 1617: /* There's no telling what that did to the condition codes. */ ! 1618: CC_STATUS_INIT; ! 1619: if (prescan > 0) ! 1620: break; ! 1621: if (! app_on) ! 1622: { ! 1623: fprintf (file, ASM_APP_ON); ! 1624: app_on = 1; ! 1625: } ! 1626: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0)); ! 1627: break; ! 1628: } ! 1629: ! 1630: /* Detect `asm' construct with operands. */ ! 1631: if (asm_noperands (body) >= 0) ! 1632: { ! 1633: int noperands = asm_noperands (body); ! 1634: rtx *ops; ! 1635: char *string; ! 1636: ! 1637: /* There's no telling what that did to the condition codes. */ ! 1638: CC_STATUS_INIT; ! 1639: if (prescan > 0) ! 1640: break; ! 1641: ! 1642: /* alloca won't do here, since only return from `final' ! 1643: would free it. */ ! 1644: if (noperands > 0) ! 1645: ops = (rtx *) xmalloc (noperands * sizeof (rtx)); ! 1646: ! 1647: if (! app_on) ! 1648: { ! 1649: fprintf (file, ASM_APP_ON); ! 1650: app_on = 1; ! 1651: } ! 1652: ! 1653: /* Get out the operand values. */ ! 1654: string = decode_asm_operands (body, ops, NULL_PTR, ! 1655: NULL_PTR, NULL_PTR); ! 1656: /* Inhibit aborts on what would otherwise be compiler bugs. */ ! 1657: insn_noperands = noperands; ! 1658: this_is_asm_operands = insn; ! 1659: /* Output the insn using them. */ ! 1660: output_asm_insn (string, ops); ! 1661: this_is_asm_operands = 0; ! 1662: if (noperands > 0) ! 1663: free (ops); ! 1664: break; ! 1665: } ! 1666: ! 1667: if (prescan <= 0 && app_on) ! 1668: { ! 1669: fprintf (file, ASM_APP_OFF); ! 1670: app_on = 0; ! 1671: } ! 1672: ! 1673: if (GET_CODE (body) == SEQUENCE) ! 1674: { ! 1675: /* A delayed-branch sequence */ ! 1676: register int i; ! 1677: rtx next; ! 1678: ! 1679: if (prescan > 0) ! 1680: break; ! 1681: final_sequence = body; ! 1682: ! 1683: /* The first insn in this SEQUENCE might be a JUMP_INSN that will ! 1684: force the restoration of a comparison that was previously ! 1685: thought unnecessary. If that happens, cancel this sequence ! 1686: and cause that insn to be restored. */ ! 1687: ! 1688: next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1); ! 1689: if (next != XVECEXP (body, 0, 1)) ! 1690: { ! 1691: final_sequence = 0; ! 1692: return next; ! 1693: } ! 1694: ! 1695: for (i = 1; i < XVECLEN (body, 0); i++) ! 1696: final_scan_insn (XVECEXP (body, 0, i), file, 0, prescan, 1); ! 1697: #ifdef DBR_OUTPUT_SEQEND ! 1698: DBR_OUTPUT_SEQEND (file); ! 1699: #endif ! 1700: final_sequence = 0; ! 1701: ! 1702: /* If the insn requiring the delay slot was a CALL_INSN, the ! 1703: insns in the delay slot are actually executed before the ! 1704: called function. Hence we don't preserve any CC-setting ! 1705: actions in these insns and the CC must be marked as being ! 1706: clobbered by the function. */ ! 1707: if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN) ! 1708: CC_STATUS_INIT; ! 1709: ! 1710: /* Following a conditional branch sequence, we have a new basic ! 1711: block. */ ! 1712: if (profile_block_flag) ! 1713: { ! 1714: rtx insn = XVECEXP (body, 0, 0); ! 1715: rtx body = PATTERN (insn); ! 1716: ! 1717: if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET ! 1718: && GET_CODE (SET_SRC (body)) != LABEL_REF) ! 1719: || (GET_CODE (insn) == JUMP_INSN ! 1720: && GET_CODE (body) == PARALLEL ! 1721: && GET_CODE (XVECEXP (body, 0, 0)) == SET ! 1722: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF)) ! 1723: new_block = 1; ! 1724: } ! 1725: break; ! 1726: } ! 1727: ! 1728: /* We have a real machine instruction as rtl. */ ! 1729: ! 1730: body = PATTERN (insn); ! 1731: ! 1732: #ifdef HAVE_cc0 ! 1733: /* Check for redundant test and compare instructions ! 1734: (when the condition codes are already set up as desired). ! 1735: This is done only when optimizing; if not optimizing, ! 1736: it should be possible for the user to alter a variable ! 1737: with the debugger in between statements ! 1738: and the next statement should reexamine the variable ! 1739: to compute the condition codes. */ ! 1740: ! 1741: if (optimize ! 1742: && GET_CODE (body) == SET ! 1743: && GET_CODE (SET_DEST (body)) == CC0 ! 1744: && insn != last_ignored_compare) ! 1745: { ! 1746: if (GET_CODE (SET_SRC (body)) == SUBREG) ! 1747: SET_SRC (body) = alter_subreg (SET_SRC (body)); ! 1748: else if (GET_CODE (SET_SRC (body)) == COMPARE) ! 1749: { ! 1750: if (GET_CODE (XEXP (SET_SRC (body), 0)) == SUBREG) ! 1751: XEXP (SET_SRC (body), 0) ! 1752: = alter_subreg (XEXP (SET_SRC (body), 0)); ! 1753: if (GET_CODE (XEXP (SET_SRC (body), 1)) == SUBREG) ! 1754: XEXP (SET_SRC (body), 1) ! 1755: = alter_subreg (XEXP (SET_SRC (body), 1)); ! 1756: } ! 1757: if ((cc_status.value1 != 0 ! 1758: && rtx_equal_p (SET_SRC (body), cc_status.value1)) ! 1759: || (cc_status.value2 != 0 ! 1760: && rtx_equal_p (SET_SRC (body), cc_status.value2))) ! 1761: { ! 1762: /* Don't delete insn if it has an addressing side-effect. */ ! 1763: if (! FIND_REG_INC_NOTE (insn, 0) ! 1764: /* or if anything in it is volatile. */ ! 1765: && ! volatile_refs_p (PATTERN (insn))) ! 1766: { ! 1767: /* We don't really delete the insn; just ignore it. */ ! 1768: last_ignored_compare = insn; ! 1769: break; ! 1770: } ! 1771: } ! 1772: } ! 1773: #endif ! 1774: ! 1775: /* Following a conditional branch, we have a new basic block. ! 1776: But if we are inside a sequence, the new block starts after the ! 1777: last insn of the sequence. */ ! 1778: if (profile_block_flag && final_sequence == 0 ! 1779: && ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET ! 1780: && GET_CODE (SET_SRC (body)) != LABEL_REF) ! 1781: || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL ! 1782: && GET_CODE (XVECEXP (body, 0, 0)) == SET ! 1783: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))) ! 1784: new_block = 1; ! 1785: ! 1786: #ifndef STACK_REGS ! 1787: /* Don't bother outputting obvious no-ops, even without -O. ! 1788: This optimization is fast and doesn't interfere with debugging. ! 1789: Don't do this if the insn is in a delay slot, since this ! 1790: will cause an improper number of delay insns to be written. */ ! 1791: if (final_sequence == 0 ! 1792: && prescan >= 0 ! 1793: && GET_CODE (insn) == INSN && GET_CODE (body) == SET ! 1794: && GET_CODE (SET_SRC (body)) == REG ! 1795: && GET_CODE (SET_DEST (body)) == REG ! 1796: && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body))) ! 1797: break; ! 1798: #endif ! 1799: ! 1800: #ifdef HAVE_cc0 ! 1801: /* If this is a conditional branch, maybe modify it ! 1802: if the cc's are in a nonstandard state ! 1803: so that it accomplishes the same thing that it would ! 1804: do straightforwardly if the cc's were set up normally. */ ! 1805: ! 1806: if (cc_status.flags != 0 ! 1807: && GET_CODE (insn) == JUMP_INSN ! 1808: && GET_CODE (body) == SET ! 1809: && SET_DEST (body) == pc_rtx ! 1810: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE ! 1811: /* This is done during prescan; it is not done again ! 1812: in final scan when prescan has been done. */ ! 1813: && prescan >= 0) ! 1814: { ! 1815: /* This function may alter the contents of its argument ! 1816: and clear some of the cc_status.flags bits. ! 1817: It may also return 1 meaning condition now always true ! 1818: or -1 meaning condition now always false ! 1819: or 2 meaning condition nontrivial but altered. */ ! 1820: register int result = alter_cond (XEXP (SET_SRC (body), 0)); ! 1821: /* If condition now has fixed value, replace the IF_THEN_ELSE ! 1822: with its then-operand or its else-operand. */ ! 1823: if (result == 1) ! 1824: SET_SRC (body) = XEXP (SET_SRC (body), 1); ! 1825: if (result == -1) ! 1826: SET_SRC (body) = XEXP (SET_SRC (body), 2); ! 1827: ! 1828: /* The jump is now either unconditional or a no-op. ! 1829: If it has become a no-op, don't try to output it. ! 1830: (It would not be recognized.) */ ! 1831: if (SET_SRC (body) == pc_rtx) ! 1832: { ! 1833: PUT_CODE (insn, NOTE); ! 1834: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; ! 1835: NOTE_SOURCE_FILE (insn) = 0; ! 1836: break; ! 1837: } ! 1838: else if (GET_CODE (SET_SRC (body)) == RETURN) ! 1839: /* Replace (set (pc) (return)) with (return). */ ! 1840: PATTERN (insn) = body = SET_SRC (body); ! 1841: ! 1842: /* Rerecognize the instruction if it has changed. */ ! 1843: if (result != 0) ! 1844: INSN_CODE (insn) = -1; ! 1845: } ! 1846: ! 1847: /* Make same adjustments to instructions that examine the ! 1848: condition codes without jumping (if this machine has them). */ ! 1849: ! 1850: if (cc_status.flags != 0 ! 1851: && GET_CODE (body) == SET) ! 1852: { ! 1853: switch (GET_CODE (SET_SRC (body))) ! 1854: { ! 1855: case GTU: ! 1856: case GT: ! 1857: case LTU: ! 1858: case LT: ! 1859: case GEU: ! 1860: case GE: ! 1861: case LEU: ! 1862: case LE: ! 1863: case EQ: ! 1864: case NE: ! 1865: { ! 1866: register int result; ! 1867: if (XEXP (SET_SRC (body), 0) != cc0_rtx) ! 1868: break; ! 1869: result = alter_cond (SET_SRC (body)); ! 1870: if (result == 1) ! 1871: validate_change (insn, &SET_SRC (body), const_true_rtx, 0); ! 1872: else if (result == -1) ! 1873: validate_change (insn, &SET_SRC (body), const0_rtx, 0); ! 1874: else if (result == 2) ! 1875: INSN_CODE (insn) = -1; ! 1876: } ! 1877: } ! 1878: } ! 1879: #endif ! 1880: ! 1881: /* Do machine-specific peephole optimizations if desired. */ ! 1882: ! 1883: if (optimize && !flag_no_peephole && !nopeepholes) ! 1884: { ! 1885: rtx next = peephole (insn); ! 1886: /* When peepholing, if there were notes within the peephole, ! 1887: emit them before the peephole. */ ! 1888: if (next != 0 && next != NEXT_INSN (insn)) ! 1889: { ! 1890: rtx prev = PREV_INSN (insn); ! 1891: rtx note; ! 1892: ! 1893: for (note = NEXT_INSN (insn); note != next; ! 1894: note = NEXT_INSN (note)) ! 1895: final_scan_insn (note, file, optimize, prescan, nopeepholes); ! 1896: ! 1897: /* In case this is prescan, put the notes ! 1898: in proper position for later rescan. */ ! 1899: note = NEXT_INSN (insn); ! 1900: PREV_INSN (note) = prev; ! 1901: NEXT_INSN (prev) = note; ! 1902: NEXT_INSN (PREV_INSN (next)) = insn; ! 1903: PREV_INSN (insn) = PREV_INSN (next); ! 1904: NEXT_INSN (insn) = next; ! 1905: PREV_INSN (next) = insn; ! 1906: } ! 1907: ! 1908: /* PEEPHOLE might have changed this. */ ! 1909: body = PATTERN (insn); ! 1910: } ! 1911: ! 1912: /* Try to recognize the instruction. ! 1913: If successful, verify that the operands satisfy the ! 1914: constraints for the instruction. Crash if they don't, ! 1915: since `reload' should have changed them so that they do. */ ! 1916: ! 1917: insn_code_number = recog_memoized (insn); ! 1918: insn_extract (insn); ! 1919: for (i = 0; i < insn_n_operands[insn_code_number]; i++) ! 1920: { ! 1921: if (GET_CODE (recog_operand[i]) == SUBREG) ! 1922: recog_operand[i] = alter_subreg (recog_operand[i]); ! 1923: else if (GET_CODE (recog_operand[i]) == PLUS ! 1924: || GET_CODE (recog_operand[i]) == MULT) ! 1925: recog_operand[i] = walk_alter_subreg (recog_operand[i]); ! 1926: } ! 1927: ! 1928: for (i = 0; i < insn_n_dups[insn_code_number]; i++) ! 1929: { ! 1930: if (GET_CODE (*recog_dup_loc[i]) == SUBREG) ! 1931: *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]); ! 1932: else if (GET_CODE (*recog_dup_loc[i]) == PLUS ! 1933: || GET_CODE (*recog_dup_loc[i]) == MULT) ! 1934: *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]); ! 1935: } ! 1936: ! 1937: #ifdef REGISTER_CONSTRAINTS ! 1938: if (! constrain_operands (insn_code_number, 1)) ! 1939: fatal_insn_not_found (insn); ! 1940: #endif ! 1941: ! 1942: /* Some target machines need to prescan each insn before ! 1943: it is output. */ ! 1944: ! 1945: #ifdef FINAL_PRESCAN_INSN ! 1946: FINAL_PRESCAN_INSN (insn, recog_operand, ! 1947: insn_n_operands[insn_code_number]); ! 1948: #endif ! 1949: ! 1950: #ifdef HAVE_cc0 ! 1951: cc_prev_status = cc_status; ! 1952: ! 1953: /* Update `cc_status' for this instruction. ! 1954: The instruction's output routine may change it further. ! 1955: If the output routine for a jump insn needs to depend ! 1956: on the cc status, it should look at cc_prev_status. */ ! 1957: ! 1958: NOTICE_UPDATE_CC (body, insn); ! 1959: #endif ! 1960: ! 1961: debug_insn = insn; ! 1962: ! 1963: /* If the proper template needs to be chosen by some C code, ! 1964: run that code and get the real template. */ ! 1965: ! 1966: template = insn_template[insn_code_number]; ! 1967: if (template == 0) ! 1968: { ! 1969: template = (*insn_outfun[insn_code_number]) (recog_operand, insn); ! 1970: ! 1971: /* If the C code returns 0, it means that it is a jump insn ! 1972: which follows a deleted test insn, and that test insn ! 1973: needs to be reinserted. */ ! 1974: if (template == 0) ! 1975: { ! 1976: if (prev_nonnote_insn (insn) != last_ignored_compare) ! 1977: abort (); ! 1978: new_block = 0; ! 1979: return prev_nonnote_insn (insn); ! 1980: } ! 1981: } ! 1982: ! 1983: /* If the template is the string "#", it means that this insn must ! 1984: be split. */ ! 1985: if (template[0] == '#' && template[1] == '\0') ! 1986: { ! 1987: rtx new = try_split (body, insn, 0); ! 1988: ! 1989: /* If we didn't split the insn, go away. */ ! 1990: if (new == insn && PATTERN (new) == body) ! 1991: abort (); ! 1992: ! 1993: new_block = 0; ! 1994: return new; ! 1995: } ! 1996: ! 1997: if (prescan > 0) ! 1998: break; ! 1999: ! 2000: /* Output assembler code from the template. */ ! 2001: ! 2002: output_asm_insn (template, recog_operand); ! 2003: ! 2004: #if 0 ! 2005: /* It's not at all clear why we did this and doing so interferes ! 2006: with tests we'd like to do to use REG_WAS_0 notes, so let's try ! 2007: with this out. */ ! 2008: ! 2009: /* Mark this insn as having been output. */ ! 2010: INSN_DELETED_P (insn) = 1; ! 2011: #endif ! 2012: ! 2013: debug_insn = 0; ! 2014: } ! 2015: } ! 2016: return NEXT_INSN (insn); ! 2017: } ! 2018: ! 2019: /* Output debugging info to the assembler file FILE ! 2020: based on the NOTE-insn INSN, assumed to be a line number. */ ! 2021: ! 2022: static void ! 2023: output_source_line (file, insn) ! 2024: FILE *file; ! 2025: rtx insn; ! 2026: { ! 2027: char ltext_label_name[100]; ! 2028: register char *filename = NOTE_SOURCE_FILE (insn); ! 2029: ! 2030: /* Remember filename for basic block profiling. ! 2031: Filenames are allocated on the permanent obstack ! 2032: or are passed in ARGV, so we don't have to save ! 2033: the string. */ ! 2034: ! 2035: if (profile_block_flag && last_filename != filename) ! 2036: bb_file_label_num = add_bb_string (filename, TRUE); ! 2037: ! 2038: last_filename = filename; ! 2039: last_linenum = NOTE_LINE_NUMBER (insn); ! 2040: ! 2041: if (write_symbols != NO_DEBUG) ! 2042: { ! 2043: #ifdef SDB_DEBUGGING_INFO ! 2044: if (write_symbols == SDB_DEBUG ! 2045: #if 0 /* People like having line numbers even in wrong file! */ ! 2046: /* COFF can't handle multiple source files--lose, lose. */ ! 2047: && !strcmp (filename, main_input_filename) ! 2048: #endif ! 2049: /* COFF relative line numbers must be positive. */ ! 2050: && last_linenum > sdb_begin_function_line) ! 2051: { ! 2052: #ifdef ASM_OUTPUT_SOURCE_LINE ! 2053: ASM_OUTPUT_SOURCE_LINE (file, last_linenum); ! 2054: #else ! 2055: fprintf (file, "\t.ln\t%d\n", ! 2056: ((sdb_begin_function_line > -1) ! 2057: ? last_linenum - sdb_begin_function_line : 1)); ! 2058: #endif ! 2059: } ! 2060: #endif ! 2061: ! 2062: #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) ! 2063: if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) ! 2064: dbxout_source_line (file, filename, NOTE_LINE_NUMBER (insn)); ! 2065: #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ ! 2066: ! 2067: #ifdef DWARF_DEBUGGING_INFO ! 2068: if (write_symbols == DWARF_DEBUG) ! 2069: dwarfout_line (filename, NOTE_LINE_NUMBER (insn)); ! 2070: #endif ! 2071: } ! 2072: } ! 2073: ! 2074: /* If X is a SUBREG, replace it with a REG or a MEM, ! 2075: based on the thing it is a subreg of. */ ! 2076: ! 2077: rtx ! 2078: alter_subreg (x) ! 2079: register rtx x; ! 2080: { ! 2081: register rtx y = SUBREG_REG (x); ! 2082: if (GET_CODE (y) == SUBREG) ! 2083: y = alter_subreg (y); ! 2084: ! 2085: if (GET_CODE (y) == REG) ! 2086: { ! 2087: /* If the containing reg really gets a hard reg, so do we. */ ! 2088: PUT_CODE (x, REG); ! 2089: REGNO (x) = REGNO (y) + SUBREG_WORD (x); ! 2090: } ! 2091: else if (GET_CODE (y) == MEM) ! 2092: { ! 2093: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD; ! 2094: #if BYTES_BIG_ENDIAN ! 2095: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))) ! 2096: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y)))); ! 2097: #endif ! 2098: PUT_CODE (x, MEM); ! 2099: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y); ! 2100: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset); ! 2101: } ! 2102: ! 2103: return x; ! 2104: } ! 2105: ! 2106: /* Do alter_subreg on all the SUBREGs contained in X. */ ! 2107: ! 2108: static rtx ! 2109: walk_alter_subreg (x) ! 2110: rtx x; ! 2111: { ! 2112: switch (GET_CODE (x)) ! 2113: { ! 2114: case PLUS: ! 2115: case MULT: ! 2116: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); ! 2117: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1)); ! 2118: break; ! 2119: ! 2120: case MEM: ! 2121: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); ! 2122: break; ! 2123: ! 2124: case SUBREG: ! 2125: return alter_subreg (x); ! 2126: } ! 2127: ! 2128: return x; ! 2129: } ! 2130: ! 2131: #ifdef HAVE_cc0 ! 2132: ! 2133: /* Given BODY, the body of a jump instruction, alter the jump condition ! 2134: as required by the bits that are set in cc_status.flags. ! 2135: Not all of the bits there can be handled at this level in all cases. ! 2136: ! 2137: The value is normally 0. ! 2138: 1 means that the condition has become always true. ! 2139: -1 means that the condition has become always false. ! 2140: 2 means that COND has been altered. */ ! 2141: ! 2142: static int ! 2143: alter_cond (cond) ! 2144: register rtx cond; ! 2145: { ! 2146: int value = 0; ! 2147: ! 2148: if (cc_status.flags & CC_REVERSED) ! 2149: { ! 2150: value = 2; ! 2151: PUT_CODE (cond, swap_condition (GET_CODE (cond))); ! 2152: } ! 2153: ! 2154: if (cc_status.flags & CC_INVERTED) ! 2155: { ! 2156: value = 2; ! 2157: PUT_CODE (cond, reverse_condition (GET_CODE (cond))); ! 2158: } ! 2159: ! 2160: if (cc_status.flags & CC_NOT_POSITIVE) ! 2161: switch (GET_CODE (cond)) ! 2162: { ! 2163: case LE: ! 2164: case LEU: ! 2165: case GEU: ! 2166: /* Jump becomes unconditional. */ ! 2167: return 1; ! 2168: ! 2169: case GT: ! 2170: case GTU: ! 2171: case LTU: ! 2172: /* Jump becomes no-op. */ ! 2173: return -1; ! 2174: ! 2175: case GE: ! 2176: PUT_CODE (cond, EQ); ! 2177: value = 2; ! 2178: break; ! 2179: ! 2180: case LT: ! 2181: PUT_CODE (cond, NE); ! 2182: value = 2; ! 2183: break; ! 2184: } ! 2185: ! 2186: if (cc_status.flags & CC_NOT_NEGATIVE) ! 2187: switch (GET_CODE (cond)) ! 2188: { ! 2189: case GE: ! 2190: case GEU: ! 2191: /* Jump becomes unconditional. */ ! 2192: return 1; ! 2193: ! 2194: case LT: ! 2195: case LTU: ! 2196: /* Jump becomes no-op. */ ! 2197: return -1; ! 2198: ! 2199: case LE: ! 2200: case LEU: ! 2201: PUT_CODE (cond, EQ); ! 2202: value = 2; ! 2203: break; ! 2204: ! 2205: case GT: ! 2206: case GTU: ! 2207: PUT_CODE (cond, NE); ! 2208: value = 2; ! 2209: break; ! 2210: } ! 2211: ! 2212: if (cc_status.flags & CC_NO_OVERFLOW) ! 2213: switch (GET_CODE (cond)) ! 2214: { ! 2215: case GEU: ! 2216: /* Jump becomes unconditional. */ ! 2217: return 1; ! 2218: ! 2219: case LEU: ! 2220: PUT_CODE (cond, EQ); ! 2221: value = 2; ! 2222: break; ! 2223: ! 2224: case GTU: ! 2225: PUT_CODE (cond, NE); ! 2226: value = 2; ! 2227: break; ! 2228: ! 2229: case LTU: ! 2230: /* Jump becomes no-op. */ ! 2231: return -1; ! 2232: } ! 2233: ! 2234: if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N)) ! 2235: switch (GET_CODE (cond)) ! 2236: { ! 2237: case LE: ! 2238: case LEU: ! 2239: case GE: ! 2240: case GEU: ! 2241: case LT: ! 2242: case LTU: ! 2243: case GT: ! 2244: case GTU: ! 2245: abort (); ! 2246: ! 2247: case NE: ! 2248: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT); ! 2249: value = 2; ! 2250: break; ! 2251: ! 2252: case EQ: ! 2253: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE); ! 2254: value = 2; ! 2255: break; ! 2256: } ! 2257: ! 2258: if (cc_status.flags & CC_NOT_SIGNED) ! 2259: /* The flags are valid if signed condition operators are converted ! 2260: to unsigned. */ ! 2261: switch (GET_CODE (cond)) ! 2262: { ! 2263: case LE: ! 2264: PUT_CODE (cond, LEU); ! 2265: value = 2; ! 2266: break; ! 2267: ! 2268: case LT: ! 2269: PUT_CODE (cond, LTU); ! 2270: value = 2; ! 2271: break; ! 2272: ! 2273: case GT: ! 2274: PUT_CODE (cond, GTU); ! 2275: value = 2; ! 2276: break; ! 2277: ! 2278: case GE: ! 2279: PUT_CODE (cond, GEU); ! 2280: value = 2; ! 2281: break; ! 2282: } ! 2283: ! 2284: return value; ! 2285: } ! 2286: #endif ! 2287: ! 2288: /* Report inconsistency between the assembler template and the operands. ! 2289: In an `asm', it's the user's fault; otherwise, the compiler's fault. */ ! 2290: ! 2291: void ! 2292: output_operand_lossage (str) ! 2293: char *str; ! 2294: { ! 2295: if (this_is_asm_operands) ! 2296: error_for_asm (this_is_asm_operands, "invalid `asm': %s", str); ! 2297: else ! 2298: abort (); ! 2299: } ! 2300: ! 2301: /* Output of assembler code from a template, and its subroutines. */ ! 2302: ! 2303: /* Output text from TEMPLATE to the assembler output file, ! 2304: obeying %-directions to substitute operands taken from ! 2305: the vector OPERANDS. ! 2306: ! 2307: %N (for N a digit) means print operand N in usual manner. ! 2308: %lN means require operand N to be a CODE_LABEL or LABEL_REF ! 2309: and print the label name with no punctuation. ! 2310: %cN means require operand N to be a constant ! 2311: and print the constant expression with no punctuation. ! 2312: %aN means expect operand N to be a memory address ! 2313: (not a memory reference!) and print a reference ! 2314: to that address. ! 2315: %nN means expect operand N to be a constant ! 2316: and print a constant expression for minus the value ! 2317: of the operand, with no other punctuation. */ ! 2318: ! 2319: void ! 2320: output_asm_insn (template, operands) ! 2321: char *template; ! 2322: rtx *operands; ! 2323: { ! 2324: register char *p; ! 2325: register int c, i; ! 2326: ! 2327: /* An insn may return a null string template ! 2328: in a case where no assembler code is needed. */ ! 2329: if (*template == 0) ! 2330: return; ! 2331: ! 2332: p = template; ! 2333: putc ('\t', asm_out_file); ! 2334: ! 2335: #ifdef ASM_OUTPUT_OPCODE ! 2336: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 2337: #endif ! 2338: ! 2339: while (c = *p++) ! 2340: switch (c) ! 2341: { ! 2342: #ifdef ASM_OUTPUT_OPCODE ! 2343: case '\n': ! 2344: putc (c, asm_out_file); ! 2345: while ((c = *p) == '\t') ! 2346: { ! 2347: putc (c, asm_out_file); ! 2348: p++; ! 2349: } ! 2350: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 2351: break; ! 2352: #endif ! 2353: ! 2354: #ifdef ASSEMBLER_DIALECT ! 2355: case '{': ! 2356: /* If we want the first dialect, do nothing. Otherwise, skip ! 2357: DIALECT_NUMBER of strings ending with '|'. */ ! 2358: for (i = 0; i < dialect_number; i++) ! 2359: { ! 2360: while (*p && *p++ != '|') ! 2361: ; ! 2362: ! 2363: if (*p == '|') ! 2364: p++; ! 2365: } ! 2366: break; ! 2367: ! 2368: case '|': ! 2369: /* Skip to close brace. */ ! 2370: while (*p && *p++ != '}') ! 2371: ; ! 2372: break; ! 2373: ! 2374: case '}': ! 2375: break; ! 2376: #endif ! 2377: ! 2378: case '%': ! 2379: /* %% outputs a single %. */ ! 2380: if (*p == '%') ! 2381: { ! 2382: p++; ! 2383: putc (c, asm_out_file); ! 2384: } ! 2385: /* %= outputs a number which is unique to each insn in the entire ! 2386: compilation. This is useful for making local labels that are ! 2387: referred to more than once in a given insn. */ ! 2388: else if (*p == '=') ! 2389: { ! 2390: p++; ! 2391: fprintf (asm_out_file, "%d", insn_counter); ! 2392: } ! 2393: /* % followed by a letter and some digits ! 2394: outputs an operand in a special way depending on the letter. ! 2395: Letters `acln' are implemented directly. ! 2396: Other letters are passed to `output_operand' so that ! 2397: the PRINT_OPERAND macro can define them. */ ! 2398: else if ((*p >= 'a' && *p <= 'z') ! 2399: || (*p >= 'A' && *p <= 'Z')) ! 2400: { ! 2401: int letter = *p++; ! 2402: c = atoi (p); ! 2403: ! 2404: if (! (*p >= '0' && *p <= '9')) ! 2405: output_operand_lossage ("operand number missing after %-letter"); ! 2406: else if (this_is_asm_operands && c >= (unsigned) insn_noperands) ! 2407: output_operand_lossage ("operand number out of range"); ! 2408: else if (letter == 'l') ! 2409: output_asm_label (operands[c]); ! 2410: else if (letter == 'a') ! 2411: output_address (operands[c]); ! 2412: else if (letter == 'c') ! 2413: { ! 2414: if (CONSTANT_ADDRESS_P (operands[c])) ! 2415: output_addr_const (asm_out_file, operands[c]); ! 2416: else ! 2417: output_operand (operands[c], 'c'); ! 2418: } ! 2419: else if (letter == 'n') ! 2420: { ! 2421: if (GET_CODE (operands[c]) == CONST_INT) ! 2422: fprintf (asm_out_file, ! 2423: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! 2424: "%d", ! 2425: #else ! 2426: "%ld", ! 2427: #endif ! 2428: - INTVAL (operands[c])); ! 2429: else ! 2430: { ! 2431: putc ('-', asm_out_file); ! 2432: output_addr_const (asm_out_file, operands[c]); ! 2433: } ! 2434: } ! 2435: else ! 2436: output_operand (operands[c], letter); ! 2437: ! 2438: while ((c = *p) >= '0' && c <= '9') p++; ! 2439: } ! 2440: /* % followed by a digit outputs an operand the default way. */ ! 2441: else if (*p >= '0' && *p <= '9') ! 2442: { ! 2443: c = atoi (p); ! 2444: if (this_is_asm_operands && c >= (unsigned) insn_noperands) ! 2445: output_operand_lossage ("operand number out of range"); ! 2446: else ! 2447: output_operand (operands[c], 0); ! 2448: while ((c = *p) >= '0' && c <= '9') p++; ! 2449: } ! 2450: /* % followed by punctuation: output something for that ! 2451: punctuation character alone, with no operand. ! 2452: The PRINT_OPERAND macro decides what is actually done. */ ! 2453: #ifdef PRINT_OPERAND_PUNCT_VALID_P ! 2454: else if (PRINT_OPERAND_PUNCT_VALID_P (*p)) ! 2455: output_operand (NULL_RTX, *p++); ! 2456: #endif ! 2457: else ! 2458: output_operand_lossage ("invalid %%-code"); ! 2459: break; ! 2460: ! 2461: default: ! 2462: putc (c, asm_out_file); ! 2463: } ! 2464: ! 2465: if (flag_print_asm_name) ! 2466: { ! 2467: /* Annotate the assembly with a comment describing the pattern and ! 2468: alternative used. */ ! 2469: if (debug_insn) ! 2470: { ! 2471: register int num = INSN_CODE (debug_insn); ! 2472: fprintf (asm_out_file, " %s %d %s", ! 2473: ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]); ! 2474: if (insn_n_alternatives[num] > 1) ! 2475: fprintf (asm_out_file, "/%d", which_alternative + 1); ! 2476: ! 2477: /* Clear this so only the first assembler insn ! 2478: of any rtl insn will get the special comment for -dp. */ ! 2479: debug_insn = 0; ! 2480: } ! 2481: } ! 2482: ! 2483: putc ('\n', asm_out_file); ! 2484: } ! 2485: ! 2486: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ ! 2487: ! 2488: void ! 2489: output_asm_label (x) ! 2490: rtx x; ! 2491: { ! 2492: char buf[256]; ! 2493: ! 2494: if (GET_CODE (x) == LABEL_REF) ! 2495: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); ! 2496: else if (GET_CODE (x) == CODE_LABEL) ! 2497: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); ! 2498: else ! 2499: output_operand_lossage ("`%l' operand isn't a label"); ! 2500: ! 2501: assemble_name (asm_out_file, buf); ! 2502: } ! 2503: ! 2504: /* Print operand X using machine-dependent assembler syntax. ! 2505: The macro PRINT_OPERAND is defined just to control this function. ! 2506: CODE is a non-digit that preceded the operand-number in the % spec, ! 2507: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char ! 2508: between the % and the digits. ! 2509: When CODE is a non-letter, X is 0. ! 2510: ! 2511: The meanings of the letters are machine-dependent and controlled ! 2512: by PRINT_OPERAND. */ ! 2513: ! 2514: static void ! 2515: output_operand (x, code) ! 2516: rtx x; ! 2517: int code; ! 2518: { ! 2519: if (x && GET_CODE (x) == SUBREG) ! 2520: x = alter_subreg (x); ! 2521: ! 2522: /* If X is a pseudo-register, abort now rather than writing trash to the ! 2523: assembler file. */ ! 2524: ! 2525: if (x && GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER) ! 2526: abort (); ! 2527: ! 2528: PRINT_OPERAND (asm_out_file, x, code); ! 2529: } ! 2530: ! 2531: /* Print a memory reference operand for address X ! 2532: using machine-dependent assembler syntax. ! 2533: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */ ! 2534: ! 2535: void ! 2536: output_address (x) ! 2537: rtx x; ! 2538: { ! 2539: walk_alter_subreg (x); ! 2540: PRINT_OPERAND_ADDRESS (asm_out_file, x); ! 2541: } ! 2542: ! 2543: /* Print an integer constant expression in assembler syntax. ! 2544: Addition and subtraction are the only arithmetic ! 2545: that may appear in these expressions. */ ! 2546: ! 2547: void ! 2548: output_addr_const (file, x) ! 2549: FILE *file; ! 2550: rtx x; ! 2551: { ! 2552: char buf[256]; ! 2553: ! 2554: restart: ! 2555: switch (GET_CODE (x)) ! 2556: { ! 2557: case PC: ! 2558: if (flag_pic) ! 2559: putc ('.', file); ! 2560: else ! 2561: abort (); ! 2562: break; ! 2563: ! 2564: case SYMBOL_REF: ! 2565: assemble_name (file, XSTR (x, 0)); ! 2566: break; ! 2567: ! 2568: case LABEL_REF: ! 2569: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); ! 2570: assemble_name (file, buf); ! 2571: break; ! 2572: ! 2573: case CODE_LABEL: ! 2574: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); ! 2575: assemble_name (file, buf); ! 2576: break; ! 2577: ! 2578: case CONST_INT: ! 2579: fprintf (file, ! 2580: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! 2581: "%d", ! 2582: #else ! 2583: "%ld", ! 2584: #endif ! 2585: INTVAL (x)); ! 2586: break; ! 2587: ! 2588: case CONST: ! 2589: /* This used to output parentheses around the expression, ! 2590: but that does not work on the 386 (either ATT or BSD assembler). */ ! 2591: output_addr_const (file, XEXP (x, 0)); ! 2592: break; ! 2593: ! 2594: case CONST_DOUBLE: ! 2595: if (GET_MODE (x) == VOIDmode) ! 2596: { ! 2597: /* We can use %d if the number is one word and positive. */ ! 2598: if (CONST_DOUBLE_HIGH (x)) ! 2599: fprintf (file, ! 2600: #if HOST_BITS_PER_WIDE_INT == 64 ! 2601: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! 2602: "0x%lx%016lx", ! 2603: #else ! 2604: "0x%x%016x", ! 2605: #endif ! 2606: #else ! 2607: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! 2608: "0x%lx%08lx", ! 2609: #else ! 2610: "0x%x%08x", ! 2611: #endif ! 2612: #endif ! 2613: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); ! 2614: else if (CONST_DOUBLE_LOW (x) < 0) ! 2615: fprintf (file, ! 2616: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! 2617: "0x%x", ! 2618: #else ! 2619: "0x%lx", ! 2620: #endif ! 2621: CONST_DOUBLE_LOW (x)); ! 2622: else ! 2623: fprintf (file, ! 2624: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! 2625: "%d", ! 2626: #else ! 2627: "%ld", ! 2628: #endif ! 2629: CONST_DOUBLE_LOW (x)); ! 2630: } ! 2631: else ! 2632: /* We can't handle floating point constants; ! 2633: PRINT_OPERAND must handle them. */ ! 2634: output_operand_lossage ("floating constant misused"); ! 2635: break; ! 2636: ! 2637: case PLUS: ! 2638: /* Some assemblers need integer constants to appear last (eg masm). */ ! 2639: if (GET_CODE (XEXP (x, 0)) == CONST_INT) ! 2640: { ! 2641: output_addr_const (file, XEXP (x, 1)); ! 2642: if (INTVAL (XEXP (x, 0)) >= 0) ! 2643: fprintf (file, "+"); ! 2644: output_addr_const (file, XEXP (x, 0)); ! 2645: } ! 2646: else ! 2647: { ! 2648: output_addr_const (file, XEXP (x, 0)); ! 2649: if (INTVAL (XEXP (x, 1)) >= 0) ! 2650: fprintf (file, "+"); ! 2651: output_addr_const (file, XEXP (x, 1)); ! 2652: } ! 2653: break; ! 2654: ! 2655: case MINUS: ! 2656: /* Avoid outputting things like x-x or x+5-x, ! 2657: since some assemblers can't handle that. */ ! 2658: x = simplify_subtraction (x); ! 2659: if (GET_CODE (x) != MINUS) ! 2660: goto restart; ! 2661: ! 2662: output_addr_const (file, XEXP (x, 0)); ! 2663: fprintf (file, "-"); ! 2664: if (GET_CODE (XEXP (x, 1)) == CONST_INT ! 2665: && INTVAL (XEXP (x, 1)) < 0) ! 2666: { ! 2667: fprintf (file, ASM_OPEN_PAREN); ! 2668: output_addr_const (file, XEXP (x, 1)); ! 2669: fprintf (file, ASM_CLOSE_PAREN); ! 2670: } ! 2671: else ! 2672: output_addr_const (file, XEXP (x, 1)); ! 2673: break; ! 2674: ! 2675: case ZERO_EXTEND: ! 2676: case SIGN_EXTEND: ! 2677: output_addr_const (file, XEXP (x, 0)); ! 2678: break; ! 2679: ! 2680: default: ! 2681: output_operand_lossage ("invalid expression as operand"); ! 2682: } ! 2683: } ! 2684: ! 2685: /* A poor man's fprintf, with the added features of %I, %R, %L, and %U. ! 2686: %R prints the value of REGISTER_PREFIX. ! 2687: %L prints the value of LOCAL_LABEL_PREFIX. ! 2688: %U prints the value of USER_LABEL_PREFIX. ! 2689: %I prints the value of IMMEDIATE_PREFIX. ! 2690: %O runs ASM_OUTPUT_OPCODE to transform what follows in the string. ! 2691: Also supported are %d, %x, %s, %e, %f, %g and %%. ! 2692: ! 2693: We handle alternate assembler dialects here, just like output_asm_insn. */ ! 2694: ! 2695: void ! 2696: asm_fprintf (va_alist) ! 2697: va_dcl ! 2698: { ! 2699: va_list argptr; ! 2700: FILE *file; ! 2701: char buf[10]; ! 2702: char *p, *q, c; ! 2703: int i; ! 2704: ! 2705: va_start (argptr); ! 2706: ! 2707: file = va_arg (argptr, FILE *); ! 2708: p = va_arg (argptr, char *); ! 2709: buf[0] = '%'; ! 2710: ! 2711: while (c = *p++) ! 2712: switch (c) ! 2713: { ! 2714: #ifdef ASSEMBLER_DIALECT ! 2715: case '{': ! 2716: /* If we want the first dialect, do nothing. Otherwise, skip ! 2717: DIALECT_NUMBER of strings ending with '|'. */ ! 2718: for (i = 0; i < dialect_number; i++) ! 2719: { ! 2720: while (*p && *p++ != '|') ! 2721: ; ! 2722: ! 2723: if (*p == '|') ! 2724: p++; ! 2725: } ! 2726: break; ! 2727: ! 2728: case '|': ! 2729: /* Skip to close brace. */ ! 2730: while (*p && *p++ != '}') ! 2731: ; ! 2732: break; ! 2733: ! 2734: case '}': ! 2735: break; ! 2736: #endif ! 2737: ! 2738: case '%': ! 2739: c = *p++; ! 2740: q = &buf[1]; ! 2741: while ((c >= '0' && c <= '9') || c == '.') ! 2742: { ! 2743: *q++ = c; ! 2744: c = *p++; ! 2745: } ! 2746: switch (c) ! 2747: { ! 2748: case '%': ! 2749: fprintf (file, "%%"); ! 2750: break; ! 2751: ! 2752: case 'd': case 'i': case 'u': ! 2753: case 'x': case 'p': case 'X': ! 2754: case 'o': ! 2755: *q++ = c; ! 2756: *q = 0; ! 2757: fprintf (file, buf, va_arg (argptr, int)); ! 2758: break; ! 2759: ! 2760: case 'w': ! 2761: /* This is a prefix to the 'd', 'i', 'u', 'x', 'p', and 'X' cases, ! 2762: but we do not check for those cases. It means that the value ! 2763: is a HOST_WIDE_INT, which may be either `int' or `long'. */ ! 2764: ! 2765: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! 2766: *q++ = 'l'; ! 2767: #endif ! 2768: ! 2769: *q++ = *p++; ! 2770: *q = 0; ! 2771: fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT)); ! 2772: break; ! 2773: ! 2774: case 'l': ! 2775: *q++ = c; ! 2776: *q++ = *p++; ! 2777: *q = 0; ! 2778: fprintf (file, buf, va_arg (argptr, long)); ! 2779: break; ! 2780: ! 2781: case 'e': ! 2782: case 'f': ! 2783: case 'g': ! 2784: *q++ = c; ! 2785: *q = 0; ! 2786: fprintf (file, buf, va_arg (argptr, double)); ! 2787: break; ! 2788: ! 2789: case 's': ! 2790: *q++ = c; ! 2791: *q = 0; ! 2792: fprintf (file, buf, va_arg (argptr, char *)); ! 2793: break; ! 2794: ! 2795: case 'O': ! 2796: #ifdef ASM_OUTPUT_OPCODE ! 2797: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 2798: #endif ! 2799: break; ! 2800: ! 2801: case 'R': ! 2802: #ifdef REGISTER_PREFIX ! 2803: fprintf (file, "%s", REGISTER_PREFIX); ! 2804: #endif ! 2805: break; ! 2806: ! 2807: case 'I': ! 2808: #ifdef IMMEDIATE_PREFIX ! 2809: fprintf (file, "%s", IMMEDIATE_PREFIX); ! 2810: #endif ! 2811: break; ! 2812: ! 2813: case 'L': ! 2814: #ifdef LOCAL_LABEL_PREFIX ! 2815: fprintf (file, "%s", LOCAL_LABEL_PREFIX); ! 2816: #endif ! 2817: break; ! 2818: ! 2819: case 'U': ! 2820: #ifdef USER_LABEL_PREFIX ! 2821: fprintf (file, "%s", USER_LABEL_PREFIX); ! 2822: #endif ! 2823: break; ! 2824: ! 2825: case 'S': ! 2826: *q++ = c; ! 2827: *q = 0; ! 2828: assemble_name (file, va_arg (argptr, char*)); ! 2829: break; ! 2830: ! 2831: default: ! 2832: abort (); ! 2833: } ! 2834: break; ! 2835: ! 2836: default: ! 2837: fputc (c, file); ! 2838: } ! 2839: } ! 2840: ! 2841: /* Split up a CONST_DOUBLE or integer constant rtx ! 2842: into two rtx's for single words, ! 2843: storing in *FIRST the word that comes first in memory in the target ! 2844: and in *SECOND the other. */ ! 2845: ! 2846: void ! 2847: split_double (value, first, second) ! 2848: rtx value; ! 2849: rtx *first, *second; ! 2850: { ! 2851: if (GET_CODE (value) == CONST_INT) ! 2852: { ! 2853: /* The rule for using CONST_INT for a wider mode ! 2854: is that we regard the value as signed. ! 2855: So sign-extend it. */ ! 2856: rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx); ! 2857: #if WORDS_BIG_ENDIAN ! 2858: *first = high; ! 2859: *second = value; ! 2860: #else ! 2861: *first = value; ! 2862: *second = high; ! 2863: #endif ! 2864: } ! 2865: else if (GET_CODE (value) != CONST_DOUBLE) ! 2866: { ! 2867: #if WORDS_BIG_ENDIAN ! 2868: *first = const0_rtx; ! 2869: *second = value; ! 2870: #else ! 2871: *first = value; ! 2872: *second = const0_rtx; ! 2873: #endif ! 2874: } ! 2875: else if (GET_MODE (value) == VOIDmode ! 2876: /* This is the old way we did CONST_DOUBLE integers. */ ! 2877: || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT) ! 2878: { ! 2879: /* In an integer, the words are defined as most and least significant. ! 2880: So order them by the target's convention. */ ! 2881: #if WORDS_BIG_ENDIAN ! 2882: *first = GEN_INT (CONST_DOUBLE_HIGH (value)); ! 2883: *second = GEN_INT (CONST_DOUBLE_LOW (value)); ! 2884: #else ! 2885: *first = GEN_INT (CONST_DOUBLE_LOW (value)); ! 2886: *second = GEN_INT (CONST_DOUBLE_HIGH (value)); ! 2887: #endif ! 2888: } ! 2889: else ! 2890: { ! 2891: #ifdef REAL_ARITHMETIC ! 2892: REAL_VALUE_TYPE r; HOST_WIDE_INT l[2]; ! 2893: REAL_VALUE_FROM_CONST_DOUBLE (r, value); ! 2894: REAL_VALUE_TO_TARGET_DOUBLE (r, l); ! 2895: *first = GEN_INT (l[0]); ! 2896: *second = GEN_INT (l[1]); ! 2897: #else ! 2898: if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! 2899: || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) ! 2900: && ! flag_pretend_float) ! 2901: abort (); ! 2902: ! 2903: #if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN ! 2904: /* Host and target agree => no need to swap. */ ! 2905: *first = GEN_INT (CONST_DOUBLE_LOW (value)); ! 2906: *second = GEN_INT (CONST_DOUBLE_HIGH (value)); ! 2907: #else ! 2908: *second = GEN_INT (CONST_DOUBLE_LOW (value)); ! 2909: *first = GEN_INT (CONST_DOUBLE_HIGH (value)); ! 2910: #endif ! 2911: #endif /* no REAL_ARITHMETIC */ ! 2912: } ! 2913: } ! 2914: ! 2915: /* Return nonzero if this function has no function calls. */ ! 2916: ! 2917: int ! 2918: leaf_function_p () ! 2919: { ! 2920: rtx insn; ! 2921: ! 2922: if (profile_flag || profile_block_flag) ! 2923: return 0; ! 2924: ! 2925: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) ! 2926: { ! 2927: if (GET_CODE (insn) == CALL_INSN) ! 2928: return 0; ! 2929: if (GET_CODE (insn) == INSN ! 2930: && GET_CODE (PATTERN (insn)) == SEQUENCE ! 2931: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN) ! 2932: return 0; ! 2933: } ! 2934: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) ! 2935: { ! 2936: if (GET_CODE (XEXP (insn, 0)) == CALL_INSN) ! 2937: return 0; ! 2938: if (GET_CODE (XEXP (insn, 0)) == INSN ! 2939: && GET_CODE (PATTERN (XEXP (insn, 0))) == SEQUENCE ! 2940: && GET_CODE (XVECEXP (PATTERN (XEXP (insn, 0)), 0, 0)) == CALL_INSN) ! 2941: return 0; ! 2942: } ! 2943: ! 2944: return 1; ! 2945: } ! 2946: ! 2947: /* On some machines, a function with no call insns ! 2948: can run faster if it doesn't create its own register window. ! 2949: When output, the leaf function should use only the "output" ! 2950: registers. Ordinarily, the function would be compiled to use ! 2951: the "input" registers to find its arguments; it is a candidate ! 2952: for leaf treatment if it uses only the "input" registers. ! 2953: Leaf function treatment means renumbering so the function ! 2954: uses the "output" registers instead. */ ! 2955: ! 2956: #ifdef LEAF_REGISTERS ! 2957: ! 2958: static char permitted_reg_in_leaf_functions[] = LEAF_REGISTERS; ! 2959: ! 2960: /* Return 1 if this function uses only the registers that can be ! 2961: safely renumbered. */ ! 2962: ! 2963: int ! 2964: only_leaf_regs_used () ! 2965: { ! 2966: int i; ! 2967: ! 2968: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 2969: { ! 2970: if ((regs_ever_live[i] || global_regs[i]) ! 2971: && ! permitted_reg_in_leaf_functions[i]) ! 2972: return 0; ! 2973: } ! 2974: return 1; ! 2975: } ! 2976: ! 2977: /* Scan all instructions and renumber all registers into those ! 2978: available in leaf functions. */ ! 2979: ! 2980: static void ! 2981: leaf_renumber_regs (first) ! 2982: rtx first; ! 2983: { ! 2984: rtx insn; ! 2985: ! 2986: /* Renumber only the actual patterns. ! 2987: The reg-notes can contain frame pointer refs, ! 2988: and renumbering them could crash, and should not be needed. */ ! 2989: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 2990: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') ! 2991: leaf_renumber_regs_insn (PATTERN (insn)); ! 2992: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) ! 2993: if (GET_RTX_CLASS (GET_CODE (XEXP (insn, 0))) == 'i') ! 2994: leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0))); ! 2995: } ! 2996: ! 2997: /* Scan IN_RTX and its subexpressions, and renumber all regs into those ! 2998: available in leaf functions. */ ! 2999: ! 3000: void ! 3001: leaf_renumber_regs_insn (in_rtx) ! 3002: register rtx in_rtx; ! 3003: { ! 3004: register int i, j; ! 3005: register char *format_ptr; ! 3006: ! 3007: if (in_rtx == 0) ! 3008: return; ! 3009: ! 3010: /* Renumber all input-registers into output-registers. ! 3011: renumbered_regs would be 1 for an output-register; ! 3012: they */ ! 3013: ! 3014: if (GET_CODE (in_rtx) == REG) ! 3015: { ! 3016: int newreg; ! 3017: ! 3018: /* Don't renumber the same reg twice. */ ! 3019: if (in_rtx->used) ! 3020: return; ! 3021: ! 3022: newreg = REGNO (in_rtx); ! 3023: /* Don't try to renumber pseudo regs. It is possible for a pseudo reg ! 3024: to reach here as part of a REG_NOTE. */ ! 3025: if (newreg >= FIRST_PSEUDO_REGISTER) ! 3026: { ! 3027: in_rtx->used = 1; ! 3028: return; ! 3029: } ! 3030: newreg = LEAF_REG_REMAP (newreg); ! 3031: if (newreg < 0) ! 3032: abort (); ! 3033: regs_ever_live[REGNO (in_rtx)] = 0; ! 3034: regs_ever_live[newreg] = 1; ! 3035: REGNO (in_rtx) = newreg; ! 3036: in_rtx->used = 1; ! 3037: } ! 3038: ! 3039: if (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i') ! 3040: { ! 3041: /* Inside a SEQUENCE, we find insns. ! 3042: Renumber just the patterns of these insns, ! 3043: just as we do for the top-level insns. */ ! 3044: leaf_renumber_regs_insn (PATTERN (in_rtx)); ! 3045: return; ! 3046: } ! 3047: ! 3048: format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); ! 3049: ! 3050: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) ! 3051: switch (*format_ptr++) ! 3052: { ! 3053: case 'e': ! 3054: leaf_renumber_regs_insn (XEXP (in_rtx, i)); ! 3055: break; ! 3056: ! 3057: case 'E': ! 3058: if (NULL != XVEC (in_rtx, i)) ! 3059: { ! 3060: for (j = 0; j < XVECLEN (in_rtx, i); j++) ! 3061: leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j)); ! 3062: } ! 3063: break; ! 3064: ! 3065: case 'S': ! 3066: case 's': ! 3067: case '0': ! 3068: case 'i': ! 3069: case 'w': ! 3070: case 'n': ! 3071: case 'u': ! 3072: break; ! 3073: ! 3074: default: ! 3075: abort (); ! 3076: } ! 3077: } ! 3078: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.