final.c revision 169699
118334Speter/* Convert RTL to assembler code and output it, for GNU compiler. 290087Sobrien Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 3169699Skan 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 4169699Skan Free Software Foundation, Inc. 518334Speter 690087SobrienThis file is part of GCC. 718334Speter 890087SobrienGCC is free software; you can redistribute it and/or modify it under 990087Sobrienthe terms of the GNU General Public License as published by the Free 1090087SobrienSoftware Foundation; either version 2, or (at your option) any later 1190087Sobrienversion. 1218334Speter 1390087SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490087SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590087SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690087Sobrienfor more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1990087Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169699SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169699Skan02110-1301, USA. */ 2218334Speter 2318334Speter/* This is the final pass of the compiler. 2418334Speter It looks at the rtl code for a function and outputs assembler code. 2518334Speter 2618334Speter Call `final_start_function' to output the assembler code for function entry, 2718334Speter `final' to output assembler code for some RTL code, 2818334Speter `final_end_function' to output assembler code for function exit. 2918334Speter If a function is compiled in several pieces, each piece is 3018334Speter output separately with `final'. 3118334Speter 3218334Speter Some optimizations are also done at this level. 3318334Speter Move instructions that were made unnecessary by good register allocation 3418334Speter are detected and omitted from the output. (Though most of these 3518334Speter are removed by the last jump pass.) 3618334Speter 3718334Speter Instructions to set the condition codes are omitted when it can be 3818334Speter seen that the condition codes already had the desired values. 3918334Speter 4018334Speter In some cases it is sufficient if the inherited condition codes 4118334Speter have related values, but this may require the following insn 4218334Speter (the one that tests the condition codes) to be modified. 4318334Speter 4418334Speter The code for the function prologue and epilogue are generated 4590087Sobrien directly in assembler by the target functions function_prologue and 4690087Sobrien function_epilogue. Those instructions never exist as rtl. */ 4718334Speter 4818334Speter#include "config.h" 4950503Sobrien#include "system.h" 50132727Skan#include "coretypes.h" 51132727Skan#include "tm.h" 5218334Speter 5318334Speter#include "tree.h" 5418334Speter#include "rtl.h" 5590087Sobrien#include "tm_p.h" 5618334Speter#include "regs.h" 5718334Speter#include "insn-config.h" 5818334Speter#include "insn-attr.h" 5918334Speter#include "recog.h" 6018334Speter#include "conditions.h" 6118334Speter#include "flags.h" 6218334Speter#include "real.h" 6318334Speter#include "hard-reg-set.h" 6418334Speter#include "output.h" 6550503Sobrien#include "except.h" 6690087Sobrien#include "function.h" 6750503Sobrien#include "toplev.h" 6850503Sobrien#include "reload.h" 6952515Sobrien#include "intl.h" 7090087Sobrien#include "basic-block.h" 7190087Sobrien#include "target.h" 7290087Sobrien#include "debug.h" 7390087Sobrien#include "expr.h" 74117404Skan#include "cfglayout.h" 75169699Skan#include "tree-pass.h" 76169699Skan#include "timevar.h" 77169699Skan#include "cgraph.h" 78169699Skan#include "coverage.h" 7918334Speter 8018334Speter#ifdef XCOFF_DEBUGGING_INFO 8190087Sobrien#include "xcoffout.h" /* Needed for external data 8290087Sobrien declarations for e.g. AIX 4.x. */ 8318334Speter#endif 8418334Speter 8550503Sobrien#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) 8650503Sobrien#include "dwarf2out.h" 8750503Sobrien#endif 8850503Sobrien 89132727Skan#ifdef DBX_DEBUGGING_INFO 90132727Skan#include "dbxout.h" 91132727Skan#endif 92132727Skan 93169699Skan#ifdef SDB_DEBUGGING_INFO 94169699Skan#include "sdbout.h" 95169699Skan#endif 96169699Skan 9718334Speter/* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a 9818334Speter null default for it to save conditionalization later. */ 9918334Speter#ifndef CC_STATUS_INIT 10018334Speter#define CC_STATUS_INIT 10118334Speter#endif 10218334Speter 10318334Speter/* How to start an assembler comment. */ 10418334Speter#ifndef ASM_COMMENT_START 10518334Speter#define ASM_COMMENT_START ";#" 10618334Speter#endif 10718334Speter 10818334Speter/* Is the given character a logical line separator for the assembler? */ 10918334Speter#ifndef IS_ASM_LOGICAL_LINE_SEPARATOR 11018334Speter#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == ';') 11118334Speter#endif 11218334Speter 11350503Sobrien#ifndef JUMP_TABLES_IN_TEXT_SECTION 11450503Sobrien#define JUMP_TABLES_IN_TEXT_SECTION 0 11550503Sobrien#endif 11650503Sobrien 117132727Skan/* Bitflags used by final_scan_insn. */ 118132727Skan#define SEEN_BB 1 119132727Skan#define SEEN_NOTE 2 120132727Skan#define SEEN_EMITTED 4 121132727Skan 12218334Speter/* Last insn processed by final_scan_insn. */ 12390087Sobrienstatic rtx debug_insn; 12490087Sobrienrtx current_output_insn; 12518334Speter 12618334Speter/* Line number of last NOTE. */ 12718334Speterstatic int last_linenum; 12818334Speter 12918334Speter/* Highest line number in current block. */ 13018334Speterstatic int high_block_linenum; 13118334Speter 13218334Speter/* Likewise for function. */ 13318334Speterstatic int high_function_linenum; 13418334Speter 13518334Speter/* Filename of last NOTE. */ 13690087Sobrienstatic const char *last_filename; 13718334Speter 138169699Skan/* Whether to force emission of a line note before the next insn. */ 139169699Skanstatic bool force_source_line = false; 14050503Sobrien 141169699Skanextern const int length_unit_log; /* This is defined in insn-attrtab.c. */ 142169699Skan 14318334Speter/* Nonzero while outputting an `asm' with operands. 144169699Skan This means that inconsistencies are the user's fault, so don't die. 14518334Speter The precise value is the insn being output, to pass to error_for_asm. */ 146117404Skanrtx this_is_asm_operands; 14718334Speter 14818334Speter/* Number of operands of this insn, for an `asm' with operands. */ 14950503Sobrienstatic unsigned int insn_noperands; 15018334Speter 15118334Speter/* Compare optimization flag. */ 15218334Speter 15318334Speterstatic rtx last_ignored_compare = 0; 15418334Speter 15518334Speter/* Assign a unique number to each insn that is output. 15618334Speter This can be used to generate unique local labels. */ 15718334Speter 15818334Speterstatic int insn_counter = 0; 15918334Speter 16018334Speter#ifdef HAVE_cc0 16118334Speter/* This variable contains machine-dependent flags (defined in tm.h) 16218334Speter set and examined by output routines 16318334Speter that describe how to interpret the condition codes properly. */ 16418334Speter 16518334SpeterCC_STATUS cc_status; 16618334Speter 16718334Speter/* During output of an insn, this contains a copy of cc_status 16818334Speter from before the insn. */ 16918334Speter 17018334SpeterCC_STATUS cc_prev_status; 17118334Speter#endif 17218334Speter 17318334Speter/* Indexed by hardware reg number, is 1 if that register is ever 17418334Speter used in the current function. 17518334Speter 17618334Speter In life_analysis, or in stupid_life_analysis, this is set 17718334Speter up to record the hard regs used explicitly. Reload adds 17818334Speter in the hard regs used for holding pseudo regs. Final uses 17918334Speter it to generate the code in the function prologue and epilogue 18018334Speter to save and restore registers as needed. */ 18118334Speter 18218334Speterchar regs_ever_live[FIRST_PSEUDO_REGISTER]; 18318334Speter 184132727Skan/* Like regs_ever_live, but 1 if a reg is set or clobbered from an asm. 185132727Skan Unlike regs_ever_live, elements of this array corresponding to 186132727Skan eliminable regs like the frame pointer are set if an asm sets them. */ 187132727Skan 188132727Skanchar regs_asm_clobbered[FIRST_PSEUDO_REGISTER]; 189132727Skan 19018334Speter/* Nonzero means current function must be given a frame pointer. 191132727Skan Initialized in function.c to 0. Set only in reload1.c as per 192132727Skan the needs of the function. */ 19318334Speter 19418334Speterint frame_pointer_needed; 19518334Speter 19690087Sobrien/* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen. */ 19718334Speter 19818334Speterstatic int block_depth; 19918334Speter 20018334Speter/* Nonzero if have enabled APP processing of our assembler output. */ 20118334Speter 20218334Speterstatic int app_on; 20318334Speter 20418334Speter/* If we are outputting an insn sequence, this contains the sequence rtx. 20518334Speter Zero otherwise. */ 20618334Speter 20718334Speterrtx final_sequence; 20818334Speter 20918334Speter#ifdef ASSEMBLER_DIALECT 21018334Speter 21118334Speter/* Number of the assembler dialect to use, starting at 0. */ 21218334Speterstatic int dialect_number; 21318334Speter#endif 21418334Speter 21590087Sobrien#ifdef HAVE_conditional_execution 21690087Sobrien/* Nonnull if the insn currently being emitted was a COND_EXEC pattern. */ 21790087Sobrienrtx current_insn_predicate; 21890087Sobrien#endif 21918334Speter 22050503Sobrien#ifdef HAVE_ATTR_length 221132727Skanstatic int asm_insn_count (rtx); 22250503Sobrien#endif 223132727Skanstatic void profile_function (FILE *); 224132727Skanstatic void profile_after_prologue (FILE *); 225132727Skanstatic bool notice_source_line (rtx); 226132727Skanstatic rtx walk_alter_subreg (rtx *); 227132727Skanstatic void output_asm_name (void); 228132727Skanstatic void output_alternate_entry_point (FILE *, rtx); 229132727Skanstatic tree get_mem_expr_from_op (rtx, int *); 230132727Skanstatic void output_asm_operand_names (rtx *, int *, int); 231132727Skanstatic void output_operand (rtx, int); 23250503Sobrien#ifdef LEAF_REGISTERS 233132727Skanstatic void leaf_renumber_regs (rtx); 23450503Sobrien#endif 23550503Sobrien#ifdef HAVE_cc0 236132727Skanstatic int alter_cond (rtx); 23750503Sobrien#endif 23890087Sobrien#ifndef ADDR_VEC_ALIGN 239132727Skanstatic int final_addr_vec_align (rtx); 24090087Sobrien#endif 24190087Sobrien#ifdef HAVE_ATTR_length 242132727Skanstatic int align_fuzz (rtx, rtx, int, unsigned); 24390087Sobrien#endif 24418334Speter 24518334Speter/* Initialize data in final at the beginning of a compilation. */ 24618334Speter 24718334Spetervoid 248132727Skaninit_final (const char *filename ATTRIBUTE_UNUSED) 24918334Speter{ 25018334Speter app_on = 0; 25118334Speter final_sequence = 0; 25218334Speter 25318334Speter#ifdef ASSEMBLER_DIALECT 25418334Speter dialect_number = ASSEMBLER_DIALECT; 25518334Speter#endif 25618334Speter} 25718334Speter 25890087Sobrien/* Default target function prologue and epilogue assembler output. 25918334Speter 26090087Sobrien If not overridden for epilogue code, then the function body itself 26190087Sobrien contains return instructions wherever needed. */ 26290087Sobrienvoid 263132727Skandefault_function_pro_epilogue (FILE *file ATTRIBUTE_UNUSED, 264132727Skan HOST_WIDE_INT size ATTRIBUTE_UNUSED) 26590087Sobrien{ 26690087Sobrien} 26718334Speter 26890087Sobrien/* Default target hook that outputs nothing to a stream. */ 26990087Sobrienvoid 270132727Skanno_asm_to_stream (FILE *file ATTRIBUTE_UNUSED) 27190087Sobrien{ 27218334Speter} 27318334Speter 27418334Speter/* Enable APP processing of subsequent output. 27518334Speter Used before the output from an `asm' statement. */ 27618334Speter 27718334Spetervoid 278132727Skanapp_enable (void) 27918334Speter{ 28018334Speter if (! app_on) 28118334Speter { 28250503Sobrien fputs (ASM_APP_ON, asm_out_file); 28318334Speter app_on = 1; 28418334Speter } 28518334Speter} 28618334Speter 28718334Speter/* Disable APP processing of subsequent output. 28818334Speter Called from varasm.c before most kinds of output. */ 28918334Speter 29018334Spetervoid 291132727Skanapp_disable (void) 29218334Speter{ 29318334Speter if (app_on) 29418334Speter { 29550503Sobrien fputs (ASM_APP_OFF, asm_out_file); 29618334Speter app_on = 0; 29718334Speter } 29818334Speter} 29918334Speter 30090087Sobrien/* Return the number of slots filled in the current 30118334Speter delayed branch sequence (we don't count the insn needing the 30218334Speter delay slot). Zero if not in a delayed branch sequence. */ 30318334Speter 30418334Speter#ifdef DELAY_SLOTS 30518334Speterint 306132727Skandbr_sequence_length (void) 30718334Speter{ 30818334Speter if (final_sequence != 0) 30918334Speter return XVECLEN (final_sequence, 0) - 1; 31018334Speter else 31118334Speter return 0; 31218334Speter} 31318334Speter#endif 31418334Speter 31518334Speter/* The next two pages contain routines used to compute the length of an insn 31618334Speter and to shorten branches. */ 31718334Speter 31818334Speter/* Arrays for insn lengths, and addresses. The latter is referenced by 31918334Speter `insn_current_length'. */ 32018334Speter 32190087Sobrienstatic int *insn_lengths; 32218334Speter 32390087Sobrienvarray_type insn_addresses_; 32490087Sobrien 32552515Sobrien/* Max uid for which the above arrays are valid. */ 32652515Sobrienstatic int insn_lengths_max_uid; 32752515Sobrien 32818334Speter/* Address of insn being processed. Used by `insn_current_length'. */ 32918334Speterint insn_current_address; 33018334Speter 33150503Sobrien/* Address of insn being processed in previous iteration. */ 33250503Sobrienint insn_last_address; 33350503Sobrien 33490087Sobrien/* known invariant alignment of insn being processed. */ 33550503Sobrienint insn_current_align; 33650503Sobrien 33750503Sobrien/* After shorten_branches, for any insn, uid_align[INSN_UID (insn)] 33850503Sobrien gives the next following alignment insn that increases the known 33950503Sobrien alignment, or NULL_RTX if there is no such insn. 34050503Sobrien For any alignment obtained this way, we can again index uid_align with 34150503Sobrien its uid to obtain the next following align that in turn increases the 34250503Sobrien alignment, till we reach NULL_RTX; the sequence obtained this way 34350503Sobrien for each insn we'll call the alignment chain of this insn in the following 34450503Sobrien comments. */ 34550503Sobrien 34690087Sobrienstruct label_alignment 34790087Sobrien{ 34850503Sobrien short alignment; 34950503Sobrien short max_skip; 35050503Sobrien}; 35150503Sobrien 35250503Sobrienstatic rtx *uid_align; 35350503Sobrienstatic int *uid_shuid; 35450503Sobrienstatic struct label_alignment *label_align; 35550503Sobrien 35618334Speter/* Indicate that branch shortening hasn't yet been done. */ 35718334Speter 35818334Spetervoid 359132727Skaninit_insn_lengths (void) 36018334Speter{ 36150503Sobrien if (uid_shuid) 36250503Sobrien { 36350503Sobrien free (uid_shuid); 36450503Sobrien uid_shuid = 0; 36550503Sobrien } 36650503Sobrien if (insn_lengths) 36750503Sobrien { 36850503Sobrien free (insn_lengths); 36950503Sobrien insn_lengths = 0; 37052515Sobrien insn_lengths_max_uid = 0; 37150503Sobrien } 37290087Sobrien#ifdef HAVE_ATTR_length 37390087Sobrien INSN_ADDRESSES_FREE (); 37490087Sobrien#endif 37550503Sobrien if (uid_align) 37650503Sobrien { 37750503Sobrien free (uid_align); 37850503Sobrien uid_align = 0; 37950503Sobrien } 38018334Speter} 38118334Speter 38218334Speter/* Obtain the current length of an insn. If branch shortening has been done, 383169699Skan get its actual length. Otherwise, use FALLBACK_FN to calculate the 384169699Skan length. */ 385169699Skanstatic inline int 386169699Skanget_attr_length_1 (rtx insn ATTRIBUTE_UNUSED, 387169699Skan int (*fallback_fn) (rtx) ATTRIBUTE_UNUSED) 38818334Speter{ 38918334Speter#ifdef HAVE_ATTR_length 39018334Speter rtx body; 39118334Speter int i; 39218334Speter int length = 0; 39318334Speter 39452515Sobrien if (insn_lengths_max_uid > INSN_UID (insn)) 39518334Speter return insn_lengths[INSN_UID (insn)]; 39618334Speter else 39718334Speter switch (GET_CODE (insn)) 39818334Speter { 39918334Speter case NOTE: 40018334Speter case BARRIER: 40118334Speter case CODE_LABEL: 40218334Speter return 0; 40318334Speter 40418334Speter case CALL_INSN: 405169699Skan length = fallback_fn (insn); 40618334Speter break; 40718334Speter 40818334Speter case JUMP_INSN: 40918334Speter body = PATTERN (insn); 410117404Skan if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 41118334Speter { 41250503Sobrien /* Alignment is machine-dependent and should be handled by 41350503Sobrien ADDR_VEC_ALIGN. */ 41418334Speter } 41518334Speter else 416169699Skan length = fallback_fn (insn); 41718334Speter break; 41818334Speter 41918334Speter case INSN: 42018334Speter body = PATTERN (insn); 42118334Speter if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER) 42218334Speter return 0; 42318334Speter 42418334Speter else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) 425169699Skan length = asm_insn_count (body) * fallback_fn (insn); 42618334Speter else if (GET_CODE (body) == SEQUENCE) 42718334Speter for (i = 0; i < XVECLEN (body, 0); i++) 42818334Speter length += get_attr_length (XVECEXP (body, 0, i)); 42918334Speter else 430169699Skan length = fallback_fn (insn); 43150503Sobrien break; 43250503Sobrien 43350503Sobrien default: 43450503Sobrien break; 43518334Speter } 43618334Speter 43718334Speter#ifdef ADJUST_INSN_LENGTH 43818334Speter ADJUST_INSN_LENGTH (insn, length); 43918334Speter#endif 44018334Speter return length; 44118334Speter#else /* not HAVE_ATTR_length */ 44218334Speter return 0; 443169699Skan#define insn_default_length 0 444169699Skan#define insn_min_length 0 44518334Speter#endif /* not HAVE_ATTR_length */ 44618334Speter} 447169699Skan 448169699Skan/* Obtain the current length of an insn. If branch shortening has been done, 449169699Skan get its actual length. Otherwise, get its maximum length. */ 450169699Skanint 451169699Skanget_attr_length (rtx insn) 452169699Skan{ 453169699Skan return get_attr_length_1 (insn, insn_default_length); 454169699Skan} 455169699Skan 456169699Skan/* Obtain the current length of an insn. If branch shortening has been done, 457169699Skan get its actual length. Otherwise, get its minimum length. */ 458169699Skanint 459169699Skanget_attr_min_length (rtx insn) 460169699Skan{ 461169699Skan return get_attr_length_1 (insn, insn_min_length); 462169699Skan} 46318334Speter 46450503Sobrien/* Code to handle alignment inside shorten_branches. */ 46550503Sobrien 46650503Sobrien/* Here is an explanation how the algorithm in align_fuzz can give 46750503Sobrien proper results: 46850503Sobrien 46950503Sobrien Call a sequence of instructions beginning with alignment point X 47050503Sobrien and continuing until the next alignment point `block X'. When `X' 47190087Sobrien is used in an expression, it means the alignment value of the 47250503Sobrien alignment point. 47390087Sobrien 47450503Sobrien Call the distance between the start of the first insn of block X, and 47550503Sobrien the end of the last insn of block X `IX', for the `inner size of X'. 47650503Sobrien This is clearly the sum of the instruction lengths. 47790087Sobrien 47850503Sobrien Likewise with the next alignment-delimited block following X, which we 47950503Sobrien shall call block Y. 48090087Sobrien 48150503Sobrien Call the distance between the start of the first insn of block X, and 48250503Sobrien the start of the first insn of block Y `OX', for the `outer size of X'. 48390087Sobrien 48450503Sobrien The estimated padding is then OX - IX. 48590087Sobrien 48650503Sobrien OX can be safely estimated as 48790087Sobrien 48850503Sobrien if (X >= Y) 48950503Sobrien OX = round_up(IX, Y) 49050503Sobrien else 49150503Sobrien OX = round_up(IX, X) + Y - X 49290087Sobrien 49350503Sobrien Clearly est(IX) >= real(IX), because that only depends on the 49450503Sobrien instruction lengths, and those being overestimated is a given. 49590087Sobrien 49650503Sobrien Clearly round_up(foo, Z) >= round_up(bar, Z) if foo >= bar, so 49750503Sobrien we needn't worry about that when thinking about OX. 49890087Sobrien 49950503Sobrien When X >= Y, the alignment provided by Y adds no uncertainty factor 50050503Sobrien for branch ranges starting before X, so we can just round what we have. 50150503Sobrien But when X < Y, we don't know anything about the, so to speak, 50250503Sobrien `middle bits', so we have to assume the worst when aligning up from an 50350503Sobrien address mod X to one mod Y, which is Y - X. */ 50450503Sobrien 50550503Sobrien#ifndef LABEL_ALIGN 50690087Sobrien#define LABEL_ALIGN(LABEL) align_labels_log 50750503Sobrien#endif 50850503Sobrien 50950503Sobrien#ifndef LABEL_ALIGN_MAX_SKIP 51090087Sobrien#define LABEL_ALIGN_MAX_SKIP align_labels_max_skip 51150503Sobrien#endif 51250503Sobrien 51350503Sobrien#ifndef LOOP_ALIGN 51490087Sobrien#define LOOP_ALIGN(LABEL) align_loops_log 51550503Sobrien#endif 51650503Sobrien 51750503Sobrien#ifndef LOOP_ALIGN_MAX_SKIP 51890087Sobrien#define LOOP_ALIGN_MAX_SKIP align_loops_max_skip 51950503Sobrien#endif 52050503Sobrien 52150503Sobrien#ifndef LABEL_ALIGN_AFTER_BARRIER 52250503Sobrien#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0 52350503Sobrien#endif 52450503Sobrien 52550503Sobrien#ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 52650503Sobrien#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0 52750503Sobrien#endif 52850503Sobrien 52990087Sobrien#ifndef JUMP_ALIGN 53090087Sobrien#define JUMP_ALIGN(LABEL) align_jumps_log 53190087Sobrien#endif 53290087Sobrien 53390087Sobrien#ifndef JUMP_ALIGN_MAX_SKIP 53490087Sobrien#define JUMP_ALIGN_MAX_SKIP align_jumps_max_skip 53590087Sobrien#endif 53690087Sobrien 53750503Sobrien#ifndef ADDR_VEC_ALIGN 53890087Sobrienstatic int 539132727Skanfinal_addr_vec_align (rtx addr_vec) 54050503Sobrien{ 54190087Sobrien int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec))); 54250503Sobrien 54350503Sobrien if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT) 54450503Sobrien align = BIGGEST_ALIGNMENT / BITS_PER_UNIT; 54590087Sobrien return exact_log2 (align); 54650503Sobrien 54750503Sobrien} 54890087Sobrien 54950503Sobrien#define ADDR_VEC_ALIGN(ADDR_VEC) final_addr_vec_align (ADDR_VEC) 55050503Sobrien#endif 55150503Sobrien 55250503Sobrien#ifndef INSN_LENGTH_ALIGNMENT 55350503Sobrien#define INSN_LENGTH_ALIGNMENT(INSN) length_unit_log 55450503Sobrien#endif 55550503Sobrien 55650503Sobrien#define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)]) 55750503Sobrien 55850503Sobrienstatic int min_labelno, max_labelno; 55950503Sobrien 56050503Sobrien#define LABEL_TO_ALIGNMENT(LABEL) \ 56150503Sobrien (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].alignment) 56250503Sobrien 56350503Sobrien#define LABEL_TO_MAX_SKIP(LABEL) \ 56450503Sobrien (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].max_skip) 56550503Sobrien 56650503Sobrien/* For the benefit of port specific code do this also as a function. */ 56790087Sobrien 56850503Sobrienint 569132727Skanlabel_to_alignment (rtx label) 57050503Sobrien{ 57150503Sobrien return LABEL_TO_ALIGNMENT (label); 57250503Sobrien} 57350503Sobrien 57450503Sobrien#ifdef HAVE_ATTR_length 57550503Sobrien/* The differences in addresses 57650503Sobrien between a branch and its target might grow or shrink depending on 57750503Sobrien the alignment the start insn of the range (the branch for a forward 57850503Sobrien branch or the label for a backward branch) starts out on; if these 57950503Sobrien differences are used naively, they can even oscillate infinitely. 58050503Sobrien We therefore want to compute a 'worst case' address difference that 58150503Sobrien is independent of the alignment the start insn of the range end 58250503Sobrien up on, and that is at least as large as the actual difference. 58350503Sobrien The function align_fuzz calculates the amount we have to add to the 58450503Sobrien naively computed difference, by traversing the part of the alignment 58550503Sobrien chain of the start insn of the range that is in front of the end insn 58650503Sobrien of the range, and considering for each alignment the maximum amount 58750503Sobrien that it might contribute to a size increase. 58850503Sobrien 58950503Sobrien For casesi tables, we also want to know worst case minimum amounts of 59050503Sobrien address difference, in case a machine description wants to introduce 59150503Sobrien some common offset that is added to all offsets in a table. 59290087Sobrien For this purpose, align_fuzz with a growth argument of 0 computes the 59350503Sobrien appropriate adjustment. */ 59450503Sobrien 59550503Sobrien/* Compute the maximum delta by which the difference of the addresses of 59650503Sobrien START and END might grow / shrink due to a different address for start 59750503Sobrien which changes the size of alignment insns between START and END. 59850503Sobrien KNOWN_ALIGN_LOG is the alignment known for START. 59950503Sobrien GROWTH should be ~0 if the objective is to compute potential code size 60050503Sobrien increase, and 0 if the objective is to compute potential shrink. 60150503Sobrien The return value is undefined for any other value of GROWTH. */ 60290087Sobrien 60390087Sobrienstatic int 604132727Skanalign_fuzz (rtx start, rtx end, int known_align_log, unsigned int growth) 60550503Sobrien{ 60650503Sobrien int uid = INSN_UID (start); 60750503Sobrien rtx align_label; 60850503Sobrien int known_align = 1 << known_align_log; 60950503Sobrien int end_shuid = INSN_SHUID (end); 61050503Sobrien int fuzz = 0; 61150503Sobrien 61250503Sobrien for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid]) 61350503Sobrien { 61450503Sobrien int align_addr, new_align; 61550503Sobrien 61650503Sobrien uid = INSN_UID (align_label); 61790087Sobrien align_addr = INSN_ADDRESSES (uid) - insn_lengths[uid]; 61850503Sobrien if (uid_shuid[uid] > end_shuid) 61950503Sobrien break; 62050503Sobrien known_align_log = LABEL_TO_ALIGNMENT (align_label); 62150503Sobrien new_align = 1 << known_align_log; 62250503Sobrien if (new_align < known_align) 62350503Sobrien continue; 62450503Sobrien fuzz += (-align_addr ^ growth) & (new_align - known_align); 62550503Sobrien known_align = new_align; 62650503Sobrien } 62750503Sobrien return fuzz; 62850503Sobrien} 62950503Sobrien 63050503Sobrien/* Compute a worst-case reference address of a branch so that it 63150503Sobrien can be safely used in the presence of aligned labels. Since the 63250503Sobrien size of the branch itself is unknown, the size of the branch is 63350503Sobrien not included in the range. I.e. for a forward branch, the reference 63450503Sobrien address is the end address of the branch as known from the previous 63550503Sobrien branch shortening pass, minus a value to account for possible size 63650503Sobrien increase due to alignment. For a backward branch, it is the start 63750503Sobrien address of the branch as known from the current pass, plus a value 63850503Sobrien to account for possible size increase due to alignment. 63950503Sobrien NB.: Therefore, the maximum offset allowed for backward branches needs 64050503Sobrien to exclude the branch size. */ 64190087Sobrien 64250503Sobrienint 643132727Skaninsn_current_reference_address (rtx branch) 64450503Sobrien{ 64590087Sobrien rtx dest, seq; 64690087Sobrien int seq_uid; 64790087Sobrien 64890087Sobrien if (! INSN_ADDRESSES_SET_P ()) 64990087Sobrien return 0; 65090087Sobrien 65190087Sobrien seq = NEXT_INSN (PREV_INSN (branch)); 65290087Sobrien seq_uid = INSN_UID (seq); 653169699Skan if (!JUMP_P (branch)) 65450503Sobrien /* This can happen for example on the PA; the objective is to know the 65550503Sobrien offset to address something in front of the start of the function. 65650503Sobrien Thus, we can treat it like a backward branch. 65750503Sobrien We assume here that FUNCTION_BOUNDARY / BITS_PER_UNIT is larger than 65850503Sobrien any alignment we'd encounter, so we skip the call to align_fuzz. */ 65950503Sobrien return insn_current_address; 66050503Sobrien dest = JUMP_LABEL (branch); 66190087Sobrien 66290087Sobrien /* BRANCH has no proper alignment chain set, so use SEQ. 66390087Sobrien BRANCH also has no INSN_SHUID. */ 66490087Sobrien if (INSN_SHUID (seq) < INSN_SHUID (dest)) 66550503Sobrien { 66690087Sobrien /* Forward branch. */ 66750503Sobrien return (insn_last_address + insn_lengths[seq_uid] 66850503Sobrien - align_fuzz (seq, dest, length_unit_log, ~0)); 66950503Sobrien } 67050503Sobrien else 67150503Sobrien { 67290087Sobrien /* Backward branch. */ 67350503Sobrien return (insn_current_address 67450503Sobrien + align_fuzz (dest, seq, length_unit_log, ~0)); 67550503Sobrien } 67650503Sobrien} 67750503Sobrien#endif /* HAVE_ATTR_length */ 67850503Sobrien 679169699Skan/* Compute branch alignments based on frequency information in the 680169699Skan CFG. */ 681169699Skan 682169699Skanstatic unsigned int 683132727Skancompute_alignments (void) 68490087Sobrien{ 68590087Sobrien int log, max_skip, max_log; 686117404Skan basic_block bb; 68790087Sobrien 68890087Sobrien if (label_align) 68990087Sobrien { 69090087Sobrien free (label_align); 69190087Sobrien label_align = 0; 69290087Sobrien } 69390087Sobrien 69490087Sobrien max_labelno = max_label_num (); 69590087Sobrien min_labelno = get_first_label_num (); 696169699Skan label_align = XCNEWVEC (struct label_alignment, max_labelno - min_labelno + 1); 69790087Sobrien 69890087Sobrien /* If not optimizing or optimizing for size, don't assign any alignments. */ 69990087Sobrien if (! optimize || optimize_size) 700169699Skan return 0; 70190087Sobrien 702117404Skan FOR_EACH_BB (bb) 70390087Sobrien { 704132727Skan rtx label = BB_HEAD (bb); 70590087Sobrien int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0; 70690087Sobrien edge e; 707169699Skan edge_iterator ei; 70890087Sobrien 709169699Skan if (!LABEL_P (label) 710132727Skan || probably_never_executed_bb_p (bb)) 71190087Sobrien continue; 71290087Sobrien max_log = LABEL_ALIGN (label); 71390087Sobrien max_skip = LABEL_ALIGN_MAX_SKIP; 71490087Sobrien 715169699Skan FOR_EACH_EDGE (e, ei, bb->preds) 71690087Sobrien { 71790087Sobrien if (e->flags & EDGE_FALLTHRU) 71890087Sobrien has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e); 71990087Sobrien else 72090087Sobrien branch_frequency += EDGE_FREQUENCY (e); 72190087Sobrien } 72290087Sobrien 72390087Sobrien /* There are two purposes to align block with no fallthru incoming edge: 72490087Sobrien 1) to avoid fetch stalls when branch destination is near cache boundary 72590087Sobrien 2) to improve cache efficiency in case the previous block is not executed 72690087Sobrien (so it does not need to be in the cache). 72790087Sobrien 72890087Sobrien We to catch first case, we align frequently executed blocks. 72990087Sobrien To catch the second, we align blocks that are executed more frequently 73090087Sobrien than the predecessor and the predecessor is likely to not be executed 73190087Sobrien when function is called. */ 73290087Sobrien 73390087Sobrien if (!has_fallthru 73490087Sobrien && (branch_frequency > BB_FREQ_MAX / 10 735117404Skan || (bb->frequency > bb->prev_bb->frequency * 10 736117404Skan && (bb->prev_bb->frequency 73790087Sobrien <= ENTRY_BLOCK_PTR->frequency / 2)))) 73890087Sobrien { 73990087Sobrien log = JUMP_ALIGN (label); 74090087Sobrien if (max_log < log) 74190087Sobrien { 74290087Sobrien max_log = log; 74390087Sobrien max_skip = JUMP_ALIGN_MAX_SKIP; 74490087Sobrien } 74590087Sobrien } 74690087Sobrien /* In case block is frequent and reached mostly by non-fallthru edge, 747117404Skan align it. It is most likely a first block of loop. */ 74890087Sobrien if (has_fallthru 749132727Skan && maybe_hot_bb_p (bb) 75090087Sobrien && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10 751117404Skan && branch_frequency > fallthru_frequency * 2) 75290087Sobrien { 75390087Sobrien log = LOOP_ALIGN (label); 75490087Sobrien if (max_log < log) 75590087Sobrien { 75690087Sobrien max_log = log; 75790087Sobrien max_skip = LOOP_ALIGN_MAX_SKIP; 75890087Sobrien } 75990087Sobrien } 76090087Sobrien LABEL_TO_ALIGNMENT (label) = max_log; 76190087Sobrien LABEL_TO_MAX_SKIP (label) = max_skip; 76290087Sobrien } 763169699Skan return 0; 76490087Sobrien} 765169699Skan 766169699Skanstruct tree_opt_pass pass_compute_alignments = 767169699Skan{ 768169699Skan NULL, /* name */ 769169699Skan NULL, /* gate */ 770169699Skan compute_alignments, /* execute */ 771169699Skan NULL, /* sub */ 772169699Skan NULL, /* next */ 773169699Skan 0, /* static_pass_number */ 774169699Skan 0, /* tv_id */ 775169699Skan 0, /* properties_required */ 776169699Skan 0, /* properties_provided */ 777169699Skan 0, /* properties_destroyed */ 778169699Skan 0, /* todo_flags_start */ 779169699Skan 0, /* todo_flags_finish */ 780169699Skan 0 /* letter */ 781169699Skan}; 782169699Skan 78390087Sobrien 78418334Speter/* Make a pass over all insns and compute their actual lengths by shortening 78518334Speter any branches of variable length if possible. */ 78618334Speter 78750503Sobrien/* shorten_branches might be called multiple times: for example, the SH 78850503Sobrien port splits out-of-range conditional branches in MACHINE_DEPENDENT_REORG. 78950503Sobrien In order to do this, it needs proper length information, which it obtains 79050503Sobrien by calling shorten_branches. This cannot be collapsed with 79190087Sobrien shorten_branches itself into a single pass unless we also want to integrate 79250503Sobrien reorg.c, since the branch splitting exposes new instructions with delay 79350503Sobrien slots. */ 79450503Sobrien 79518334Spetervoid 796132727Skanshorten_branches (rtx first ATTRIBUTE_UNUSED) 79718334Speter{ 79850503Sobrien rtx insn; 79950503Sobrien int max_uid; 80050503Sobrien int i; 80150503Sobrien int max_log; 80250503Sobrien int max_skip; 80318334Speter#ifdef HAVE_ATTR_length 80450503Sobrien#define MAX_CODE_ALIGN 16 80550503Sobrien rtx seq; 80618334Speter int something_changed = 1; 80718334Speter char *varying_length; 80818334Speter rtx body; 80918334Speter int uid; 81050503Sobrien rtx align_tab[MAX_CODE_ALIGN]; 81118334Speter 81250503Sobrien#endif 81318334Speter 81450503Sobrien /* Compute maximum UID and allocate label_align / uid_shuid. */ 81550503Sobrien max_uid = get_max_uid (); 81650503Sobrien 817169699Skan /* Free uid_shuid before reallocating it. */ 818169699Skan free (uid_shuid); 81950503Sobrien 820169699Skan uid_shuid = XNEWVEC (int, max_uid); 821169699Skan 82290087Sobrien if (max_labelno != max_label_num ()) 82390087Sobrien { 82490087Sobrien int old = max_labelno; 82590087Sobrien int n_labels; 82690087Sobrien int n_old_labels; 82790087Sobrien 82890087Sobrien max_labelno = max_label_num (); 82990087Sobrien 83090087Sobrien n_labels = max_labelno - min_labelno + 1; 83190087Sobrien n_old_labels = old - min_labelno + 1; 83290087Sobrien 833132727Skan label_align = xrealloc (label_align, 834132727Skan n_labels * sizeof (struct label_alignment)); 83590087Sobrien 836169699Skan /* Range of labels grows monotonically in the function. Failing here 83790087Sobrien means that the initialization of array got lost. */ 838169699Skan gcc_assert (n_old_labels <= n_labels); 83990087Sobrien 84090087Sobrien memset (label_align + n_old_labels, 0, 84190087Sobrien (n_labels - n_old_labels) * sizeof (struct label_alignment)); 84290087Sobrien } 84390087Sobrien 84450503Sobrien /* Initialize label_align and set up uid_shuid to be strictly 84550503Sobrien monotonically rising with insn order. */ 84650503Sobrien /* We use max_log here to keep track of the maximum alignment we want to 84750503Sobrien impose on the next CODE_LABEL (or the current one if we are processing 84850503Sobrien the CODE_LABEL itself). */ 84990087Sobrien 85050503Sobrien max_log = 0; 85150503Sobrien max_skip = 0; 85250503Sobrien 85350503Sobrien for (insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn)) 85450503Sobrien { 85550503Sobrien int log; 85650503Sobrien 85750503Sobrien INSN_SHUID (insn) = i++; 85890087Sobrien if (INSN_P (insn)) 859169699Skan continue; 860169699Skan 861169699Skan if (LABEL_P (insn)) 86250503Sobrien { 86350503Sobrien rtx next; 86450503Sobrien 86590087Sobrien /* Merge in alignments computed by compute_alignments. */ 86690087Sobrien log = LABEL_TO_ALIGNMENT (insn); 86790087Sobrien if (max_log < log) 86890087Sobrien { 86990087Sobrien max_log = log; 87090087Sobrien max_skip = LABEL_TO_MAX_SKIP (insn); 87190087Sobrien } 87290087Sobrien 87350503Sobrien log = LABEL_ALIGN (insn); 87450503Sobrien if (max_log < log) 87550503Sobrien { 87650503Sobrien max_log = log; 87750503Sobrien max_skip = LABEL_ALIGN_MAX_SKIP; 87850503Sobrien } 879169699Skan next = next_nonnote_insn (insn); 88050503Sobrien /* ADDR_VECs only take room if read-only data goes into the text 88150503Sobrien section. */ 882169699Skan if (JUMP_TABLES_IN_TEXT_SECTION 883169699Skan || readonly_data_section == text_section) 884169699Skan if (next && JUMP_P (next)) 88550503Sobrien { 88650503Sobrien rtx nextbody = PATTERN (next); 88750503Sobrien if (GET_CODE (nextbody) == ADDR_VEC 88850503Sobrien || GET_CODE (nextbody) == ADDR_DIFF_VEC) 88950503Sobrien { 89050503Sobrien log = ADDR_VEC_ALIGN (next); 89150503Sobrien if (max_log < log) 89250503Sobrien { 89350503Sobrien max_log = log; 89450503Sobrien max_skip = LABEL_ALIGN_MAX_SKIP; 89550503Sobrien } 89650503Sobrien } 89750503Sobrien } 89850503Sobrien LABEL_TO_ALIGNMENT (insn) = max_log; 89950503Sobrien LABEL_TO_MAX_SKIP (insn) = max_skip; 90050503Sobrien max_log = 0; 90150503Sobrien max_skip = 0; 90250503Sobrien } 903169699Skan else if (BARRIER_P (insn)) 90450503Sobrien { 90550503Sobrien rtx label; 90650503Sobrien 90790087Sobrien for (label = insn; label && ! INSN_P (label); 90850503Sobrien label = NEXT_INSN (label)) 909169699Skan if (LABEL_P (label)) 91050503Sobrien { 91150503Sobrien log = LABEL_ALIGN_AFTER_BARRIER (insn); 91250503Sobrien if (max_log < log) 91350503Sobrien { 91450503Sobrien max_log = log; 91550503Sobrien max_skip = LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP; 91650503Sobrien } 91750503Sobrien break; 91850503Sobrien } 91950503Sobrien } 92050503Sobrien } 92150503Sobrien#ifdef HAVE_ATTR_length 92250503Sobrien 92350503Sobrien /* Allocate the rest of the arrays. */ 924169699Skan insn_lengths = XNEWVEC (int, max_uid); 92552515Sobrien insn_lengths_max_uid = max_uid; 92650503Sobrien /* Syntax errors can lead to labels being outside of the main insn stream. 92750503Sobrien Initialize insn_addresses, so that we get reproducible results. */ 92890087Sobrien INSN_ADDRESSES_ALLOC (max_uid); 92950503Sobrien 930169699Skan varying_length = XCNEWVEC (char, max_uid); 93150503Sobrien 93250503Sobrien /* Initialize uid_align. We scan instructions 93350503Sobrien from end to start, and keep in align_tab[n] the last seen insn 93450503Sobrien that does an alignment of at least n+1, i.e. the successor 93550503Sobrien in the alignment chain for an insn that does / has a known 93650503Sobrien alignment of n. */ 937169699Skan uid_align = XCNEWVEC (rtx, max_uid); 93850503Sobrien 93990087Sobrien for (i = MAX_CODE_ALIGN; --i >= 0;) 94050503Sobrien align_tab[i] = NULL_RTX; 94150503Sobrien seq = get_last_insn (); 94250503Sobrien for (; seq; seq = PREV_INSN (seq)) 94350503Sobrien { 94450503Sobrien int uid = INSN_UID (seq); 94550503Sobrien int log; 946169699Skan log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq) : 0); 94750503Sobrien uid_align[uid] = align_tab[0]; 94850503Sobrien if (log) 94950503Sobrien { 95050503Sobrien /* Found an alignment label. */ 95150503Sobrien uid_align[uid] = align_tab[log]; 95250503Sobrien for (i = log - 1; i >= 0; i--) 95350503Sobrien align_tab[i] = seq; 95450503Sobrien } 95550503Sobrien } 95650503Sobrien#ifdef CASE_VECTOR_SHORTEN_MODE 95750503Sobrien if (optimize) 95850503Sobrien { 95950503Sobrien /* Look for ADDR_DIFF_VECs, and initialize their minimum and maximum 96050503Sobrien label fields. */ 96150503Sobrien 96250503Sobrien int min_shuid = INSN_SHUID (get_insns ()) - 1; 96350503Sobrien int max_shuid = INSN_SHUID (get_last_insn ()) + 1; 96450503Sobrien int rel; 96550503Sobrien 96650503Sobrien for (insn = first; insn != 0; insn = NEXT_INSN (insn)) 96750503Sobrien { 96850503Sobrien rtx min_lab = NULL_RTX, max_lab = NULL_RTX, pat; 96950503Sobrien int len, i, min, max, insn_shuid; 97050503Sobrien int min_align; 97150503Sobrien addr_diff_vec_flags flags; 97250503Sobrien 973169699Skan if (!JUMP_P (insn) 97450503Sobrien || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) 97550503Sobrien continue; 97650503Sobrien pat = PATTERN (insn); 97750503Sobrien len = XVECLEN (pat, 1); 978169699Skan gcc_assert (len > 0); 97950503Sobrien min_align = MAX_CODE_ALIGN; 98050503Sobrien for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--) 98150503Sobrien { 98250503Sobrien rtx lab = XEXP (XVECEXP (pat, 1, i), 0); 98350503Sobrien int shuid = INSN_SHUID (lab); 98450503Sobrien if (shuid < min) 98550503Sobrien { 98650503Sobrien min = shuid; 98750503Sobrien min_lab = lab; 98850503Sobrien } 98950503Sobrien if (shuid > max) 99050503Sobrien { 99150503Sobrien max = shuid; 99250503Sobrien max_lab = lab; 99350503Sobrien } 99450503Sobrien if (min_align > LABEL_TO_ALIGNMENT (lab)) 99550503Sobrien min_align = LABEL_TO_ALIGNMENT (lab); 99650503Sobrien } 997169699Skan XEXP (pat, 2) = gen_rtx_LABEL_REF (Pmode, min_lab); 998169699Skan XEXP (pat, 3) = gen_rtx_LABEL_REF (Pmode, max_lab); 99950503Sobrien insn_shuid = INSN_SHUID (insn); 100050503Sobrien rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0)); 1001169699Skan memset (&flags, 0, sizeof (flags)); 100250503Sobrien flags.min_align = min_align; 100350503Sobrien flags.base_after_vec = rel > insn_shuid; 100450503Sobrien flags.min_after_vec = min > insn_shuid; 100550503Sobrien flags.max_after_vec = max > insn_shuid; 100650503Sobrien flags.min_after_base = min > rel; 100750503Sobrien flags.max_after_base = max > rel; 100850503Sobrien ADDR_DIFF_VEC_FLAGS (pat) = flags; 100950503Sobrien } 101050503Sobrien } 101150503Sobrien#endif /* CASE_VECTOR_SHORTEN_MODE */ 101250503Sobrien 101318334Speter /* Compute initial lengths, addresses, and varying flags for each insn. */ 1014132727Skan for (insn_current_address = 0, insn = first; 101518334Speter insn != 0; 101618334Speter insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) 101718334Speter { 101818334Speter uid = INSN_UID (insn); 101950503Sobrien 102050503Sobrien insn_lengths[uid] = 0; 102150503Sobrien 1022169699Skan if (LABEL_P (insn)) 102350503Sobrien { 102450503Sobrien int log = LABEL_TO_ALIGNMENT (insn); 102550503Sobrien if (log) 102650503Sobrien { 102750503Sobrien int align = 1 << log; 102850503Sobrien int new_address = (insn_current_address + align - 1) & -align; 102950503Sobrien insn_lengths[uid] = new_address - insn_current_address; 103050503Sobrien } 103150503Sobrien } 103250503Sobrien 1033117404Skan INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid]; 103490087Sobrien 1035169699Skan if (NOTE_P (insn) || BARRIER_P (insn) 1036169699Skan || LABEL_P (insn)) 103718334Speter continue; 103850503Sobrien if (INSN_DELETED_P (insn)) 103950503Sobrien continue; 104018334Speter 104118334Speter body = PATTERN (insn); 104218334Speter if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 104318334Speter { 104418334Speter /* This only takes room if read-only data goes into the text 104518334Speter section. */ 1046169699Skan if (JUMP_TABLES_IN_TEXT_SECTION 1047169699Skan || readonly_data_section == text_section) 104850503Sobrien insn_lengths[uid] = (XVECLEN (body, 104950503Sobrien GET_CODE (body) == ADDR_DIFF_VEC) 105050503Sobrien * GET_MODE_SIZE (GET_MODE (body))); 105150503Sobrien /* Alignment is handled by ADDR_VEC_ALIGN. */ 105218334Speter } 105390087Sobrien else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) 105418334Speter insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn); 105518334Speter else if (GET_CODE (body) == SEQUENCE) 105618334Speter { 105718334Speter int i; 105818334Speter int const_delay_slots; 105918334Speter#ifdef DELAY_SLOTS 106018334Speter const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0)); 106118334Speter#else 106218334Speter const_delay_slots = 0; 106318334Speter#endif 106418334Speter /* Inside a delay slot sequence, we do not do any branch shortening 106518334Speter if the shortening could change the number of delay slots 106650503Sobrien of the branch. */ 106718334Speter for (i = 0; i < XVECLEN (body, 0); i++) 106818334Speter { 106918334Speter rtx inner_insn = XVECEXP (body, 0, i); 107018334Speter int inner_uid = INSN_UID (inner_insn); 107118334Speter int inner_length; 107218334Speter 107390087Sobrien if (GET_CODE (body) == ASM_INPUT 107490087Sobrien || asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0) 107518334Speter inner_length = (asm_insn_count (PATTERN (inner_insn)) 107618334Speter * insn_default_length (inner_insn)); 107718334Speter else 107818334Speter inner_length = insn_default_length (inner_insn); 107990087Sobrien 108018334Speter insn_lengths[inner_uid] = inner_length; 108118334Speter if (const_delay_slots) 108218334Speter { 108318334Speter if ((varying_length[inner_uid] 108418334Speter = insn_variable_length_p (inner_insn)) != 0) 108518334Speter varying_length[uid] = 1; 108690087Sobrien INSN_ADDRESSES (inner_uid) = (insn_current_address 108790087Sobrien + insn_lengths[uid]); 108818334Speter } 108918334Speter else 109018334Speter varying_length[inner_uid] = 0; 109118334Speter insn_lengths[uid] += inner_length; 109218334Speter } 109318334Speter } 109418334Speter else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER) 109518334Speter { 109618334Speter insn_lengths[uid] = insn_default_length (insn); 109718334Speter varying_length[uid] = insn_variable_length_p (insn); 109818334Speter } 109918334Speter 110018334Speter /* If needed, do any adjustment. */ 110118334Speter#ifdef ADJUST_INSN_LENGTH 110218334Speter ADJUST_INSN_LENGTH (insn, insn_lengths[uid]); 110352515Sobrien if (insn_lengths[uid] < 0) 110490087Sobrien fatal_insn ("negative insn length", insn); 110518334Speter#endif 110618334Speter } 110718334Speter 110818334Speter /* Now loop over all the insns finding varying length insns. For each, 110918334Speter get the current insn length. If it has changed, reflect the change. 111018334Speter When nothing changes for a full pass, we are done. */ 111118334Speter 111218334Speter while (something_changed) 111318334Speter { 111418334Speter something_changed = 0; 111550503Sobrien insn_current_align = MAX_CODE_ALIGN - 1; 1116132727Skan for (insn_current_address = 0, insn = first; 111718334Speter insn != 0; 111818334Speter insn = NEXT_INSN (insn)) 111918334Speter { 112018334Speter int new_length; 112150503Sobrien#ifdef ADJUST_INSN_LENGTH 112218334Speter int tmp_length; 112350503Sobrien#endif 112450503Sobrien int length_align; 112518334Speter 112618334Speter uid = INSN_UID (insn); 112750503Sobrien 1128169699Skan if (LABEL_P (insn)) 112950503Sobrien { 113050503Sobrien int log = LABEL_TO_ALIGNMENT (insn); 113150503Sobrien if (log > insn_current_align) 113250503Sobrien { 113350503Sobrien int align = 1 << log; 113450503Sobrien int new_address= (insn_current_address + align - 1) & -align; 113550503Sobrien insn_lengths[uid] = new_address - insn_current_address; 113650503Sobrien insn_current_align = log; 113750503Sobrien insn_current_address = new_address; 113850503Sobrien } 113950503Sobrien else 114050503Sobrien insn_lengths[uid] = 0; 114190087Sobrien INSN_ADDRESSES (uid) = insn_current_address; 114250503Sobrien continue; 114350503Sobrien } 114450503Sobrien 114550503Sobrien length_align = INSN_LENGTH_ALIGNMENT (insn); 114650503Sobrien if (length_align < insn_current_align) 114750503Sobrien insn_current_align = length_align; 114850503Sobrien 114990087Sobrien insn_last_address = INSN_ADDRESSES (uid); 115090087Sobrien INSN_ADDRESSES (uid) = insn_current_address; 115150503Sobrien 115250503Sobrien#ifdef CASE_VECTOR_SHORTEN_MODE 1153169699Skan if (optimize && JUMP_P (insn) 115450503Sobrien && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) 115518334Speter { 115650503Sobrien rtx body = PATTERN (insn); 115750503Sobrien int old_length = insn_lengths[uid]; 115850503Sobrien rtx rel_lab = XEXP (XEXP (body, 0), 0); 115950503Sobrien rtx min_lab = XEXP (XEXP (body, 2), 0); 116050503Sobrien rtx max_lab = XEXP (XEXP (body, 3), 0); 116190087Sobrien int rel_addr = INSN_ADDRESSES (INSN_UID (rel_lab)); 116290087Sobrien int min_addr = INSN_ADDRESSES (INSN_UID (min_lab)); 116390087Sobrien int max_addr = INSN_ADDRESSES (INSN_UID (max_lab)); 116450503Sobrien rtx prev; 116550503Sobrien int rel_align = 0; 116690087Sobrien addr_diff_vec_flags flags; 116750503Sobrien 116890087Sobrien /* Avoid automatic aggregate initialization. */ 116990087Sobrien flags = ADDR_DIFF_VEC_FLAGS (body); 117090087Sobrien 117150503Sobrien /* Try to find a known alignment for rel_lab. */ 117250503Sobrien for (prev = rel_lab; 117350503Sobrien prev 117450503Sobrien && ! insn_lengths[INSN_UID (prev)] 117550503Sobrien && ! (varying_length[INSN_UID (prev)] & 1); 117650503Sobrien prev = PREV_INSN (prev)) 117750503Sobrien if (varying_length[INSN_UID (prev)] & 2) 117850503Sobrien { 117950503Sobrien rel_align = LABEL_TO_ALIGNMENT (prev); 118050503Sobrien break; 118150503Sobrien } 118250503Sobrien 118350503Sobrien /* See the comment on addr_diff_vec_flags in rtl.h for the 118450503Sobrien meaning of the flags values. base: REL_LAB vec: INSN */ 118550503Sobrien /* Anything after INSN has still addresses from the last 118650503Sobrien pass; adjust these so that they reflect our current 118750503Sobrien estimate for this pass. */ 118850503Sobrien if (flags.base_after_vec) 118950503Sobrien rel_addr += insn_current_address - insn_last_address; 119050503Sobrien if (flags.min_after_vec) 119150503Sobrien min_addr += insn_current_address - insn_last_address; 119250503Sobrien if (flags.max_after_vec) 119350503Sobrien max_addr += insn_current_address - insn_last_address; 119450503Sobrien /* We want to know the worst case, i.e. lowest possible value 119550503Sobrien for the offset of MIN_LAB. If MIN_LAB is after REL_LAB, 119650503Sobrien its offset is positive, and we have to be wary of code shrink; 119750503Sobrien otherwise, it is negative, and we have to be vary of code 119850503Sobrien size increase. */ 119950503Sobrien if (flags.min_after_base) 120050503Sobrien { 120150503Sobrien /* If INSN is between REL_LAB and MIN_LAB, the size 120250503Sobrien changes we are about to make can change the alignment 120350503Sobrien within the observed offset, therefore we have to break 120450503Sobrien it up into two parts that are independent. */ 120550503Sobrien if (! flags.base_after_vec && flags.min_after_vec) 120650503Sobrien { 120750503Sobrien min_addr -= align_fuzz (rel_lab, insn, rel_align, 0); 120850503Sobrien min_addr -= align_fuzz (insn, min_lab, 0, 0); 120950503Sobrien } 121050503Sobrien else 121150503Sobrien min_addr -= align_fuzz (rel_lab, min_lab, rel_align, 0); 121250503Sobrien } 121350503Sobrien else 121450503Sobrien { 121550503Sobrien if (flags.base_after_vec && ! flags.min_after_vec) 121650503Sobrien { 121750503Sobrien min_addr -= align_fuzz (min_lab, insn, 0, ~0); 121850503Sobrien min_addr -= align_fuzz (insn, rel_lab, 0, ~0); 121950503Sobrien } 122050503Sobrien else 122150503Sobrien min_addr -= align_fuzz (min_lab, rel_lab, 0, ~0); 122250503Sobrien } 122350503Sobrien /* Likewise, determine the highest lowest possible value 122450503Sobrien for the offset of MAX_LAB. */ 122550503Sobrien if (flags.max_after_base) 122650503Sobrien { 122750503Sobrien if (! flags.base_after_vec && flags.max_after_vec) 122850503Sobrien { 122950503Sobrien max_addr += align_fuzz (rel_lab, insn, rel_align, ~0); 123050503Sobrien max_addr += align_fuzz (insn, max_lab, 0, ~0); 123150503Sobrien } 123250503Sobrien else 123350503Sobrien max_addr += align_fuzz (rel_lab, max_lab, rel_align, ~0); 123450503Sobrien } 123550503Sobrien else 123650503Sobrien { 123750503Sobrien if (flags.base_after_vec && ! flags.max_after_vec) 123850503Sobrien { 123950503Sobrien max_addr += align_fuzz (max_lab, insn, 0, 0); 124050503Sobrien max_addr += align_fuzz (insn, rel_lab, 0, 0); 124150503Sobrien } 124250503Sobrien else 124350503Sobrien max_addr += align_fuzz (max_lab, rel_lab, 0, 0); 124450503Sobrien } 124550503Sobrien PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr, 124650503Sobrien max_addr - rel_addr, 124750503Sobrien body)); 1248169699Skan if (JUMP_TABLES_IN_TEXT_SECTION 1249169699Skan || readonly_data_section == text_section) 125050503Sobrien { 125150503Sobrien insn_lengths[uid] 125250503Sobrien = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body))); 125350503Sobrien insn_current_address += insn_lengths[uid]; 125450503Sobrien if (insn_lengths[uid] != old_length) 125550503Sobrien something_changed = 1; 125650503Sobrien } 125750503Sobrien 125850503Sobrien continue; 125950503Sobrien } 126050503Sobrien#endif /* CASE_VECTOR_SHORTEN_MODE */ 126150503Sobrien 126250503Sobrien if (! (varying_length[uid])) 126350503Sobrien { 1264169699Skan if (NONJUMP_INSN_P (insn) 126590087Sobrien && GET_CODE (PATTERN (insn)) == SEQUENCE) 126690087Sobrien { 126790087Sobrien int i; 126890087Sobrien 126990087Sobrien body = PATTERN (insn); 127090087Sobrien for (i = 0; i < XVECLEN (body, 0); i++) 127190087Sobrien { 127290087Sobrien rtx inner_insn = XVECEXP (body, 0, i); 127390087Sobrien int inner_uid = INSN_UID (inner_insn); 127490087Sobrien 127590087Sobrien INSN_ADDRESSES (inner_uid) = insn_current_address; 127690087Sobrien 127790087Sobrien insn_current_address += insn_lengths[inner_uid]; 127890087Sobrien } 1279117404Skan } 128090087Sobrien else 128190087Sobrien insn_current_address += insn_lengths[uid]; 128290087Sobrien 128318334Speter continue; 128418334Speter } 128590087Sobrien 1286169699Skan if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE) 128718334Speter { 128818334Speter int i; 128990087Sobrien 129018334Speter body = PATTERN (insn); 129118334Speter new_length = 0; 129218334Speter for (i = 0; i < XVECLEN (body, 0); i++) 129318334Speter { 129418334Speter rtx inner_insn = XVECEXP (body, 0, i); 129518334Speter int inner_uid = INSN_UID (inner_insn); 129618334Speter int inner_length; 129718334Speter 129890087Sobrien INSN_ADDRESSES (inner_uid) = insn_current_address; 129918334Speter 130018334Speter /* insn_current_length returns 0 for insns with a 130118334Speter non-varying length. */ 130218334Speter if (! varying_length[inner_uid]) 130318334Speter inner_length = insn_lengths[inner_uid]; 130418334Speter else 130518334Speter inner_length = insn_current_length (inner_insn); 130618334Speter 130718334Speter if (inner_length != insn_lengths[inner_uid]) 130818334Speter { 130918334Speter insn_lengths[inner_uid] = inner_length; 131018334Speter something_changed = 1; 131118334Speter } 131218334Speter insn_current_address += insn_lengths[inner_uid]; 131318334Speter new_length += inner_length; 131418334Speter } 131518334Speter } 131618334Speter else 131718334Speter { 131818334Speter new_length = insn_current_length (insn); 131918334Speter insn_current_address += new_length; 132018334Speter } 132118334Speter 132218334Speter#ifdef ADJUST_INSN_LENGTH 132318334Speter /* If needed, do any adjustment. */ 132418334Speter tmp_length = new_length; 132518334Speter ADJUST_INSN_LENGTH (insn, new_length); 132618334Speter insn_current_address += (new_length - tmp_length); 132718334Speter#endif 132818334Speter 132918334Speter if (new_length != insn_lengths[uid]) 133018334Speter { 133118334Speter insn_lengths[uid] = new_length; 133218334Speter something_changed = 1; 133318334Speter } 133418334Speter } 133518334Speter /* For a non-optimizing compile, do only a single pass. */ 133618334Speter if (!optimize) 133718334Speter break; 133818334Speter } 133950503Sobrien 134050503Sobrien free (varying_length); 134150503Sobrien 134218334Speter#endif /* HAVE_ATTR_length */ 134318334Speter} 134418334Speter 134518334Speter#ifdef HAVE_ATTR_length 134618334Speter/* Given the body of an INSN known to be generated by an ASM statement, return 134718334Speter the number of machine instructions likely to be generated for this insn. 134818334Speter This is used to compute its length. */ 134918334Speter 135018334Speterstatic int 1351132727Skanasm_insn_count (rtx body) 135218334Speter{ 135390087Sobrien const char *template; 135418334Speter int count = 1; 135518334Speter 135618334Speter if (GET_CODE (body) == ASM_INPUT) 135718334Speter template = XSTR (body, 0); 135818334Speter else 135990087Sobrien template = decode_asm_operands (body, NULL, NULL, NULL, NULL); 136018334Speter 136190087Sobrien for (; *template; template++) 136290087Sobrien if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n') 136318334Speter count++; 136418334Speter 136518334Speter return count; 136618334Speter} 136718334Speter#endif 136818334Speter 136918334Speter/* Output assembler code for the start of a function, 137018334Speter and initialize some of the variables in this file 137118334Speter for the new function. The label for the function and associated 137218334Speter assembler pseudo-ops have already been output in `assemble_start_function'. 137318334Speter 137418334Speter FIRST is the first insn of the rtl for the function being compiled. 137518334Speter FILE is the file to write assembler code to. 137618334Speter OPTIMIZE is nonzero if we should eliminate redundant 137718334Speter test and compare insns. */ 137818334Speter 137918334Spetervoid 1380132727Skanfinal_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, 1381132727Skan int optimize ATTRIBUTE_UNUSED) 138218334Speter{ 138318334Speter block_depth = 0; 138418334Speter 138518334Speter this_is_asm_operands = 0; 138618334Speter 1387132727Skan last_filename = locator_file (prologue_locator); 1388132727Skan last_linenum = locator_line (prologue_locator); 138918334Speter 139090087Sobrien high_block_linenum = high_function_linenum = last_linenum; 139118334Speter 139290087Sobrien (*debug_hooks->begin_prologue) (last_linenum, last_filename); 139350503Sobrien 1394169699Skan#if defined (DWARF2_UNWIND_INFO) || defined (TARGET_UNWIND_INFO) 139590087Sobrien if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG) 139690087Sobrien dwarf2out_begin_prologue (0, NULL); 139718334Speter#endif 139818334Speter 139918334Speter#ifdef LEAF_REG_REMAP 140052515Sobrien if (current_function_uses_only_leaf_regs) 140118334Speter leaf_renumber_regs (first); 140218334Speter#endif 140318334Speter 140418334Speter /* The Sun386i and perhaps other machines don't work right 140518334Speter if the profiling code comes after the prologue. */ 140618334Speter#ifdef PROFILE_BEFORE_PROLOGUE 140790087Sobrien if (current_function_profile) 140818334Speter profile_function (file); 140918334Speter#endif /* PROFILE_BEFORE_PROLOGUE */ 141018334Speter 141150503Sobrien#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue) 141250503Sobrien if (dwarf2out_do_frame ()) 1413169699Skan dwarf2out_frame_debug (NULL_RTX, false); 141450503Sobrien#endif 141550503Sobrien 141690087Sobrien /* If debugging, assign block numbers to all of the blocks in this 141790087Sobrien function. */ 141890087Sobrien if (write_symbols) 141990087Sobrien { 1420132727Skan reemit_insn_block_notes (); 142190087Sobrien number_blocks (current_function_decl); 142290087Sobrien /* We never actually put out begin/end notes for the top-level 142390087Sobrien block in the function. But, conceptually, that block is 142490087Sobrien always needed. */ 142590087Sobrien TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1; 142690087Sobrien } 142790087Sobrien 142818334Speter /* First output the function prologue: code to set up the stack frame. */ 1429169699Skan targetm.asm_out.function_prologue (file, get_frame_size ()); 143018334Speter 143118334Speter /* If the machine represents the prologue as RTL, the profiling code must 143218334Speter be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ 143318334Speter#ifdef HAVE_prologue 143418334Speter if (! HAVE_prologue) 143518334Speter#endif 143618334Speter profile_after_prologue (file); 143718334Speter} 143818334Speter 143918334Speterstatic void 1440132727Skanprofile_after_prologue (FILE *file ATTRIBUTE_UNUSED) 144118334Speter{ 144218334Speter#ifndef PROFILE_BEFORE_PROLOGUE 144390087Sobrien if (current_function_profile) 144418334Speter profile_function (file); 144518334Speter#endif /* not PROFILE_BEFORE_PROLOGUE */ 144618334Speter} 144718334Speter 144818334Speterstatic void 1449132727Skanprofile_function (FILE *file ATTRIBUTE_UNUSED) 145018334Speter{ 145174478Sobrien#ifndef NO_PROFILE_COUNTERS 1452132727Skan# define NO_PROFILE_COUNTERS 0 145374478Sobrien#endif 145450503Sobrien#if defined(ASM_OUTPUT_REG_PUSH) 145518334Speter int sval = current_function_returns_struct; 1456132727Skan rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1); 145750503Sobrien#if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM) 1458169699Skan int cxt = cfun->static_chain_decl != NULL; 145950503Sobrien#endif 146050503Sobrien#endif /* ASM_OUTPUT_REG_PUSH */ 146118334Speter 1462132727Skan if (! NO_PROFILE_COUNTERS) 1463132727Skan { 1464132727Skan int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE); 1465169699Skan switch_to_section (data_section); 1466132727Skan ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); 1467169699Skan targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no); 1468132727Skan assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1); 1469132727Skan } 147018334Speter 1471169699Skan switch_to_section (current_function_section ()); 147218334Speter 1473132727Skan#if defined(ASM_OUTPUT_REG_PUSH) 1474169699Skan if (sval && svrtx != NULL_RTX && REG_P (svrtx)) 1475132727Skan ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx)); 147618334Speter#endif 147718334Speter 147850503Sobrien#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) 147918334Speter if (cxt) 148018334Speter ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM); 148118334Speter#else 148250503Sobrien#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) 148318334Speter if (cxt) 148450503Sobrien { 148550503Sobrien ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM); 148650503Sobrien } 148718334Speter#endif 148818334Speter#endif 148918334Speter 1490117404Skan FUNCTION_PROFILER (file, current_function_funcdef_no); 149118334Speter 149250503Sobrien#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) 149318334Speter if (cxt) 149418334Speter ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM); 149518334Speter#else 149650503Sobrien#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) 149718334Speter if (cxt) 149850503Sobrien { 149950503Sobrien ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM); 150050503Sobrien } 150118334Speter#endif 150218334Speter#endif 150318334Speter 1504132727Skan#if defined(ASM_OUTPUT_REG_PUSH) 1505169699Skan if (sval && svrtx != NULL_RTX && REG_P (svrtx)) 1506132727Skan ASM_OUTPUT_REG_POP (file, REGNO (svrtx)); 150718334Speter#endif 150818334Speter} 150918334Speter 151018334Speter/* Output assembler code for the end of a function. 151118334Speter For clarity, args are same as those of `final_start_function' 151218334Speter even though not all of them are needed. */ 151318334Speter 151418334Spetervoid 1515132727Skanfinal_end_function (void) 151618334Speter{ 151790087Sobrien app_disable (); 151818334Speter 151990087Sobrien (*debug_hooks->end_function) (high_function_linenum); 152018334Speter 152118334Speter /* Finally, output the function epilogue: 152218334Speter code to restore the stack frame and return to the caller. */ 1523169699Skan targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ()); 152418334Speter 152590087Sobrien /* And debug output. */ 1526117404Skan (*debug_hooks->end_epilogue) (last_linenum, last_filename); 152790087Sobrien 152890087Sobrien#if defined (DWARF2_UNWIND_INFO) 152990087Sobrien if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG 153090087Sobrien && dwarf2out_do_frame ()) 1531117404Skan dwarf2out_end_epilogue (last_linenum, last_filename); 153250503Sobrien#endif 153318334Speter} 153418334Speter 153518334Speter/* Output assembler code for some insns: all or part of a function. 1536169699Skan For description of args, see `final_start_function', above. */ 153718334Speter 153818334Spetervoid 1539169699Skanfinal (rtx first, FILE *file, int optimize) 154018334Speter{ 154190087Sobrien rtx insn; 154250503Sobrien int max_uid = 0; 1543132727Skan int seen = 0; 154418334Speter 154518334Speter last_ignored_compare = 0; 154618334Speter 1547132727Skan#ifdef SDB_DEBUGGING_INFO 1548132727Skan /* When producing SDB debugging info, delete troublesome line number 154918334Speter notes from inlined functions in other files as well as duplicate 155018334Speter line number notes. */ 155118334Speter if (write_symbols == SDB_DEBUG) 155218334Speter { 155318334Speter rtx last = 0; 155418334Speter for (insn = first; insn; insn = NEXT_INSN (insn)) 1555169699Skan if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0) 155618334Speter { 1557169699Skan if (last != 0 1558169699Skan#ifdef USE_MAPPED_LOCATION 1559169699Skan && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last) 1560169699Skan#else 1561169699Skan && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last) 1562169699Skan && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last) 1563169699Skan#endif 1564169699Skan ) 156518334Speter { 156690087Sobrien delete_insn (insn); /* Use delete_note. */ 156718334Speter continue; 156818334Speter } 156918334Speter last = insn; 157018334Speter } 157118334Speter } 157218334Speter#endif 157318334Speter 157418334Speter for (insn = first; insn; insn = NEXT_INSN (insn)) 157550503Sobrien { 1576132727Skan if (INSN_UID (insn) > max_uid) /* Find largest UID. */ 157790087Sobrien max_uid = INSN_UID (insn); 157852515Sobrien#ifdef HAVE_cc0 157952515Sobrien /* If CC tracking across branches is enabled, record the insn which 158052515Sobrien jumps to each branch only reached from one place. */ 1581169699Skan if (optimize && JUMP_P (insn)) 158252515Sobrien { 158352515Sobrien rtx lab = JUMP_LABEL (insn); 158452515Sobrien if (lab && LABEL_NUSES (lab) == 1) 158552515Sobrien { 158652515Sobrien LABEL_REFS (lab) = insn; 158752515Sobrien } 158852515Sobrien } 158952515Sobrien#endif 159050503Sobrien } 159118334Speter 159218334Speter init_recog (); 159318334Speter 159418334Speter CC_STATUS_INIT; 159518334Speter 159618334Speter /* Output the insns. */ 159718334Speter for (insn = NEXT_INSN (first); insn;) 159850503Sobrien { 159950503Sobrien#ifdef HAVE_ATTR_length 160090087Sobrien if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ()) 160190087Sobrien { 160290087Sobrien /* This can be triggered by bugs elsewhere in the compiler if 160390087Sobrien new insns are created after init_insn_lengths is called. */ 1604169699Skan gcc_assert (NOTE_P (insn)); 1605169699Skan insn_current_address = -1; 160690087Sobrien } 160790087Sobrien else 160890087Sobrien insn_current_address = INSN_ADDRESSES (INSN_UID (insn)); 160990087Sobrien#endif /* HAVE_ATTR_length */ 161090087Sobrien 1611169699Skan insn = final_scan_insn (insn, file, optimize, 0, &seen); 161250503Sobrien } 161390087Sobrien} 161490087Sobrien 161590087Sobrienconst char * 1616132727Skanget_insn_template (int code, rtx insn) 161790087Sobrien{ 161890087Sobrien switch (insn_data[code].output_format) 161990087Sobrien { 162090087Sobrien case INSN_OUTPUT_FORMAT_SINGLE: 1621132727Skan return insn_data[code].output.single; 162290087Sobrien case INSN_OUTPUT_FORMAT_MULTI: 1623132727Skan return insn_data[code].output.multi[which_alternative]; 162490087Sobrien case INSN_OUTPUT_FORMAT_FUNCTION: 1625169699Skan gcc_assert (insn); 1626132727Skan return (*insn_data[code].output.function) (recog_data.operand, insn); 162750503Sobrien 162890087Sobrien default: 1629169699Skan gcc_unreachable (); 163090087Sobrien } 163118334Speter} 163290087Sobrien 1633117404Skan/* Emit the appropriate declaration for an alternate-entry-point 1634117404Skan symbol represented by INSN, to FILE. INSN is a CODE_LABEL with 1635117404Skan LABEL_KIND != LABEL_NORMAL. 1636117404Skan 1637117404Skan The case fall-through in this function is intentional. */ 1638117404Skanstatic void 1639132727Skanoutput_alternate_entry_point (FILE *file, rtx insn) 1640117404Skan{ 1641117404Skan const char *name = LABEL_NAME (insn); 1642117404Skan 1643117404Skan switch (LABEL_KIND (insn)) 1644117404Skan { 1645117404Skan case LABEL_WEAK_ENTRY: 1646117404Skan#ifdef ASM_WEAKEN_LABEL 1647117404Skan ASM_WEAKEN_LABEL (file, name); 1648117404Skan#endif 1649117404Skan case LABEL_GLOBAL_ENTRY: 1650169699Skan targetm.asm_out.globalize_label (file, name); 1651117404Skan case LABEL_STATIC_ENTRY: 1652117404Skan#ifdef ASM_OUTPUT_TYPE_DIRECTIVE 1653117404Skan ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); 1654117404Skan#endif 1655117404Skan ASM_OUTPUT_LABEL (file, name); 1656117404Skan break; 1657117404Skan 1658117404Skan case LABEL_NORMAL: 1659117404Skan default: 1660169699Skan gcc_unreachable (); 1661117404Skan } 1662117404Skan} 1663117404Skan 166418334Speter/* The final scan for one insn, INSN. 166518334Speter Args are same as in `final', except that INSN 166618334Speter is the insn being scanned. 166718334Speter Value returned is the next insn to be scanned. 166818334Speter 166918334Speter NOPEEPHOLES is the flag to disallow peephole processing (currently 1670132727Skan used for within delayed branch sequence output). 167118334Speter 1672132727Skan SEEN is used to track the end of the prologue, for emitting 1673132727Skan debug information. We force the emission of a line note after 1674132727Skan both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG, or 1675132727Skan at the beginning of the second basic block, whichever comes 1676132727Skan first. */ 1677132727Skan 167818334Speterrtx 1679132727Skanfinal_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, 1680169699Skan int nopeepholes ATTRIBUTE_UNUSED, int *seen) 168118334Speter{ 168250503Sobrien#ifdef HAVE_cc0 168350503Sobrien rtx set; 168450503Sobrien#endif 1685169699Skan rtx next; 168650503Sobrien 168718334Speter insn_counter++; 168818334Speter 168918334Speter /* Ignore deleted insns. These can occur when we split insns (due to a 169018334Speter template of "#") while not optimizing. */ 169118334Speter if (INSN_DELETED_P (insn)) 169218334Speter return NEXT_INSN (insn); 169318334Speter 169418334Speter switch (GET_CODE (insn)) 169518334Speter { 169618334Speter case NOTE: 169790087Sobrien switch (NOTE_LINE_NUMBER (insn)) 169818334Speter { 169990087Sobrien case NOTE_INSN_DELETED: 170090087Sobrien case NOTE_INSN_FUNCTION_END: 170190087Sobrien case NOTE_INSN_REPEATED_LINE_NUMBER: 170290087Sobrien case NOTE_INSN_EXPECTED_VALUE: 170318334Speter break; 170418334Speter 1705169699Skan case NOTE_INSN_SWITCH_TEXT_SECTIONS: 1706169699Skan in_cold_section_p = !in_cold_section_p; 1707169699Skan (*debug_hooks->switch_text_section) (); 1708169699Skan switch_to_section (current_function_section ()); 1709169699Skan break; 1710169699Skan 171190087Sobrien case NOTE_INSN_BASIC_BLOCK: 1712169699Skan#ifdef TARGET_UNWIND_INFO 1713169699Skan targetm.asm_out.unwind_emit (asm_out_file, insn); 171450503Sobrien#endif 1715169699Skan 171690087Sobrien if (flag_debug_asm) 171790087Sobrien fprintf (asm_out_file, "\t%s basic block %d\n", 171890087Sobrien ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index); 1719132727Skan 1720132727Skan if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB) 1721132727Skan { 1722132727Skan *seen |= SEEN_EMITTED; 1723169699Skan force_source_line = true; 1724132727Skan } 1725132727Skan else 1726132727Skan *seen |= SEEN_BB; 1727132727Skan 172850503Sobrien break; 172950503Sobrien 173090087Sobrien case NOTE_INSN_EH_REGION_BEG: 173190087Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB", 173290087Sobrien NOTE_EH_HANDLER (insn)); 173390087Sobrien break; 173490087Sobrien 173590087Sobrien case NOTE_INSN_EH_REGION_END: 173690087Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE", 173790087Sobrien NOTE_EH_HANDLER (insn)); 173890087Sobrien break; 173990087Sobrien 174090087Sobrien case NOTE_INSN_PROLOGUE_END: 1741169699Skan targetm.asm_out.function_end_prologue (file); 174218334Speter profile_after_prologue (file); 1743132727Skan 1744132727Skan if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE) 1745132727Skan { 1746132727Skan *seen |= SEEN_EMITTED; 1747169699Skan force_source_line = true; 1748132727Skan } 1749132727Skan else 1750132727Skan *seen |= SEEN_NOTE; 1751132727Skan 175218334Speter break; 175318334Speter 175490087Sobrien case NOTE_INSN_EPILOGUE_BEG: 1755169699Skan targetm.asm_out.function_begin_epilogue (file); 175618334Speter break; 175718334Speter 175890087Sobrien case NOTE_INSN_FUNCTION_BEG: 175990087Sobrien app_disable (); 1760117404Skan (*debug_hooks->end_prologue) (last_linenum, last_filename); 1761132727Skan 1762132727Skan if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE) 1763132727Skan { 1764132727Skan *seen |= SEEN_EMITTED; 1765169699Skan force_source_line = true; 1766132727Skan } 1767132727Skan else 1768132727Skan *seen |= SEEN_NOTE; 1769132727Skan 177018334Speter break; 177190087Sobrien 177290087Sobrien case NOTE_INSN_BLOCK_BEG: 177390087Sobrien if (debug_info_level == DINFO_LEVEL_NORMAL 177418334Speter || debug_info_level == DINFO_LEVEL_VERBOSE 177590087Sobrien || write_symbols == DWARF2_DEBUG 177690087Sobrien || write_symbols == VMS_AND_DWARF2_DEBUG 177790087Sobrien || write_symbols == VMS_DEBUG) 177890087Sobrien { 177990087Sobrien int n = BLOCK_NUMBER (NOTE_BLOCK (insn)); 178018334Speter 178190087Sobrien app_disable (); 178290087Sobrien ++block_depth; 178390087Sobrien high_block_linenum = last_linenum; 178490087Sobrien 178590087Sobrien /* Output debugging info about the symbol-block beginning. */ 178690087Sobrien (*debug_hooks->begin_block) (last_linenum, n); 178790087Sobrien 178890087Sobrien /* Mark this block as output. */ 178990087Sobrien TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1; 179018334Speter } 179190087Sobrien break; 179218334Speter 179390087Sobrien case NOTE_INSN_BLOCK_END: 179490087Sobrien if (debug_info_level == DINFO_LEVEL_NORMAL 179590087Sobrien || debug_info_level == DINFO_LEVEL_VERBOSE 179690087Sobrien || write_symbols == DWARF2_DEBUG 179790087Sobrien || write_symbols == VMS_AND_DWARF2_DEBUG 179890087Sobrien || write_symbols == VMS_DEBUG) 179990087Sobrien { 180090087Sobrien int n = BLOCK_NUMBER (NOTE_BLOCK (insn)); 180118334Speter 180290087Sobrien app_disable (); 180318334Speter 180490087Sobrien /* End of a symbol-block. */ 180590087Sobrien --block_depth; 1806169699Skan gcc_assert (block_depth >= 0); 180718334Speter 180890087Sobrien (*debug_hooks->end_block) (high_block_linenum, n); 180990087Sobrien } 181090087Sobrien break; 181118334Speter 181290087Sobrien case NOTE_INSN_DELETED_LABEL: 181390087Sobrien /* Emit the label. We may have deleted the CODE_LABEL because 181490087Sobrien the label could be proved to be unreachable, though still 181590087Sobrien referenced (in the form of having its address taken. */ 181690087Sobrien ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); 181790087Sobrien break; 181818334Speter 1819169699Skan case NOTE_INSN_VAR_LOCATION: 1820169699Skan (*debug_hooks->var_location) (insn); 1821169699Skan break; 1822169699Skan 182390087Sobrien case 0: 182490087Sobrien break; 182518334Speter 182690087Sobrien default: 1827169699Skan gcc_assert (NOTE_LINE_NUMBER (insn) > 0); 182890087Sobrien break; 182918334Speter } 183018334Speter break; 183118334Speter 183218334Speter case BARRIER: 183390087Sobrien#if defined (DWARF2_UNWIND_INFO) 183490087Sobrien if (dwarf2out_do_frame ()) 1835169699Skan dwarf2out_frame_debug (insn, false); 183618334Speter#endif 183718334Speter break; 183818334Speter 183918334Speter case CODE_LABEL: 184050503Sobrien /* The target port might emit labels in the output function for 184150503Sobrien some insn, e.g. sh.c output_branchy_insn. */ 184250503Sobrien if (CODE_LABEL_NUMBER (insn) <= max_labelno) 184350503Sobrien { 184450503Sobrien int align = LABEL_TO_ALIGNMENT (insn); 184550503Sobrien#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN 184650503Sobrien int max_skip = LABEL_TO_MAX_SKIP (insn); 184750503Sobrien#endif 184850503Sobrien 184950503Sobrien if (align && NEXT_INSN (insn)) 185090087Sobrien { 185150503Sobrien#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN 185290087Sobrien ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip); 185350503Sobrien#else 1854117404Skan#ifdef ASM_OUTPUT_ALIGN_WITH_NOP 1855117404Skan ASM_OUTPUT_ALIGN_WITH_NOP (file, align); 1856117404Skan#else 185790087Sobrien ASM_OUTPUT_ALIGN (file, align); 185850503Sobrien#endif 1859117404Skan#endif 186090087Sobrien } 186150503Sobrien } 186252515Sobrien#ifdef HAVE_cc0 186318334Speter CC_STATUS_INIT; 186452515Sobrien /* If this label is reached from only one place, set the condition 186552515Sobrien codes from the instruction just before the branch. */ 186652515Sobrien 186752515Sobrien /* Disabled because some insns set cc_status in the C output code 186852515Sobrien and NOTICE_UPDATE_CC alone can set incorrect status. */ 186952515Sobrien if (0 /* optimize && LABEL_NUSES (insn) == 1*/) 187052515Sobrien { 187152515Sobrien rtx jump = LABEL_REFS (insn); 187252515Sobrien rtx barrier = prev_nonnote_insn (insn); 187352515Sobrien rtx prev; 187452515Sobrien /* If the LABEL_REFS field of this label has been set to point 187552515Sobrien at a branch, the predecessor of the branch is a regular 187652515Sobrien insn, and that branch is the only way to reach this label, 187752515Sobrien set the condition codes based on the branch and its 187852515Sobrien predecessor. */ 1879169699Skan if (barrier && BARRIER_P (barrier) 1880169699Skan && jump && JUMP_P (jump) 188152515Sobrien && (prev = prev_nonnote_insn (jump)) 1882169699Skan && NONJUMP_INSN_P (prev)) 188352515Sobrien { 188452515Sobrien NOTICE_UPDATE_CC (PATTERN (prev), prev); 188552515Sobrien NOTICE_UPDATE_CC (PATTERN (jump), jump); 188652515Sobrien } 188752515Sobrien } 188852515Sobrien#endif 188950503Sobrien 189090087Sobrien if (LABEL_NAME (insn)) 189190087Sobrien (*debug_hooks->label) (insn); 189290087Sobrien 189318334Speter if (app_on) 189418334Speter { 189550503Sobrien fputs (ASM_APP_OFF, file); 189618334Speter app_on = 0; 189718334Speter } 1898169699Skan 1899169699Skan next = next_nonnote_insn (insn); 1900169699Skan if (next != 0 && JUMP_P (next)) 190118334Speter { 1902169699Skan rtx nextbody = PATTERN (next); 190318334Speter 190418334Speter /* If this label is followed by a jump-table, 190518334Speter make sure we put the label in the read-only section. Also 190618334Speter possibly write the label and jump table together. */ 190718334Speter 190818334Speter if (GET_CODE (nextbody) == ADDR_VEC 190918334Speter || GET_CODE (nextbody) == ADDR_DIFF_VEC) 191018334Speter { 191152515Sobrien#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC) 191252515Sobrien /* In this case, the case vector is being moved by the 191352515Sobrien target, so don't output the label at all. Leave that 191452515Sobrien to the back end macros. */ 191552515Sobrien#else 191650503Sobrien if (! JUMP_TABLES_IN_TEXT_SECTION) 191750503Sobrien { 191890087Sobrien int log_align; 191990087Sobrien 1920169699Skan switch_to_section (targetm.asm_out.function_rodata_section 1921169699Skan (current_function_decl)); 192290087Sobrien 192390087Sobrien#ifdef ADDR_VEC_ALIGN 1924169699Skan log_align = ADDR_VEC_ALIGN (next); 192590087Sobrien#else 192690087Sobrien log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); 192790087Sobrien#endif 192890087Sobrien ASM_OUTPUT_ALIGN (file, log_align); 192950503Sobrien } 193050503Sobrien else 1931169699Skan switch_to_section (current_function_section ()); 193250503Sobrien 193318334Speter#ifdef ASM_OUTPUT_CASE_LABEL 193418334Speter ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), 1935169699Skan next); 193618334Speter#else 1937169699Skan targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); 193818334Speter#endif 193952515Sobrien#endif 194018334Speter break; 194118334Speter } 194218334Speter } 1943117404Skan if (LABEL_ALT_ENTRY_P (insn)) 1944117404Skan output_alternate_entry_point (file, insn); 194590087Sobrien else 1946169699Skan targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); 194718334Speter break; 194818334Speter 194918334Speter default: 195018334Speter { 195190087Sobrien rtx body = PATTERN (insn); 195218334Speter int insn_code_number; 195352515Sobrien const char *template; 195418334Speter 1955169699Skan#ifdef HAVE_conditional_execution 1956169699Skan /* Reset this early so it is correct for ASM statements. */ 1957169699Skan current_insn_predicate = NULL_RTX; 1958169699Skan#endif 195918334Speter /* An INSN, JUMP_INSN or CALL_INSN. 196018334Speter First check for special kinds that recog doesn't recognize. */ 196118334Speter 1962132727Skan if (GET_CODE (body) == USE /* These are just declarations. */ 196318334Speter || GET_CODE (body) == CLOBBER) 196418334Speter break; 196518334Speter 196618334Speter#ifdef HAVE_cc0 1967169699Skan { 1968169699Skan /* If there is a REG_CC_SETTER note on this insn, it means that 1969169699Skan the setting of the condition code was done in the delay slot 1970169699Skan of the insn that branched here. So recover the cc status 1971169699Skan from the insn that set it. */ 197218334Speter 1973169699Skan rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); 1974169699Skan if (note) 1975169699Skan { 1976169699Skan NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0)); 1977169699Skan cc_prev_status = cc_status; 1978169699Skan } 1979169699Skan } 198018334Speter#endif 198118334Speter 198218334Speter /* Detect insns that are really jump-tables 198318334Speter and output them as such. */ 198418334Speter 198518334Speter if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 198618334Speter { 198752515Sobrien#if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)) 198890087Sobrien int vlen, idx; 198952515Sobrien#endif 199018334Speter 1991169699Skan if (! JUMP_TABLES_IN_TEXT_SECTION) 1992169699Skan switch_to_section (targetm.asm_out.function_rodata_section 1993169699Skan (current_function_decl)); 1994169699Skan else 1995169699Skan switch_to_section (current_function_section ()); 199618334Speter 199718334Speter if (app_on) 199818334Speter { 199950503Sobrien fputs (ASM_APP_OFF, file); 200018334Speter app_on = 0; 200118334Speter } 200218334Speter 200352515Sobrien#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC) 200452515Sobrien if (GET_CODE (body) == ADDR_VEC) 200552515Sobrien { 200652515Sobrien#ifdef ASM_OUTPUT_ADDR_VEC 200752515Sobrien ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body); 200852515Sobrien#else 2009169699Skan gcc_unreachable (); 201052515Sobrien#endif 201152515Sobrien } 201252515Sobrien else 201352515Sobrien { 201452515Sobrien#ifdef ASM_OUTPUT_ADDR_DIFF_VEC 201552515Sobrien ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body); 201652515Sobrien#else 2017169699Skan gcc_unreachable (); 201852515Sobrien#endif 201952515Sobrien } 202052515Sobrien#else 202118334Speter vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC); 202218334Speter for (idx = 0; idx < vlen; idx++) 202318334Speter { 202418334Speter if (GET_CODE (body) == ADDR_VEC) 202518334Speter { 202618334Speter#ifdef ASM_OUTPUT_ADDR_VEC_ELT 202718334Speter ASM_OUTPUT_ADDR_VEC_ELT 202818334Speter (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); 202918334Speter#else 2030169699Skan gcc_unreachable (); 203118334Speter#endif 203218334Speter } 203318334Speter else 203418334Speter { 203518334Speter#ifdef ASM_OUTPUT_ADDR_DIFF_ELT 203618334Speter ASM_OUTPUT_ADDR_DIFF_ELT 203718334Speter (file, 203850503Sobrien body, 203918334Speter CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), 204018334Speter CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); 204118334Speter#else 2042169699Skan gcc_unreachable (); 204318334Speter#endif 204418334Speter } 204518334Speter } 204618334Speter#ifdef ASM_OUTPUT_CASE_END 204718334Speter ASM_OUTPUT_CASE_END (file, 204818334Speter CODE_LABEL_NUMBER (PREV_INSN (insn)), 204918334Speter insn); 205018334Speter#endif 205152515Sobrien#endif 205218334Speter 2053169699Skan switch_to_section (current_function_section ()); 205418334Speter 205518334Speter break; 205618334Speter } 2057132727Skan /* Output this line note if it is the first or the last line 2058132727Skan note in a row. */ 2059132727Skan if (notice_source_line (insn)) 2060132727Skan { 2061132727Skan (*debug_hooks->source_line) (last_linenum, last_filename); 2062132727Skan } 206318334Speter 206418334Speter if (GET_CODE (body) == ASM_INPUT) 206518334Speter { 206690087Sobrien const char *string = XSTR (body, 0); 206790087Sobrien 206818334Speter /* There's no telling what that did to the condition codes. */ 206918334Speter CC_STATUS_INIT; 207090087Sobrien 207190087Sobrien if (string[0]) 207218334Speter { 207390087Sobrien if (! app_on) 207490087Sobrien { 207590087Sobrien fputs (ASM_APP_ON, file); 207690087Sobrien app_on = 1; 207790087Sobrien } 207890087Sobrien fprintf (asm_out_file, "\t%s\n", string); 207918334Speter } 208018334Speter break; 208118334Speter } 208218334Speter 208318334Speter /* Detect `asm' construct with operands. */ 208418334Speter if (asm_noperands (body) >= 0) 208518334Speter { 208650503Sobrien unsigned int noperands = asm_noperands (body); 2087132727Skan rtx *ops = alloca (noperands * sizeof (rtx)); 208890087Sobrien const char *string; 208918334Speter 209018334Speter /* There's no telling what that did to the condition codes. */ 209118334Speter CC_STATUS_INIT; 209218334Speter 209318334Speter /* Get out the operand values. */ 209490087Sobrien string = decode_asm_operands (body, ops, NULL, NULL, NULL); 2095169699Skan /* Inhibit dieing on what would otherwise be compiler bugs. */ 209618334Speter insn_noperands = noperands; 209718334Speter this_is_asm_operands = insn; 209818334Speter 2099132727Skan#ifdef FINAL_PRESCAN_INSN 2100132727Skan FINAL_PRESCAN_INSN (insn, ops, insn_noperands); 2101132727Skan#endif 2102132727Skan 210318334Speter /* Output the insn using them. */ 210490087Sobrien if (string[0]) 210590087Sobrien { 210690087Sobrien if (! app_on) 210790087Sobrien { 210890087Sobrien fputs (ASM_APP_ON, file); 210990087Sobrien app_on = 1; 211090087Sobrien } 211190087Sobrien output_asm_insn (string, ops); 211290087Sobrien } 211390087Sobrien 211418334Speter this_is_asm_operands = 0; 211518334Speter break; 211618334Speter } 211718334Speter 2118169699Skan if (app_on) 211918334Speter { 212050503Sobrien fputs (ASM_APP_OFF, file); 212118334Speter app_on = 0; 212218334Speter } 212318334Speter 212418334Speter if (GET_CODE (body) == SEQUENCE) 212518334Speter { 212618334Speter /* A delayed-branch sequence */ 212790087Sobrien int i; 212818334Speter 212918334Speter final_sequence = body; 213018334Speter 2131132727Skan /* Record the delay slots' frame information before the branch. 2132132727Skan This is needed for delayed calls: see execute_cfa_program(). */ 2133132727Skan#if defined (DWARF2_UNWIND_INFO) 2134132727Skan if (dwarf2out_do_frame ()) 2135132727Skan for (i = 1; i < XVECLEN (body, 0); i++) 2136169699Skan dwarf2out_frame_debug (XVECEXP (body, 0, i), false); 2137132727Skan#endif 2138132727Skan 213918334Speter /* The first insn in this SEQUENCE might be a JUMP_INSN that will 214018334Speter force the restoration of a comparison that was previously 214118334Speter thought unnecessary. If that happens, cancel this sequence 214218334Speter and cause that insn to be restored. */ 214318334Speter 2144169699Skan next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, 1, seen); 214518334Speter if (next != XVECEXP (body, 0, 1)) 214618334Speter { 214718334Speter final_sequence = 0; 214818334Speter return next; 214918334Speter } 215018334Speter 215118334Speter for (i = 1; i < XVECLEN (body, 0); i++) 215218334Speter { 215318334Speter rtx insn = XVECEXP (body, 0, i); 215418334Speter rtx next = NEXT_INSN (insn); 215518334Speter /* We loop in case any instruction in a delay slot gets 215618334Speter split. */ 215718334Speter do 2158169699Skan insn = final_scan_insn (insn, file, 0, 1, seen); 215918334Speter while (insn != next); 216018334Speter } 216118334Speter#ifdef DBR_OUTPUT_SEQEND 216218334Speter DBR_OUTPUT_SEQEND (file); 216318334Speter#endif 216418334Speter final_sequence = 0; 216518334Speter 216618334Speter /* If the insn requiring the delay slot was a CALL_INSN, the 216718334Speter insns in the delay slot are actually executed before the 216818334Speter called function. Hence we don't preserve any CC-setting 216918334Speter actions in these insns and the CC must be marked as being 217018334Speter clobbered by the function. */ 2171169699Skan if (CALL_P (XVECEXP (body, 0, 0))) 217250503Sobrien { 217350503Sobrien CC_STATUS_INIT; 217450503Sobrien } 217518334Speter break; 217618334Speter } 217718334Speter 217818334Speter /* We have a real machine instruction as rtl. */ 217918334Speter 218018334Speter body = PATTERN (insn); 218118334Speter 218218334Speter#ifdef HAVE_cc0 218390087Sobrien set = single_set (insn); 218450503Sobrien 218518334Speter /* Check for redundant test and compare instructions 218618334Speter (when the condition codes are already set up as desired). 218718334Speter This is done only when optimizing; if not optimizing, 218818334Speter it should be possible for the user to alter a variable 218918334Speter with the debugger in between statements 219018334Speter and the next statement should reexamine the variable 219118334Speter to compute the condition codes. */ 219218334Speter 219350503Sobrien if (optimize) 219418334Speter { 219550503Sobrien if (set 219650503Sobrien && GET_CODE (SET_DEST (set)) == CC0 219750503Sobrien && insn != last_ignored_compare) 219818334Speter { 219950503Sobrien if (GET_CODE (SET_SRC (set)) == SUBREG) 220090087Sobrien SET_SRC (set) = alter_subreg (&SET_SRC (set)); 220150503Sobrien else if (GET_CODE (SET_SRC (set)) == COMPARE) 220218334Speter { 220350503Sobrien if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG) 220450503Sobrien XEXP (SET_SRC (set), 0) 220590087Sobrien = alter_subreg (&XEXP (SET_SRC (set), 0)); 220650503Sobrien if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG) 220750503Sobrien XEXP (SET_SRC (set), 1) 220890087Sobrien = alter_subreg (&XEXP (SET_SRC (set), 1)); 220918334Speter } 221050503Sobrien if ((cc_status.value1 != 0 221150503Sobrien && rtx_equal_p (SET_SRC (set), cc_status.value1)) 221250503Sobrien || (cc_status.value2 != 0 221350503Sobrien && rtx_equal_p (SET_SRC (set), cc_status.value2))) 221450503Sobrien { 221550503Sobrien /* Don't delete insn if it has an addressing side-effect. */ 221690087Sobrien if (! FIND_REG_INC_NOTE (insn, NULL_RTX) 221750503Sobrien /* or if anything in it is volatile. */ 221850503Sobrien && ! volatile_refs_p (PATTERN (insn))) 221950503Sobrien { 222050503Sobrien /* We don't really delete the insn; just ignore it. */ 222150503Sobrien last_ignored_compare = insn; 222250503Sobrien break; 222350503Sobrien } 222450503Sobrien } 222518334Speter } 222618334Speter } 222718334Speter#endif 222818334Speter 222918334Speter#ifdef HAVE_cc0 223018334Speter /* If this is a conditional branch, maybe modify it 223118334Speter if the cc's are in a nonstandard state 223218334Speter so that it accomplishes the same thing that it would 223318334Speter do straightforwardly if the cc's were set up normally. */ 223418334Speter 223518334Speter if (cc_status.flags != 0 2236169699Skan && JUMP_P (insn) 223718334Speter && GET_CODE (body) == SET 223818334Speter && SET_DEST (body) == pc_rtx 223918334Speter && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE 2240169699Skan && COMPARISON_P (XEXP (SET_SRC (body), 0)) 2241169699Skan && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx) 224218334Speter { 224318334Speter /* This function may alter the contents of its argument 224418334Speter and clear some of the cc_status.flags bits. 224518334Speter It may also return 1 meaning condition now always true 224618334Speter or -1 meaning condition now always false 224718334Speter or 2 meaning condition nontrivial but altered. */ 224890087Sobrien int result = alter_cond (XEXP (SET_SRC (body), 0)); 224918334Speter /* If condition now has fixed value, replace the IF_THEN_ELSE 225018334Speter with its then-operand or its else-operand. */ 225118334Speter if (result == 1) 225218334Speter SET_SRC (body) = XEXP (SET_SRC (body), 1); 225318334Speter if (result == -1) 225418334Speter SET_SRC (body) = XEXP (SET_SRC (body), 2); 225518334Speter 225618334Speter /* The jump is now either unconditional or a no-op. 225718334Speter If it has become a no-op, don't try to output it. 225818334Speter (It would not be recognized.) */ 225918334Speter if (SET_SRC (body) == pc_rtx) 226018334Speter { 226190087Sobrien delete_insn (insn); 226218334Speter break; 226318334Speter } 226418334Speter else if (GET_CODE (SET_SRC (body)) == RETURN) 226518334Speter /* Replace (set (pc) (return)) with (return). */ 226618334Speter PATTERN (insn) = body = SET_SRC (body); 226718334Speter 226818334Speter /* Rerecognize the instruction if it has changed. */ 226918334Speter if (result != 0) 227018334Speter INSN_CODE (insn) = -1; 227118334Speter } 227218334Speter 227318334Speter /* Make same adjustments to instructions that examine the 227450503Sobrien condition codes without jumping and instructions that 227550503Sobrien handle conditional moves (if this machine has either one). */ 227618334Speter 227718334Speter if (cc_status.flags != 0 227850503Sobrien && set != 0) 227918334Speter { 228050503Sobrien rtx cond_rtx, then_rtx, else_rtx; 228190087Sobrien 2282169699Skan if (!JUMP_P (insn) 228350503Sobrien && GET_CODE (SET_SRC (set)) == IF_THEN_ELSE) 228418334Speter { 228550503Sobrien cond_rtx = XEXP (SET_SRC (set), 0); 228650503Sobrien then_rtx = XEXP (SET_SRC (set), 1); 228750503Sobrien else_rtx = XEXP (SET_SRC (set), 2); 228850503Sobrien } 228950503Sobrien else 229050503Sobrien { 229150503Sobrien cond_rtx = SET_SRC (set); 229250503Sobrien then_rtx = const_true_rtx; 229350503Sobrien else_rtx = const0_rtx; 229450503Sobrien } 229590087Sobrien 229650503Sobrien switch (GET_CODE (cond_rtx)) 229750503Sobrien { 229818334Speter case GTU: 229918334Speter case GT: 230018334Speter case LTU: 230118334Speter case LT: 230218334Speter case GEU: 230318334Speter case GE: 230418334Speter case LEU: 230518334Speter case LE: 230618334Speter case EQ: 230718334Speter case NE: 230818334Speter { 230990087Sobrien int result; 231050503Sobrien if (XEXP (cond_rtx, 0) != cc0_rtx) 231118334Speter break; 231250503Sobrien result = alter_cond (cond_rtx); 231318334Speter if (result == 1) 231450503Sobrien validate_change (insn, &SET_SRC (set), then_rtx, 0); 231518334Speter else if (result == -1) 231650503Sobrien validate_change (insn, &SET_SRC (set), else_rtx, 0); 231718334Speter else if (result == 2) 231818334Speter INSN_CODE (insn) = -1; 231950503Sobrien if (SET_DEST (set) == SET_SRC (set)) 232090087Sobrien delete_insn (insn); 232118334Speter } 232250503Sobrien break; 232350503Sobrien 232450503Sobrien default: 232550503Sobrien break; 232618334Speter } 232718334Speter } 232850503Sobrien 232918334Speter#endif 233018334Speter 233190087Sobrien#ifdef HAVE_peephole 233218334Speter /* Do machine-specific peephole optimizations if desired. */ 233318334Speter 233418334Speter if (optimize && !flag_no_peephole && !nopeepholes) 233518334Speter { 233618334Speter rtx next = peephole (insn); 233718334Speter /* When peepholing, if there were notes within the peephole, 233818334Speter emit them before the peephole. */ 233918334Speter if (next != 0 && next != NEXT_INSN (insn)) 234018334Speter { 2341169699Skan rtx note, prev = PREV_INSN (insn); 234218334Speter 234318334Speter for (note = NEXT_INSN (insn); note != next; 234418334Speter note = NEXT_INSN (note)) 2345169699Skan final_scan_insn (note, file, optimize, nopeepholes, seen); 234618334Speter 2347169699Skan /* Put the notes in the proper position for a later 2348169699Skan rescan. For example, the SH target can do this 2349169699Skan when generating a far jump in a delayed branch 2350169699Skan sequence. */ 235118334Speter note = NEXT_INSN (insn); 235218334Speter PREV_INSN (note) = prev; 235318334Speter NEXT_INSN (prev) = note; 235418334Speter NEXT_INSN (PREV_INSN (next)) = insn; 235518334Speter PREV_INSN (insn) = PREV_INSN (next); 235618334Speter NEXT_INSN (insn) = next; 235718334Speter PREV_INSN (next) = insn; 235818334Speter } 235918334Speter 236018334Speter /* PEEPHOLE might have changed this. */ 236118334Speter body = PATTERN (insn); 236218334Speter } 236390087Sobrien#endif 236418334Speter 236518334Speter /* Try to recognize the instruction. 236618334Speter If successful, verify that the operands satisfy the 236718334Speter constraints for the instruction. Crash if they don't, 236818334Speter since `reload' should have changed them so that they do. */ 236918334Speter 237018334Speter insn_code_number = recog_memoized (insn); 237152515Sobrien cleanup_subreg_operands (insn); 237218334Speter 2373117404Skan /* Dump the insn in the assembly for debugging. */ 2374117404Skan if (flag_dump_rtl_in_asm) 2375117404Skan { 2376117404Skan print_rtx_head = ASM_COMMENT_START; 2377117404Skan print_rtl_single (asm_out_file, insn); 2378117404Skan print_rtx_head = ""; 2379117404Skan } 238090087Sobrien 238190087Sobrien if (! constrain_operands_cached (1)) 238218334Speter fatal_insn_not_found (insn); 238318334Speter 238418334Speter /* Some target machines need to prescan each insn before 238518334Speter it is output. */ 238618334Speter 238718334Speter#ifdef FINAL_PRESCAN_INSN 238890087Sobrien FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands); 238918334Speter#endif 239018334Speter 239190087Sobrien#ifdef HAVE_conditional_execution 239290087Sobrien if (GET_CODE (PATTERN (insn)) == COND_EXEC) 239390087Sobrien current_insn_predicate = COND_EXEC_TEST (PATTERN (insn)); 239490087Sobrien#endif 239590087Sobrien 239618334Speter#ifdef HAVE_cc0 239718334Speter cc_prev_status = cc_status; 239818334Speter 239918334Speter /* Update `cc_status' for this instruction. 240018334Speter The instruction's output routine may change it further. 240118334Speter If the output routine for a jump insn needs to depend 240218334Speter on the cc status, it should look at cc_prev_status. */ 240318334Speter 240418334Speter NOTICE_UPDATE_CC (body, insn); 240518334Speter#endif 240618334Speter 240790087Sobrien current_output_insn = debug_insn = insn; 240818334Speter 240990087Sobrien#if defined (DWARF2_UNWIND_INFO) 2410169699Skan if (CALL_P (insn) && dwarf2out_do_frame ()) 2411169699Skan dwarf2out_frame_debug (insn, false); 241250503Sobrien#endif 241350503Sobrien 241490087Sobrien /* Find the proper template for this insn. */ 241590087Sobrien template = get_insn_template (insn_code_number, insn); 241618334Speter 241790087Sobrien /* If the C code returns 0, it means that it is a jump insn 241890087Sobrien which follows a deleted test insn, and that test insn 241990087Sobrien needs to be reinserted. */ 242018334Speter if (template == 0) 242118334Speter { 242290087Sobrien rtx prev; 242318334Speter 2424169699Skan gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare); 242590087Sobrien 242690087Sobrien /* We have already processed the notes between the setter and 242790087Sobrien the user. Make sure we don't process them again, this is 242890087Sobrien particularly important if one of the notes is a block 242990087Sobrien scope note or an EH note. */ 243090087Sobrien for (prev = insn; 243190087Sobrien prev != last_ignored_compare; 243290087Sobrien prev = PREV_INSN (prev)) 243318334Speter { 2434169699Skan if (NOTE_P (prev)) 243590087Sobrien delete_insn (prev); /* Use delete_note. */ 243618334Speter } 243790087Sobrien 243890087Sobrien return prev; 243918334Speter } 244018334Speter 244118334Speter /* If the template is the string "#", it means that this insn must 244218334Speter be split. */ 244318334Speter if (template[0] == '#' && template[1] == '\0') 244418334Speter { 244518334Speter rtx new = try_split (body, insn, 0); 244618334Speter 244718334Speter /* If we didn't split the insn, go away. */ 244818334Speter if (new == insn && PATTERN (new) == body) 244990087Sobrien fatal_insn ("could not split insn", insn); 245090087Sobrien 245150503Sobrien#ifdef HAVE_ATTR_length 245250503Sobrien /* This instruction should have been split in shorten_branches, 245350503Sobrien to ensure that we would have valid length info for the 245450503Sobrien splitees. */ 2455169699Skan gcc_unreachable (); 245650503Sobrien#endif 245750503Sobrien 245818334Speter return new; 245918334Speter } 246090087Sobrien 2461169699Skan#ifdef TARGET_UNWIND_INFO 2462169699Skan /* ??? This will put the directives in the wrong place if 2463169699Skan get_insn_template outputs assembly directly. However calling it 2464169699Skan before get_insn_template breaks if the insns is split. */ 2465169699Skan targetm.asm_out.unwind_emit (asm_out_file, insn); 2466169699Skan#endif 246718334Speter 246818334Speter /* Output assembler code from the template. */ 246990087Sobrien output_asm_insn (template, recog_data.operand); 247018334Speter 2471132727Skan /* If necessary, report the effect that the instruction has on 2472132727Skan the unwind info. We've already done this for delay slots 2473132727Skan and call instructions. */ 247450503Sobrien#if defined (DWARF2_UNWIND_INFO) 2475169699Skan if (final_sequence == 0 2476132727Skan#if !defined (HAVE_prologue) 2477132727Skan && !ACCUMULATE_OUTGOING_ARGS 2478132727Skan#endif 247990087Sobrien && dwarf2out_do_frame ()) 2480169699Skan dwarf2out_frame_debug (insn, true); 248150503Sobrien#endif 248250503Sobrien 248390087Sobrien current_output_insn = debug_insn = 0; 248418334Speter } 248518334Speter } 248618334Speter return NEXT_INSN (insn); 248718334Speter} 248818334Speter 2489169699Skan/* Return whether a source line note needs to be emitted before INSN. */ 249018334Speter 2491132727Skanstatic bool 2492132727Skannotice_source_line (rtx insn) 249318334Speter{ 2494132727Skan const char *filename = insn_file (insn); 2495132727Skan int linenum = insn_line (insn); 249618334Speter 2497169699Skan if (filename 2498169699Skan && (force_source_line 2499169699Skan || filename != last_filename 2500169699Skan || last_linenum != linenum)) 2501132727Skan { 2502169699Skan force_source_line = false; 2503132727Skan last_filename = filename; 2504132727Skan last_linenum = linenum; 2505132727Skan high_block_linenum = MAX (last_linenum, high_block_linenum); 2506132727Skan high_function_linenum = MAX (last_linenum, high_function_linenum); 2507132727Skan return true; 2508132727Skan } 2509132727Skan return false; 251018334Speter} 251118334Speter 251252515Sobrien/* For each operand in INSN, simplify (subreg (reg)) so that it refers 251352515Sobrien directly to the desired hard register. */ 251490087Sobrien 251552515Sobrienvoid 2516132727Skancleanup_subreg_operands (rtx insn) 251752515Sobrien{ 251852515Sobrien int i; 251990087Sobrien extract_insn_cached (insn); 252090087Sobrien for (i = 0; i < recog_data.n_operands; i++) 252152515Sobrien { 2522132727Skan /* The following test cannot use recog_data.operand when testing 252390087Sobrien for a SUBREG: the underlying object might have been changed 252490087Sobrien already if we are inside a match_operator expression that 252590087Sobrien matches the else clause. Instead we test the underlying 252690087Sobrien expression directly. */ 252790087Sobrien if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG) 252890087Sobrien recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]); 252990087Sobrien else if (GET_CODE (recog_data.operand[i]) == PLUS 253090087Sobrien || GET_CODE (recog_data.operand[i]) == MULT 2531169699Skan || MEM_P (recog_data.operand[i])) 253290087Sobrien recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i]); 253352515Sobrien } 253452515Sobrien 253590087Sobrien for (i = 0; i < recog_data.n_dups; i++) 253652515Sobrien { 253790087Sobrien if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG) 253890087Sobrien *recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]); 253990087Sobrien else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS 254090087Sobrien || GET_CODE (*recog_data.dup_loc[i]) == MULT 2541169699Skan || MEM_P (*recog_data.dup_loc[i])) 254290087Sobrien *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i]); 254352515Sobrien } 254452515Sobrien} 254552515Sobrien 254618334Speter/* If X is a SUBREG, replace it with a REG or a MEM, 254718334Speter based on the thing it is a subreg of. */ 254818334Speter 254918334Speterrtx 2550132727Skanalter_subreg (rtx *xp) 255118334Speter{ 255290087Sobrien rtx x = *xp; 255390087Sobrien rtx y = SUBREG_REG (x); 255450503Sobrien 255590087Sobrien /* simplify_subreg does not remove subreg from volatile references. 255690087Sobrien We are required to. */ 2557169699Skan if (MEM_P (y)) 2558169699Skan { 2559169699Skan int offset = SUBREG_BYTE (x); 2560169699Skan 2561169699Skan /* For paradoxical subregs on big-endian machines, SUBREG_BYTE 2562169699Skan contains 0 instead of the proper offset. See simplify_subreg. */ 2563169699Skan if (offset == 0 2564169699Skan && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x))) 2565169699Skan { 2566169699Skan int difference = GET_MODE_SIZE (GET_MODE (y)) 2567169699Skan - GET_MODE_SIZE (GET_MODE (x)); 2568169699Skan if (WORDS_BIG_ENDIAN) 2569169699Skan offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 2570169699Skan if (BYTES_BIG_ENDIAN) 2571169699Skan offset += difference % UNITS_PER_WORD; 2572169699Skan } 2573169699Skan 2574169699Skan *xp = adjust_address (y, GET_MODE (x), offset); 2575169699Skan } 257690087Sobrien else 257718334Speter { 257890087Sobrien rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y), 257990087Sobrien SUBREG_BYTE (x)); 258050503Sobrien 258190087Sobrien if (new != 0) 258290087Sobrien *xp = new; 2583169699Skan else if (REG_P (y)) 258490087Sobrien { 2585169699Skan /* Simplify_subreg can't handle some REG cases, but we have to. */ 2586169699Skan unsigned int regno = subreg_regno (x); 2587132727Skan *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, SUBREG_BYTE (x)); 258890087Sobrien } 258918334Speter } 259018334Speter 259190087Sobrien return *xp; 259218334Speter} 259318334Speter 259418334Speter/* Do alter_subreg on all the SUBREGs contained in X. */ 259518334Speter 259618334Speterstatic rtx 2597132727Skanwalk_alter_subreg (rtx *xp) 259818334Speter{ 259990087Sobrien rtx x = *xp; 260018334Speter switch (GET_CODE (x)) 260118334Speter { 260218334Speter case PLUS: 260318334Speter case MULT: 2604169699Skan case AND: 260590087Sobrien XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0)); 260690087Sobrien XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1)); 260718334Speter break; 260818334Speter 260918334Speter case MEM: 2610169699Skan case ZERO_EXTEND: 261190087Sobrien XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0)); 261218334Speter break; 261318334Speter 261418334Speter case SUBREG: 261590087Sobrien return alter_subreg (xp); 261690087Sobrien 261750503Sobrien default: 261850503Sobrien break; 261918334Speter } 262018334Speter 262190087Sobrien return *xp; 262218334Speter} 262318334Speter 262418334Speter#ifdef HAVE_cc0 262518334Speter 262618334Speter/* Given BODY, the body of a jump instruction, alter the jump condition 262718334Speter as required by the bits that are set in cc_status.flags. 262818334Speter Not all of the bits there can be handled at this level in all cases. 262918334Speter 263018334Speter The value is normally 0. 263118334Speter 1 means that the condition has become always true. 263218334Speter -1 means that the condition has become always false. 263318334Speter 2 means that COND has been altered. */ 263418334Speter 263518334Speterstatic int 2636132727Skanalter_cond (rtx cond) 263718334Speter{ 263818334Speter int value = 0; 263918334Speter 264018334Speter if (cc_status.flags & CC_REVERSED) 264118334Speter { 264218334Speter value = 2; 264318334Speter PUT_CODE (cond, swap_condition (GET_CODE (cond))); 264418334Speter } 264518334Speter 264618334Speter if (cc_status.flags & CC_INVERTED) 264718334Speter { 264818334Speter value = 2; 264918334Speter PUT_CODE (cond, reverse_condition (GET_CODE (cond))); 265018334Speter } 265118334Speter 265218334Speter if (cc_status.flags & CC_NOT_POSITIVE) 265318334Speter switch (GET_CODE (cond)) 265418334Speter { 265518334Speter case LE: 265618334Speter case LEU: 265718334Speter case GEU: 265818334Speter /* Jump becomes unconditional. */ 265918334Speter return 1; 266018334Speter 266118334Speter case GT: 266218334Speter case GTU: 266318334Speter case LTU: 266418334Speter /* Jump becomes no-op. */ 266518334Speter return -1; 266618334Speter 266718334Speter case GE: 266818334Speter PUT_CODE (cond, EQ); 266918334Speter value = 2; 267018334Speter break; 267118334Speter 267218334Speter case LT: 267318334Speter PUT_CODE (cond, NE); 267418334Speter value = 2; 267518334Speter break; 267690087Sobrien 267750503Sobrien default: 267850503Sobrien break; 267918334Speter } 268018334Speter 268118334Speter if (cc_status.flags & CC_NOT_NEGATIVE) 268218334Speter switch (GET_CODE (cond)) 268318334Speter { 268418334Speter case GE: 268518334Speter case GEU: 268618334Speter /* Jump becomes unconditional. */ 268718334Speter return 1; 268818334Speter 268918334Speter case LT: 269018334Speter case LTU: 269118334Speter /* Jump becomes no-op. */ 269218334Speter return -1; 269318334Speter 269418334Speter case LE: 269518334Speter case LEU: 269618334Speter PUT_CODE (cond, EQ); 269718334Speter value = 2; 269818334Speter break; 269918334Speter 270018334Speter case GT: 270118334Speter case GTU: 270218334Speter PUT_CODE (cond, NE); 270318334Speter value = 2; 270418334Speter break; 270590087Sobrien 270650503Sobrien default: 270750503Sobrien break; 270818334Speter } 270918334Speter 271018334Speter if (cc_status.flags & CC_NO_OVERFLOW) 271118334Speter switch (GET_CODE (cond)) 271218334Speter { 271318334Speter case GEU: 271418334Speter /* Jump becomes unconditional. */ 271518334Speter return 1; 271618334Speter 271718334Speter case LEU: 271818334Speter PUT_CODE (cond, EQ); 271918334Speter value = 2; 272018334Speter break; 272118334Speter 272218334Speter case GTU: 272318334Speter PUT_CODE (cond, NE); 272418334Speter value = 2; 272518334Speter break; 272618334Speter 272718334Speter case LTU: 272818334Speter /* Jump becomes no-op. */ 272918334Speter return -1; 273090087Sobrien 273150503Sobrien default: 273250503Sobrien break; 273318334Speter } 273418334Speter 273518334Speter if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N)) 273618334Speter switch (GET_CODE (cond)) 273718334Speter { 273850503Sobrien default: 2739169699Skan gcc_unreachable (); 274018334Speter 274118334Speter case NE: 274218334Speter PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT); 274318334Speter value = 2; 274418334Speter break; 274518334Speter 274618334Speter case EQ: 274718334Speter PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE); 274818334Speter value = 2; 274918334Speter break; 275018334Speter } 275118334Speter 275218334Speter if (cc_status.flags & CC_NOT_SIGNED) 275318334Speter /* The flags are valid if signed condition operators are converted 275418334Speter to unsigned. */ 275518334Speter switch (GET_CODE (cond)) 275618334Speter { 275718334Speter case LE: 275818334Speter PUT_CODE (cond, LEU); 275918334Speter value = 2; 276018334Speter break; 276118334Speter 276218334Speter case LT: 276318334Speter PUT_CODE (cond, LTU); 276418334Speter value = 2; 276518334Speter break; 276618334Speter 276718334Speter case GT: 276818334Speter PUT_CODE (cond, GTU); 276918334Speter value = 2; 277018334Speter break; 277118334Speter 277218334Speter case GE: 277318334Speter PUT_CODE (cond, GEU); 277418334Speter value = 2; 277518334Speter break; 277650503Sobrien 277750503Sobrien default: 277850503Sobrien break; 277918334Speter } 278018334Speter 278118334Speter return value; 278218334Speter} 278318334Speter#endif 278418334Speter 278518334Speter/* Report inconsistency between the assembler template and the operands. 278618334Speter In an `asm', it's the user's fault; otherwise, the compiler's fault. */ 278718334Speter 278818334Spetervoid 2789169699Skanoutput_operand_lossage (const char *cmsgid, ...) 279018334Speter{ 279196281Sobrien char *fmt_string; 279296281Sobrien char *new_message; 279396281Sobrien const char *pfx_str; 2794132727Skan va_list ap; 279596281Sobrien 2796169699Skan va_start (ap, cmsgid); 2797132727Skan 2798169699Skan pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: "; 2799169699Skan asprintf (&fmt_string, "%s%s", pfx_str, _(cmsgid)); 280096281Sobrien vasprintf (&new_message, fmt_string, ap); 2801117404Skan 280218334Speter if (this_is_asm_operands) 280396281Sobrien error_for_asm (this_is_asm_operands, "%s", new_message); 280418334Speter else 280596281Sobrien internal_error ("%s", new_message); 280696281Sobrien 280796281Sobrien free (fmt_string); 280896281Sobrien free (new_message); 2809132727Skan va_end (ap); 281018334Speter} 281118334Speter 281218334Speter/* Output of assembler code from a template, and its subroutines. */ 281318334Speter 281490087Sobrien/* Annotate the assembly with a comment describing the pattern and 281590087Sobrien alternative used. */ 281690087Sobrien 281790087Sobrienstatic void 2818132727Skanoutput_asm_name (void) 281990087Sobrien{ 282090087Sobrien if (debug_insn) 282190087Sobrien { 282290087Sobrien int num = INSN_CODE (debug_insn); 282390087Sobrien fprintf (asm_out_file, "\t%s %d\t%s", 282490087Sobrien ASM_COMMENT_START, INSN_UID (debug_insn), 282590087Sobrien insn_data[num].name); 282690087Sobrien if (insn_data[num].n_alternatives > 1) 282790087Sobrien fprintf (asm_out_file, "/%d", which_alternative + 1); 282890087Sobrien#ifdef HAVE_ATTR_length 282990087Sobrien fprintf (asm_out_file, "\t[length = %d]", 283090087Sobrien get_attr_length (debug_insn)); 283190087Sobrien#endif 283290087Sobrien /* Clear this so only the first assembler insn 283390087Sobrien of any rtl insn will get the special comment for -dp. */ 283490087Sobrien debug_insn = 0; 283590087Sobrien } 283690087Sobrien} 283790087Sobrien 283890087Sobrien/* If OP is a REG or MEM and we can find a MEM_EXPR corresponding to it 283990087Sobrien or its address, return that expr . Set *PADDRESSP to 1 if the expr 284090087Sobrien corresponds to the address of the object and 0 if to the object. */ 284190087Sobrien 284290087Sobrienstatic tree 2843132727Skanget_mem_expr_from_op (rtx op, int *paddressp) 284490087Sobrien{ 284590087Sobrien tree expr; 284690087Sobrien int inner_addressp; 284790087Sobrien 284890087Sobrien *paddressp = 0; 284990087Sobrien 2850169699Skan if (REG_P (op)) 2851132727Skan return REG_EXPR (op); 2852169699Skan else if (!MEM_P (op)) 285390087Sobrien return 0; 285490087Sobrien 285590087Sobrien if (MEM_EXPR (op) != 0) 285690087Sobrien return MEM_EXPR (op); 285790087Sobrien 285890087Sobrien /* Otherwise we have an address, so indicate it and look at the address. */ 285990087Sobrien *paddressp = 1; 286090087Sobrien op = XEXP (op, 0); 286190087Sobrien 286290087Sobrien /* First check if we have a decl for the address, then look at the right side 286390087Sobrien if it is a PLUS. Otherwise, strip off arithmetic and keep looking. 286490087Sobrien But don't allow the address to itself be indirect. */ 286590087Sobrien if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp) 286690087Sobrien return expr; 286790087Sobrien else if (GET_CODE (op) == PLUS 286890087Sobrien && (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp))) 286990087Sobrien return expr; 287090087Sobrien 2871169699Skan while (GET_RTX_CLASS (GET_CODE (op)) == RTX_UNARY 2872169699Skan || GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH) 287390087Sobrien op = XEXP (op, 0); 287490087Sobrien 287590087Sobrien expr = get_mem_expr_from_op (op, &inner_addressp); 287690087Sobrien return inner_addressp ? 0 : expr; 287790087Sobrien} 287890087Sobrien 287990087Sobrien/* Output operand names for assembler instructions. OPERANDS is the 288090087Sobrien operand vector, OPORDER is the order to write the operands, and NOPS 288190087Sobrien is the number of operands to write. */ 288290087Sobrien 288390087Sobrienstatic void 2884132727Skanoutput_asm_operand_names (rtx *operands, int *oporder, int nops) 288590087Sobrien{ 288690087Sobrien int wrote = 0; 288790087Sobrien int i; 288890087Sobrien 288990087Sobrien for (i = 0; i < nops; i++) 289090087Sobrien { 289190087Sobrien int addressp; 2892132727Skan rtx op = operands[oporder[i]]; 2893132727Skan tree expr = get_mem_expr_from_op (op, &addressp); 289490087Sobrien 2895132727Skan fprintf (asm_out_file, "%c%s", 2896132727Skan wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START); 2897132727Skan wrote = 1; 289890087Sobrien if (expr) 289990087Sobrien { 2900132727Skan fprintf (asm_out_file, "%s", 290190087Sobrien addressp ? "*" : ""); 290290087Sobrien print_mem_expr (asm_out_file, expr); 290390087Sobrien wrote = 1; 290490087Sobrien } 2905132727Skan else if (REG_P (op) && ORIGINAL_REGNO (op) 2906132727Skan && ORIGINAL_REGNO (op) != REGNO (op)) 2907132727Skan fprintf (asm_out_file, " tmp%i", ORIGINAL_REGNO (op)); 290890087Sobrien } 290990087Sobrien} 291090087Sobrien 291118334Speter/* Output text from TEMPLATE to the assembler output file, 291218334Speter obeying %-directions to substitute operands taken from 291318334Speter the vector OPERANDS. 291418334Speter 291518334Speter %N (for N a digit) means print operand N in usual manner. 291618334Speter %lN means require operand N to be a CODE_LABEL or LABEL_REF 291718334Speter and print the label name with no punctuation. 291818334Speter %cN means require operand N to be a constant 291918334Speter and print the constant expression with no punctuation. 292018334Speter %aN means expect operand N to be a memory address 292118334Speter (not a memory reference!) and print a reference 292218334Speter to that address. 292318334Speter %nN means expect operand N to be a constant 292418334Speter and print a constant expression for minus the value 292518334Speter of the operand, with no other punctuation. */ 292618334Speter 292718334Spetervoid 2928132727Skanoutput_asm_insn (const char *template, rtx *operands) 292918334Speter{ 293090087Sobrien const char *p; 293190087Sobrien int c; 293290087Sobrien#ifdef ASSEMBLER_DIALECT 293390087Sobrien int dialect = 0; 293490087Sobrien#endif 293590087Sobrien int oporder[MAX_RECOG_OPERANDS]; 293690087Sobrien char opoutput[MAX_RECOG_OPERANDS]; 293790087Sobrien int ops = 0; 293818334Speter 293918334Speter /* An insn may return a null string template 294018334Speter in a case where no assembler code is needed. */ 294118334Speter if (*template == 0) 294218334Speter return; 294318334Speter 294490087Sobrien memset (opoutput, 0, sizeof opoutput); 294518334Speter p = template; 294618334Speter putc ('\t', asm_out_file); 294718334Speter 294818334Speter#ifdef ASM_OUTPUT_OPCODE 294918334Speter ASM_OUTPUT_OPCODE (asm_out_file, p); 295018334Speter#endif 295118334Speter 295250503Sobrien while ((c = *p++)) 295318334Speter switch (c) 295418334Speter { 295518334Speter case '\n': 295690087Sobrien if (flag_verbose_asm) 295790087Sobrien output_asm_operand_names (operands, oporder, ops); 295890087Sobrien if (flag_print_asm_name) 295990087Sobrien output_asm_name (); 296090087Sobrien 296190087Sobrien ops = 0; 296290087Sobrien memset (opoutput, 0, sizeof opoutput); 296390087Sobrien 296418334Speter putc (c, asm_out_file); 296518334Speter#ifdef ASM_OUTPUT_OPCODE 296618334Speter while ((c = *p) == '\t') 296718334Speter { 296818334Speter putc (c, asm_out_file); 296918334Speter p++; 297018334Speter } 297118334Speter ASM_OUTPUT_OPCODE (asm_out_file, p); 297218334Speter#endif 297318334Speter break; 297418334Speter 297518334Speter#ifdef ASSEMBLER_DIALECT 297618334Speter case '{': 297750503Sobrien { 297890087Sobrien int i; 297990087Sobrien 298090087Sobrien if (dialect) 298190087Sobrien output_operand_lossage ("nested assembly dialect alternatives"); 298290087Sobrien else 298390087Sobrien dialect = 1; 298490087Sobrien 298550503Sobrien /* If we want the first dialect, do nothing. Otherwise, skip 298650503Sobrien DIALECT_NUMBER of strings ending with '|'. */ 298750503Sobrien for (i = 0; i < dialect_number; i++) 298850503Sobrien { 298990087Sobrien while (*p && *p != '}' && *p++ != '|') 299050503Sobrien ; 299190087Sobrien if (*p == '}') 299290087Sobrien break; 299350503Sobrien if (*p == '|') 299450503Sobrien p++; 299550503Sobrien } 299690087Sobrien 299790087Sobrien if (*p == '\0') 299890087Sobrien output_operand_lossage ("unterminated assembly dialect alternative"); 299950503Sobrien } 300018334Speter break; 300118334Speter 300218334Speter case '|': 300390087Sobrien if (dialect) 300490087Sobrien { 300590087Sobrien /* Skip to close brace. */ 300690087Sobrien do 300790087Sobrien { 300890087Sobrien if (*p == '\0') 300990087Sobrien { 301090087Sobrien output_operand_lossage ("unterminated assembly dialect alternative"); 301190087Sobrien break; 301290087Sobrien } 301390087Sobrien } 301490087Sobrien while (*p++ != '}'); 301590087Sobrien dialect = 0; 301690087Sobrien } 301790087Sobrien else 301890087Sobrien putc (c, asm_out_file); 301918334Speter break; 302018334Speter 302118334Speter case '}': 302290087Sobrien if (! dialect) 302390087Sobrien putc (c, asm_out_file); 302490087Sobrien dialect = 0; 302518334Speter break; 302618334Speter#endif 302718334Speter 302818334Speter case '%': 302918334Speter /* %% outputs a single %. */ 303018334Speter if (*p == '%') 303118334Speter { 303218334Speter p++; 303318334Speter putc (c, asm_out_file); 303418334Speter } 303518334Speter /* %= outputs a number which is unique to each insn in the entire 303618334Speter compilation. This is useful for making local labels that are 303718334Speter referred to more than once in a given insn. */ 303818334Speter else if (*p == '=') 303918334Speter { 304018334Speter p++; 304118334Speter fprintf (asm_out_file, "%d", insn_counter); 304218334Speter } 304318334Speter /* % followed by a letter and some digits 304418334Speter outputs an operand in a special way depending on the letter. 304518334Speter Letters `acln' are implemented directly. 304618334Speter Other letters are passed to `output_operand' so that 304718334Speter the PRINT_OPERAND macro can define them. */ 304890087Sobrien else if (ISALPHA (*p)) 304918334Speter { 305018334Speter int letter = *p++; 3051169699Skan unsigned long opnum; 3052169699Skan char *endptr; 305318334Speter 3054169699Skan opnum = strtoul (p, &endptr, 10); 3055169699Skan 3056169699Skan if (endptr == p) 3057169699Skan output_operand_lossage ("operand number missing " 3058169699Skan "after %%-letter"); 3059169699Skan else if (this_is_asm_operands && opnum >= insn_noperands) 306018334Speter output_operand_lossage ("operand number out of range"); 306118334Speter else if (letter == 'l') 3062169699Skan output_asm_label (operands[opnum]); 306318334Speter else if (letter == 'a') 3064169699Skan output_address (operands[opnum]); 306518334Speter else if (letter == 'c') 306618334Speter { 3067169699Skan if (CONSTANT_ADDRESS_P (operands[opnum])) 3068169699Skan output_addr_const (asm_out_file, operands[opnum]); 306918334Speter else 3070169699Skan output_operand (operands[opnum], 'c'); 307118334Speter } 307218334Speter else if (letter == 'n') 307318334Speter { 3074169699Skan if (GET_CODE (operands[opnum]) == CONST_INT) 307550503Sobrien fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, 3076169699Skan - INTVAL (operands[opnum])); 307718334Speter else 307818334Speter { 307918334Speter putc ('-', asm_out_file); 3080169699Skan output_addr_const (asm_out_file, operands[opnum]); 308118334Speter } 308218334Speter } 308318334Speter else 3084169699Skan output_operand (operands[opnum], letter); 308590087Sobrien 3086169699Skan if (!opoutput[opnum]) 3087169699Skan oporder[ops++] = opnum; 3088169699Skan opoutput[opnum] = 1; 308990087Sobrien 3090169699Skan p = endptr; 3091169699Skan c = *p; 309218334Speter } 309318334Speter /* % followed by a digit outputs an operand the default way. */ 309490087Sobrien else if (ISDIGIT (*p)) 309518334Speter { 3096169699Skan unsigned long opnum; 3097169699Skan char *endptr; 3098169699Skan 3099169699Skan opnum = strtoul (p, &endptr, 10); 3100169699Skan if (this_is_asm_operands && opnum >= insn_noperands) 310118334Speter output_operand_lossage ("operand number out of range"); 310218334Speter else 3103169699Skan output_operand (operands[opnum], 0); 310490087Sobrien 3105169699Skan if (!opoutput[opnum]) 3106169699Skan oporder[ops++] = opnum; 3107169699Skan opoutput[opnum] = 1; 310890087Sobrien 3109169699Skan p = endptr; 3110169699Skan c = *p; 311118334Speter } 311218334Speter /* % followed by punctuation: output something for that 311318334Speter punctuation character alone, with no operand. 311418334Speter The PRINT_OPERAND macro decides what is actually done. */ 311518334Speter#ifdef PRINT_OPERAND_PUNCT_VALID_P 311690087Sobrien else if (PRINT_OPERAND_PUNCT_VALID_P ((unsigned char) *p)) 311718334Speter output_operand (NULL_RTX, *p++); 311818334Speter#endif 311918334Speter else 312018334Speter output_operand_lossage ("invalid %%-code"); 312118334Speter break; 312218334Speter 312318334Speter default: 312418334Speter putc (c, asm_out_file); 312518334Speter } 312618334Speter 312790087Sobrien /* Write out the variable names for operands, if we know them. */ 312890087Sobrien if (flag_verbose_asm) 312990087Sobrien output_asm_operand_names (operands, oporder, ops); 313090087Sobrien if (flag_print_asm_name) 313190087Sobrien output_asm_name (); 313218334Speter 313318334Speter putc ('\n', asm_out_file); 313418334Speter} 313518334Speter 313618334Speter/* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ 313718334Speter 313818334Spetervoid 3139132727Skanoutput_asm_label (rtx x) 314018334Speter{ 314118334Speter char buf[256]; 314218334Speter 314318334Speter if (GET_CODE (x) == LABEL_REF) 314490087Sobrien x = XEXP (x, 0); 3145169699Skan if (LABEL_P (x) 3146169699Skan || (NOTE_P (x) 314790087Sobrien && NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL)) 314818334Speter ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 314918334Speter else 3150169699Skan output_operand_lossage ("'%%l' operand isn't a label"); 315118334Speter 315218334Speter assemble_name (asm_out_file, buf); 315318334Speter} 315418334Speter 315518334Speter/* Print operand X using machine-dependent assembler syntax. 315618334Speter The macro PRINT_OPERAND is defined just to control this function. 315718334Speter CODE is a non-digit that preceded the operand-number in the % spec, 315818334Speter such as 'z' if the spec was `%z3'. CODE is 0 if there was no char 315918334Speter between the % and the digits. 316018334Speter When CODE is a non-letter, X is 0. 316118334Speter 316218334Speter The meanings of the letters are machine-dependent and controlled 316318334Speter by PRINT_OPERAND. */ 316418334Speter 316518334Speterstatic void 3166132727Skanoutput_operand (rtx x, int code ATTRIBUTE_UNUSED) 316718334Speter{ 316818334Speter if (x && GET_CODE (x) == SUBREG) 316990087Sobrien x = alter_subreg (&x); 317018334Speter 3171169699Skan /* X must not be a pseudo reg. */ 3172169699Skan gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER); 317318334Speter 317418334Speter PRINT_OPERAND (asm_out_file, x, code); 317518334Speter} 317618334Speter 317718334Speter/* Print a memory reference operand for address X 317818334Speter using machine-dependent assembler syntax. 317918334Speter The macro PRINT_OPERAND_ADDRESS exists just to control this function. */ 318018334Speter 318118334Spetervoid 3182132727Skanoutput_address (rtx x) 318318334Speter{ 318490087Sobrien walk_alter_subreg (&x); 318518334Speter PRINT_OPERAND_ADDRESS (asm_out_file, x); 318618334Speter} 318718334Speter 318818334Speter/* Print an integer constant expression in assembler syntax. 318918334Speter Addition and subtraction are the only arithmetic 319018334Speter that may appear in these expressions. */ 319118334Speter 319218334Spetervoid 3193132727Skanoutput_addr_const (FILE *file, rtx x) 319418334Speter{ 319518334Speter char buf[256]; 319618334Speter 319718334Speter restart: 319818334Speter switch (GET_CODE (x)) 319918334Speter { 320018334Speter case PC: 320190087Sobrien putc ('.', file); 320218334Speter break; 320318334Speter 320418334Speter case SYMBOL_REF: 3205169699Skan if (SYMBOL_REF_DECL (x)) 3206169699Skan mark_decl_referenced (SYMBOL_REF_DECL (x)); 320790087Sobrien#ifdef ASM_OUTPUT_SYMBOL_REF 320890087Sobrien ASM_OUTPUT_SYMBOL_REF (file, x); 320990087Sobrien#else 321018334Speter assemble_name (file, XSTR (x, 0)); 321190087Sobrien#endif 321218334Speter break; 321318334Speter 321418334Speter case LABEL_REF: 321590087Sobrien x = XEXP (x, 0); 321690087Sobrien /* Fall through. */ 321718334Speter case CODE_LABEL: 321818334Speter ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 321990087Sobrien#ifdef ASM_OUTPUT_LABEL_REF 322090087Sobrien ASM_OUTPUT_LABEL_REF (file, buf); 322190087Sobrien#else 322218334Speter assemble_name (file, buf); 322390087Sobrien#endif 322418334Speter break; 322518334Speter 322618334Speter case CONST_INT: 322750503Sobrien fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 322818334Speter break; 322918334Speter 323018334Speter case CONST: 323118334Speter /* This used to output parentheses around the expression, 323218334Speter but that does not work on the 386 (either ATT or BSD assembler). */ 323318334Speter output_addr_const (file, XEXP (x, 0)); 323418334Speter break; 323518334Speter 323618334Speter case CONST_DOUBLE: 323718334Speter if (GET_MODE (x) == VOIDmode) 323818334Speter { 323918334Speter /* We can use %d if the number is one word and positive. */ 324018334Speter if (CONST_DOUBLE_HIGH (x)) 324150503Sobrien fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX, 324218334Speter CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 324390087Sobrien else if (CONST_DOUBLE_LOW (x) < 0) 324450503Sobrien fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x)); 324518334Speter else 324650503Sobrien fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x)); 324718334Speter } 324818334Speter else 324918334Speter /* We can't handle floating point constants; 325018334Speter PRINT_OPERAND must handle them. */ 325118334Speter output_operand_lossage ("floating constant misused"); 325218334Speter break; 325318334Speter 325418334Speter case PLUS: 325518334Speter /* Some assemblers need integer constants to appear last (eg masm). */ 325618334Speter if (GET_CODE (XEXP (x, 0)) == CONST_INT) 325718334Speter { 325818334Speter output_addr_const (file, XEXP (x, 1)); 325918334Speter if (INTVAL (XEXP (x, 0)) >= 0) 326018334Speter fprintf (file, "+"); 326118334Speter output_addr_const (file, XEXP (x, 0)); 326218334Speter } 326318334Speter else 326418334Speter { 326518334Speter output_addr_const (file, XEXP (x, 0)); 326690087Sobrien if (GET_CODE (XEXP (x, 1)) != CONST_INT 326790087Sobrien || INTVAL (XEXP (x, 1)) >= 0) 326818334Speter fprintf (file, "+"); 326918334Speter output_addr_const (file, XEXP (x, 1)); 327018334Speter } 327118334Speter break; 327218334Speter 327318334Speter case MINUS: 327418334Speter /* Avoid outputting things like x-x or x+5-x, 327518334Speter since some assemblers can't handle that. */ 327618334Speter x = simplify_subtraction (x); 327718334Speter if (GET_CODE (x) != MINUS) 327818334Speter goto restart; 327918334Speter 328018334Speter output_addr_const (file, XEXP (x, 0)); 328118334Speter fprintf (file, "-"); 328290087Sobrien if ((GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0) 328390087Sobrien || GET_CODE (XEXP (x, 1)) == PC 328490087Sobrien || GET_CODE (XEXP (x, 1)) == SYMBOL_REF) 328590087Sobrien output_addr_const (file, XEXP (x, 1)); 328690087Sobrien else 328718334Speter { 328890087Sobrien fputs (targetm.asm_out.open_paren, file); 328918334Speter output_addr_const (file, XEXP (x, 1)); 329090087Sobrien fputs (targetm.asm_out.close_paren, file); 329118334Speter } 329218334Speter break; 329318334Speter 329418334Speter case ZERO_EXTEND: 329518334Speter case SIGN_EXTEND: 329696281Sobrien case SUBREG: 329718334Speter output_addr_const (file, XEXP (x, 0)); 329818334Speter break; 329918334Speter 330018334Speter default: 330190087Sobrien#ifdef OUTPUT_ADDR_CONST_EXTRA 330290087Sobrien OUTPUT_ADDR_CONST_EXTRA (file, x, fail); 330390087Sobrien break; 330490087Sobrien 330590087Sobrien fail: 330690087Sobrien#endif 330718334Speter output_operand_lossage ("invalid expression as operand"); 330818334Speter } 330918334Speter} 331018334Speter 331118334Speter/* A poor man's fprintf, with the added features of %I, %R, %L, and %U. 331218334Speter %R prints the value of REGISTER_PREFIX. 331318334Speter %L prints the value of LOCAL_LABEL_PREFIX. 331418334Speter %U prints the value of USER_LABEL_PREFIX. 331518334Speter %I prints the value of IMMEDIATE_PREFIX. 331618334Speter %O runs ASM_OUTPUT_OPCODE to transform what follows in the string. 3317132727Skan Also supported are %d, %i, %u, %x, %X, %o, %c, %s and %%. 331818334Speter 331918334Speter We handle alternate assembler dialects here, just like output_asm_insn. */ 332018334Speter 332118334Spetervoid 3322132727Skanasm_fprintf (FILE *file, const char *p, ...) 332318334Speter{ 332418334Speter char buf[10]; 332518334Speter char *q, c; 3326132727Skan va_list argptr; 332718334Speter 3328132727Skan va_start (argptr, p); 332918334Speter 333018334Speter buf[0] = '%'; 333118334Speter 333250503Sobrien while ((c = *p++)) 333318334Speter switch (c) 333418334Speter { 333518334Speter#ifdef ASSEMBLER_DIALECT 333618334Speter case '{': 333750503Sobrien { 333850503Sobrien int i; 333918334Speter 334050503Sobrien /* If we want the first dialect, do nothing. Otherwise, skip 334150503Sobrien DIALECT_NUMBER of strings ending with '|'. */ 334250503Sobrien for (i = 0; i < dialect_number; i++) 334350503Sobrien { 334450503Sobrien while (*p && *p++ != '|') 334550503Sobrien ; 334650503Sobrien 334750503Sobrien if (*p == '|') 334850503Sobrien p++; 334990087Sobrien } 335050503Sobrien } 335118334Speter break; 335218334Speter 335318334Speter case '|': 335418334Speter /* Skip to close brace. */ 335518334Speter while (*p && *p++ != '}') 335618334Speter ; 335718334Speter break; 335818334Speter 335918334Speter case '}': 336018334Speter break; 336118334Speter#endif 336218334Speter 336318334Speter case '%': 336418334Speter c = *p++; 336518334Speter q = &buf[1]; 3366132727Skan while (strchr ("-+ #0", c)) 3367132727Skan { 3368132727Skan *q++ = c; 3369132727Skan c = *p++; 3370132727Skan } 337190087Sobrien while (ISDIGIT (c) || c == '.') 337218334Speter { 337318334Speter *q++ = c; 337418334Speter c = *p++; 337518334Speter } 337618334Speter switch (c) 337718334Speter { 337818334Speter case '%': 3379132727Skan putc ('%', file); 338018334Speter break; 338118334Speter 338218334Speter case 'd': case 'i': case 'u': 3383132727Skan case 'x': case 'X': case 'o': 3384132727Skan case 'c': 338518334Speter *q++ = c; 338618334Speter *q = 0; 338718334Speter fprintf (file, buf, va_arg (argptr, int)); 338818334Speter break; 338918334Speter 339018334Speter case 'w': 3391132727Skan /* This is a prefix to the 'd', 'i', 'u', 'x', 'X', and 3392132727Skan 'o' cases, but we do not check for those cases. It 3393132727Skan means that the value is a HOST_WIDE_INT, which may be 3394132727Skan either `long' or `long long'. */ 3395132727Skan memcpy (q, HOST_WIDE_INT_PRINT, strlen (HOST_WIDE_INT_PRINT)); 3396132727Skan q += strlen (HOST_WIDE_INT_PRINT); 339718334Speter *q++ = *p++; 339818334Speter *q = 0; 339918334Speter fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT)); 340018334Speter break; 340118334Speter 340218334Speter case 'l': 340318334Speter *q++ = c; 3404132727Skan#ifdef HAVE_LONG_LONG 3405132727Skan if (*p == 'l') 3406132727Skan { 3407132727Skan *q++ = *p++; 3408132727Skan *q++ = *p++; 3409132727Skan *q = 0; 3410132727Skan fprintf (file, buf, va_arg (argptr, long long)); 3411132727Skan } 3412132727Skan else 3413132727Skan#endif 3414132727Skan { 3415132727Skan *q++ = *p++; 3416132727Skan *q = 0; 3417132727Skan fprintf (file, buf, va_arg (argptr, long)); 3418132727Skan } 341918334Speter 342018334Speter break; 342118334Speter 342218334Speter case 's': 342318334Speter *q++ = c; 342418334Speter *q = 0; 342518334Speter fprintf (file, buf, va_arg (argptr, char *)); 342618334Speter break; 342718334Speter 342818334Speter case 'O': 342918334Speter#ifdef ASM_OUTPUT_OPCODE 343018334Speter ASM_OUTPUT_OPCODE (asm_out_file, p); 343118334Speter#endif 343218334Speter break; 343318334Speter 343418334Speter case 'R': 343518334Speter#ifdef REGISTER_PREFIX 343618334Speter fprintf (file, "%s", REGISTER_PREFIX); 343718334Speter#endif 343818334Speter break; 343918334Speter 344018334Speter case 'I': 344118334Speter#ifdef IMMEDIATE_PREFIX 344218334Speter fprintf (file, "%s", IMMEDIATE_PREFIX); 344318334Speter#endif 344418334Speter break; 344518334Speter 344618334Speter case 'L': 344718334Speter#ifdef LOCAL_LABEL_PREFIX 344818334Speter fprintf (file, "%s", LOCAL_LABEL_PREFIX); 344918334Speter#endif 345018334Speter break; 345118334Speter 345218334Speter case 'U': 345352515Sobrien fputs (user_label_prefix, file); 345418334Speter break; 345518334Speter 345690087Sobrien#ifdef ASM_FPRINTF_EXTENSIONS 3457132727Skan /* Uppercase letters are reserved for general use by asm_fprintf 345890087Sobrien and so are not available to target specific code. In order to 345990087Sobrien prevent the ASM_FPRINTF_EXTENSIONS macro from using them then, 346090087Sobrien they are defined here. As they get turned into real extensions 346190087Sobrien to asm_fprintf they should be removed from this list. */ 346290087Sobrien case 'A': case 'B': case 'C': case 'D': case 'E': 346390087Sobrien case 'F': case 'G': case 'H': case 'J': case 'K': 346490087Sobrien case 'M': case 'N': case 'P': case 'Q': case 'S': 346590087Sobrien case 'T': case 'V': case 'W': case 'Y': case 'Z': 346690087Sobrien break; 346790087Sobrien 346890087Sobrien ASM_FPRINTF_EXTENSIONS (file, argptr, p) 346990087Sobrien#endif 347018334Speter default: 3471169699Skan gcc_unreachable (); 347218334Speter } 347318334Speter break; 347418334Speter 347518334Speter default: 3476132727Skan putc (c, file); 347718334Speter } 3478132727Skan va_end (argptr); 347918334Speter} 348018334Speter 348118334Speter/* Split up a CONST_DOUBLE or integer constant rtx 348218334Speter into two rtx's for single words, 348318334Speter storing in *FIRST the word that comes first in memory in the target 348418334Speter and in *SECOND the other. */ 348518334Speter 348618334Spetervoid 3487132727Skansplit_double (rtx value, rtx *first, rtx *second) 348818334Speter{ 348918334Speter if (GET_CODE (value) == CONST_INT) 349018334Speter { 349118334Speter if (HOST_BITS_PER_WIDE_INT >= (2 * BITS_PER_WORD)) 349218334Speter { 349318334Speter /* In this case the CONST_INT holds both target words. 349450503Sobrien Extract the bits from it into two word-sized pieces. 349550503Sobrien Sign extend each half to HOST_WIDE_INT. */ 349690087Sobrien unsigned HOST_WIDE_INT low, high; 349790087Sobrien unsigned HOST_WIDE_INT mask, sign_bit, sign_extend; 349818334Speter 349990087Sobrien /* Set sign_bit to the most significant bit of a word. */ 350090087Sobrien sign_bit = 1; 350190087Sobrien sign_bit <<= BITS_PER_WORD - 1; 350290087Sobrien 350390087Sobrien /* Set mask so that all bits of the word are set. We could 350490087Sobrien have used 1 << BITS_PER_WORD instead of basing the 350590087Sobrien calculation on sign_bit. However, on machines where 350690087Sobrien HOST_BITS_PER_WIDE_INT == BITS_PER_WORD, it could cause a 350790087Sobrien compiler warning, even though the code would never be 350890087Sobrien executed. */ 350990087Sobrien mask = sign_bit << 1; 351090087Sobrien mask--; 351190087Sobrien 351290087Sobrien /* Set sign_extend as any remaining bits. */ 351390087Sobrien sign_extend = ~mask; 351490087Sobrien 351590087Sobrien /* Pick the lower word and sign-extend it. */ 351690087Sobrien low = INTVAL (value); 351790087Sobrien low &= mask; 351890087Sobrien if (low & sign_bit) 351990087Sobrien low |= sign_extend; 352090087Sobrien 352190087Sobrien /* Pick the higher word, shifted to the least significant 352290087Sobrien bits, and sign-extend it. */ 352390087Sobrien high = INTVAL (value); 352490087Sobrien high >>= BITS_PER_WORD - 1; 352590087Sobrien high >>= 1; 352690087Sobrien high &= mask; 352790087Sobrien if (high & sign_bit) 352890087Sobrien high |= sign_extend; 352990087Sobrien 353090087Sobrien /* Store the words in the target machine order. */ 353118334Speter if (WORDS_BIG_ENDIAN) 353218334Speter { 353390087Sobrien *first = GEN_INT (high); 353490087Sobrien *second = GEN_INT (low); 353518334Speter } 353618334Speter else 353718334Speter { 353890087Sobrien *first = GEN_INT (low); 353990087Sobrien *second = GEN_INT (high); 354018334Speter } 354118334Speter } 354218334Speter else 354318334Speter { 354418334Speter /* The rule for using CONST_INT for a wider mode 354518334Speter is that we regard the value as signed. 354618334Speter So sign-extend it. */ 354718334Speter rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx); 354818334Speter if (WORDS_BIG_ENDIAN) 354918334Speter { 355018334Speter *first = high; 355118334Speter *second = value; 355218334Speter } 355318334Speter else 355418334Speter { 355518334Speter *first = value; 355618334Speter *second = high; 355718334Speter } 355818334Speter } 355918334Speter } 356018334Speter else if (GET_CODE (value) != CONST_DOUBLE) 356118334Speter { 356218334Speter if (WORDS_BIG_ENDIAN) 356318334Speter { 356418334Speter *first = const0_rtx; 356518334Speter *second = value; 356618334Speter } 356718334Speter else 356818334Speter { 356918334Speter *first = value; 357018334Speter *second = const0_rtx; 357118334Speter } 357218334Speter } 357318334Speter else if (GET_MODE (value) == VOIDmode 357418334Speter /* This is the old way we did CONST_DOUBLE integers. */ 357518334Speter || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT) 357618334Speter { 357718334Speter /* In an integer, the words are defined as most and least significant. 357818334Speter So order them by the target's convention. */ 357918334Speter if (WORDS_BIG_ENDIAN) 358018334Speter { 358118334Speter *first = GEN_INT (CONST_DOUBLE_HIGH (value)); 358218334Speter *second = GEN_INT (CONST_DOUBLE_LOW (value)); 358318334Speter } 358418334Speter else 358518334Speter { 358618334Speter *first = GEN_INT (CONST_DOUBLE_LOW (value)); 358718334Speter *second = GEN_INT (CONST_DOUBLE_HIGH (value)); 358818334Speter } 358918334Speter } 359018334Speter else 359118334Speter { 359290087Sobrien REAL_VALUE_TYPE r; 359390087Sobrien long l[2]; 359418334Speter REAL_VALUE_FROM_CONST_DOUBLE (r, value); 359518334Speter 359618334Speter /* Note, this converts the REAL_VALUE_TYPE to the target's 359718334Speter format, splits up the floating point double and outputs 359818334Speter exactly 32 bits of it into each of l[0] and l[1] -- 359950503Sobrien not necessarily BITS_PER_WORD bits. */ 360018334Speter REAL_VALUE_TO_TARGET_DOUBLE (r, l); 360118334Speter 360252515Sobrien /* If 32 bits is an entire word for the target, but not for the host, 360352515Sobrien then sign-extend on the host so that the number will look the same 360452515Sobrien way on the host that it would on the target. See for instance 360552515Sobrien simplify_unary_operation. The #if is needed to avoid compiler 360652515Sobrien warnings. */ 360752515Sobrien 360852515Sobrien#if HOST_BITS_PER_LONG > 32 360952515Sobrien if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32) 361052515Sobrien { 361152515Sobrien if (l[0] & ((long) 1 << 31)) 361252515Sobrien l[0] |= ((long) (-1) << 32); 361352515Sobrien if (l[1] & ((long) 1 << 31)) 361452515Sobrien l[1] |= ((long) (-1) << 32); 361552515Sobrien } 361652515Sobrien#endif 361752515Sobrien 3618169699Skan *first = GEN_INT (l[0]); 3619169699Skan *second = GEN_INT (l[1]); 362018334Speter } 362118334Speter} 362218334Speter 362318334Speter/* Return nonzero if this function has no function calls. */ 362418334Speter 362518334Speterint 3626132727Skanleaf_function_p (void) 362718334Speter{ 362818334Speter rtx insn; 362990087Sobrien rtx link; 363018334Speter 363190087Sobrien if (current_function_profile || profile_arc_flag) 363218334Speter return 0; 363318334Speter 363418334Speter for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 363518334Speter { 3636169699Skan if (CALL_P (insn) 363790087Sobrien && ! SIBLING_CALL_P (insn)) 363818334Speter return 0; 3639169699Skan if (NONJUMP_INSN_P (insn) 364018334Speter && GET_CODE (PATTERN (insn)) == SEQUENCE 3641169699Skan && CALL_P (XVECEXP (PATTERN (insn), 0, 0)) 364290087Sobrien && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0))) 364318334Speter return 0; 364418334Speter } 364590087Sobrien for (link = current_function_epilogue_delay_list; 364690087Sobrien link; 364790087Sobrien link = XEXP (link, 1)) 364818334Speter { 364990087Sobrien insn = XEXP (link, 0); 365090087Sobrien 3651169699Skan if (CALL_P (insn) 365290087Sobrien && ! SIBLING_CALL_P (insn)) 365318334Speter return 0; 3654169699Skan if (NONJUMP_INSN_P (insn) 365590087Sobrien && GET_CODE (PATTERN (insn)) == SEQUENCE 3656169699Skan && CALL_P (XVECEXP (PATTERN (insn), 0, 0)) 365790087Sobrien && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0))) 365818334Speter return 0; 365918334Speter } 366018334Speter 366118334Speter return 1; 366218334Speter} 366318334Speter 3664117404Skan/* Return 1 if branch is a forward branch. 366590087Sobrien Uses insn_shuid array, so it works only in the final pass. May be used by 366690087Sobrien output templates to customary add branch prediction hints. 366790087Sobrien */ 366890087Sobrienint 3669132727Skanfinal_forward_branch_p (rtx insn) 367090087Sobrien{ 367190087Sobrien int insn_id, label_id; 3672169699Skan 3673169699Skan gcc_assert (uid_shuid); 367490087Sobrien insn_id = INSN_SHUID (insn); 367590087Sobrien label_id = INSN_SHUID (JUMP_LABEL (insn)); 367690087Sobrien /* We've hit some insns that does not have id information available. */ 3677169699Skan gcc_assert (insn_id && label_id); 367890087Sobrien return insn_id < label_id; 367990087Sobrien} 368090087Sobrien 368118334Speter/* On some machines, a function with no call insns 368218334Speter can run faster if it doesn't create its own register window. 368318334Speter When output, the leaf function should use only the "output" 368418334Speter registers. Ordinarily, the function would be compiled to use 368518334Speter the "input" registers to find its arguments; it is a candidate 368618334Speter for leaf treatment if it uses only the "input" registers. 368718334Speter Leaf function treatment means renumbering so the function 368818334Speter uses the "output" registers instead. */ 368918334Speter 369018334Speter#ifdef LEAF_REGISTERS 369118334Speter 369218334Speter/* Return 1 if this function uses only the registers that can be 369318334Speter safely renumbered. */ 369418334Speter 369518334Speterint 3696132727Skanonly_leaf_regs_used (void) 369718334Speter{ 369818334Speter int i; 3699132727Skan const char *const permitted_reg_in_leaf_functions = LEAF_REGISTERS; 370018334Speter 370118334Speter for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 370250503Sobrien if ((regs_ever_live[i] || global_regs[i]) 370350503Sobrien && ! permitted_reg_in_leaf_functions[i]) 370450503Sobrien return 0; 370550503Sobrien 370650503Sobrien if (current_function_uses_pic_offset_table 370750503Sobrien && pic_offset_table_rtx != 0 3708169699Skan && REG_P (pic_offset_table_rtx) 370950503Sobrien && ! permitted_reg_in_leaf_functions[REGNO (pic_offset_table_rtx)]) 371050503Sobrien return 0; 371150503Sobrien 371218334Speter return 1; 371318334Speter} 371418334Speter 371518334Speter/* Scan all instructions and renumber all registers into those 371618334Speter available in leaf functions. */ 371718334Speter 371818334Speterstatic void 3719132727Skanleaf_renumber_regs (rtx first) 372018334Speter{ 372118334Speter rtx insn; 372218334Speter 372318334Speter /* Renumber only the actual patterns. 372418334Speter The reg-notes can contain frame pointer refs, 372518334Speter and renumbering them could crash, and should not be needed. */ 372618334Speter for (insn = first; insn; insn = NEXT_INSN (insn)) 372790087Sobrien if (INSN_P (insn)) 372818334Speter leaf_renumber_regs_insn (PATTERN (insn)); 372990087Sobrien for (insn = current_function_epilogue_delay_list; 373090087Sobrien insn; 373190087Sobrien insn = XEXP (insn, 1)) 373290087Sobrien if (INSN_P (XEXP (insn, 0))) 373318334Speter leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0))); 373418334Speter} 373518334Speter 373618334Speter/* Scan IN_RTX and its subexpressions, and renumber all regs into those 373718334Speter available in leaf functions. */ 373818334Speter 373918334Spetervoid 3740132727Skanleaf_renumber_regs_insn (rtx in_rtx) 374118334Speter{ 374290087Sobrien int i, j; 374390087Sobrien const char *format_ptr; 374418334Speter 374518334Speter if (in_rtx == 0) 374618334Speter return; 374718334Speter 374818334Speter /* Renumber all input-registers into output-registers. 374918334Speter renumbered_regs would be 1 for an output-register; 375018334Speter they */ 375118334Speter 3752169699Skan if (REG_P (in_rtx)) 375318334Speter { 375418334Speter int newreg; 375518334Speter 375618334Speter /* Don't renumber the same reg twice. */ 375718334Speter if (in_rtx->used) 375818334Speter return; 375918334Speter 376018334Speter newreg = REGNO (in_rtx); 376118334Speter /* Don't try to renumber pseudo regs. It is possible for a pseudo reg 376218334Speter to reach here as part of a REG_NOTE. */ 376318334Speter if (newreg >= FIRST_PSEUDO_REGISTER) 376418334Speter { 376518334Speter in_rtx->used = 1; 376618334Speter return; 376718334Speter } 376818334Speter newreg = LEAF_REG_REMAP (newreg); 3769169699Skan gcc_assert (newreg >= 0); 377018334Speter regs_ever_live[REGNO (in_rtx)] = 0; 377118334Speter regs_ever_live[newreg] = 1; 377218334Speter REGNO (in_rtx) = newreg; 377318334Speter in_rtx->used = 1; 377418334Speter } 377518334Speter 377690087Sobrien if (INSN_P (in_rtx)) 377718334Speter { 377818334Speter /* Inside a SEQUENCE, we find insns. 377918334Speter Renumber just the patterns of these insns, 378018334Speter just as we do for the top-level insns. */ 378118334Speter leaf_renumber_regs_insn (PATTERN (in_rtx)); 378218334Speter return; 378318334Speter } 378418334Speter 378518334Speter format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); 378618334Speter 378718334Speter for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) 378818334Speter switch (*format_ptr++) 378918334Speter { 379018334Speter case 'e': 379118334Speter leaf_renumber_regs_insn (XEXP (in_rtx, i)); 379218334Speter break; 379318334Speter 379418334Speter case 'E': 379518334Speter if (NULL != XVEC (in_rtx, i)) 379618334Speter { 379718334Speter for (j = 0; j < XVECLEN (in_rtx, i); j++) 379818334Speter leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j)); 379918334Speter } 380018334Speter break; 380118334Speter 380218334Speter case 'S': 380318334Speter case 's': 380418334Speter case '0': 380518334Speter case 'i': 380618334Speter case 'w': 380718334Speter case 'n': 380818334Speter case 'u': 380918334Speter break; 381018334Speter 381118334Speter default: 3812169699Skan gcc_unreachable (); 381318334Speter } 381418334Speter} 381518334Speter#endif 3816132727Skan 3817132727Skan 3818132727Skan/* When -gused is used, emit debug info for only used symbols. But in 3819132727Skan addition to the standard intercepted debug_hooks there are some direct 3820132727Skan calls into this file, i.e., dbxout_symbol, dbxout_parms, and dbxout_reg_params. 3821132727Skan Those routines may also be called from a higher level intercepted routine. So 3822132727Skan to prevent recording data for an inner call to one of these for an intercept, 3823132727Skan we maintain an intercept nesting counter (debug_nesting). We only save the 3824132727Skan intercepted arguments if the nesting is 1. */ 3825132727Skanint debug_nesting = 0; 3826132727Skan 3827132727Skanstatic tree *symbol_queue; 3828132727Skanint symbol_queue_index = 0; 3829132727Skanstatic int symbol_queue_size = 0; 3830132727Skan 3831132727Skan/* Generate the symbols for any queued up type symbols we encountered 3832132727Skan while generating the type info for some originally used symbol. 3833132727Skan This might generate additional entries in the queue. Only when 3834132727Skan the nesting depth goes to 0 is this routine called. */ 3835132727Skan 3836132727Skanvoid 3837132727Skandebug_flush_symbol_queue (void) 3838132727Skan{ 3839132727Skan int i; 3840132727Skan 3841132727Skan /* Make sure that additionally queued items are not flushed 3842132727Skan prematurely. */ 3843132727Skan 3844132727Skan ++debug_nesting; 3845132727Skan 3846132727Skan for (i = 0; i < symbol_queue_index; ++i) 3847132727Skan { 3848169699Skan /* If we pushed queued symbols then such symbols must be 3849132727Skan output no matter what anyone else says. Specifically, 3850132727Skan we need to make sure dbxout_symbol() thinks the symbol was 3851132727Skan used and also we need to override TYPE_DECL_SUPPRESS_DEBUG 3852132727Skan which may be set for outside reasons. */ 3853132727Skan int saved_tree_used = TREE_USED (symbol_queue[i]); 3854132727Skan int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]); 3855132727Skan TREE_USED (symbol_queue[i]) = 1; 3856132727Skan TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0; 3857132727Skan 3858132727Skan#ifdef DBX_DEBUGGING_INFO 3859132727Skan dbxout_symbol (symbol_queue[i], 0); 3860132727Skan#endif 3861132727Skan 3862132727Skan TREE_USED (symbol_queue[i]) = saved_tree_used; 3863132727Skan TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug; 3864132727Skan } 3865132727Skan 3866132727Skan symbol_queue_index = 0; 3867132727Skan --debug_nesting; 3868132727Skan} 3869132727Skan 3870132727Skan/* Queue a type symbol needed as part of the definition of a decl 3871132727Skan symbol. These symbols are generated when debug_flush_symbol_queue() 3872132727Skan is called. */ 3873132727Skan 3874132727Skanvoid 3875132727Skandebug_queue_symbol (tree decl) 3876132727Skan{ 3877132727Skan if (symbol_queue_index >= symbol_queue_size) 3878132727Skan { 3879132727Skan symbol_queue_size += 10; 3880132727Skan symbol_queue = xrealloc (symbol_queue, 3881132727Skan symbol_queue_size * sizeof (tree)); 3882132727Skan } 3883132727Skan 3884132727Skan symbol_queue[symbol_queue_index++] = decl; 3885132727Skan} 3886132727Skan 3887132727Skan/* Free symbol queue. */ 3888132727Skanvoid 3889132727Skandebug_free_queue (void) 3890132727Skan{ 3891132727Skan if (symbol_queue) 3892132727Skan { 3893132727Skan free (symbol_queue); 3894132727Skan symbol_queue = NULL; 3895132727Skan symbol_queue_size = 0; 3896132727Skan } 3897132727Skan} 3898169699Skan 3899169699Skan/* Turn the RTL into assembly. */ 3900169699Skanstatic unsigned int 3901169699Skanrest_of_handle_final (void) 3902169699Skan{ 3903169699Skan rtx x; 3904169699Skan const char *fnname; 3905169699Skan 3906169699Skan /* Get the function's name, as described by its RTL. This may be 3907169699Skan different from the DECL_NAME name used in the source file. */ 3908169699Skan 3909169699Skan x = DECL_RTL (current_function_decl); 3910169699Skan gcc_assert (MEM_P (x)); 3911169699Skan x = XEXP (x, 0); 3912169699Skan gcc_assert (GET_CODE (x) == SYMBOL_REF); 3913169699Skan fnname = XSTR (x, 0); 3914169699Skan 3915169699Skan assemble_start_function (current_function_decl, fnname); 3916169699Skan final_start_function (get_insns (), asm_out_file, optimize); 3917169699Skan final (get_insns (), asm_out_file, optimize); 3918169699Skan final_end_function (); 3919169699Skan 3920169699Skan#ifdef TARGET_UNWIND_INFO 3921169699Skan /* ??? The IA-64 ".handlerdata" directive must be issued before 3922169699Skan the ".endp" directive that closes the procedure descriptor. */ 3923169699Skan output_function_exception_table (); 3924169699Skan#endif 3925169699Skan 3926169699Skan assemble_end_function (current_function_decl, fnname); 3927169699Skan 3928169699Skan#ifndef TARGET_UNWIND_INFO 3929169699Skan /* Otherwise, it feels unclean to switch sections in the middle. */ 3930169699Skan output_function_exception_table (); 3931169699Skan#endif 3932169699Skan 3933169699Skan user_defined_section_attribute = false; 3934169699Skan 3935169699Skan if (! quiet_flag) 3936169699Skan fflush (asm_out_file); 3937169699Skan 3938169699Skan /* Release all memory allocated by flow. */ 3939169699Skan free_basic_block_vars (); 3940169699Skan 3941169699Skan /* Write DBX symbols if requested. */ 3942169699Skan 3943169699Skan /* Note that for those inline functions where we don't initially 3944169699Skan know for certain that we will be generating an out-of-line copy, 3945169699Skan the first invocation of this routine (rest_of_compilation) will 3946169699Skan skip over this code by doing a `goto exit_rest_of_compilation;'. 3947169699Skan Later on, wrapup_global_declarations will (indirectly) call 3948169699Skan rest_of_compilation again for those inline functions that need 3949169699Skan to have out-of-line copies generated. During that call, we 3950169699Skan *will* be routed past here. */ 3951169699Skan 3952169699Skan timevar_push (TV_SYMOUT); 3953169699Skan (*debug_hooks->function_decl) (current_function_decl); 3954169699Skan timevar_pop (TV_SYMOUT); 3955169699Skan return 0; 3956169699Skan} 3957169699Skan 3958169699Skanstruct tree_opt_pass pass_final = 3959169699Skan{ 3960169699Skan NULL, /* name */ 3961169699Skan NULL, /* gate */ 3962169699Skan rest_of_handle_final, /* execute */ 3963169699Skan NULL, /* sub */ 3964169699Skan NULL, /* next */ 3965169699Skan 0, /* static_pass_number */ 3966169699Skan TV_FINAL, /* tv_id */ 3967169699Skan 0, /* properties_required */ 3968169699Skan 0, /* properties_provided */ 3969169699Skan 0, /* properties_destroyed */ 3970169699Skan 0, /* todo_flags_start */ 3971169699Skan TODO_ggc_collect, /* todo_flags_finish */ 3972169699Skan 0 /* letter */ 3973169699Skan}; 3974169699Skan 3975169699Skan 3976169699Skanstatic unsigned int 3977169699Skanrest_of_handle_shorten_branches (void) 3978169699Skan{ 3979169699Skan /* Shorten branches. */ 3980169699Skan shorten_branches (get_insns ()); 3981169699Skan return 0; 3982169699Skan} 3983169699Skan 3984169699Skanstruct tree_opt_pass pass_shorten_branches = 3985169699Skan{ 3986169699Skan "shorten", /* name */ 3987169699Skan NULL, /* gate */ 3988169699Skan rest_of_handle_shorten_branches, /* execute */ 3989169699Skan NULL, /* sub */ 3990169699Skan NULL, /* next */ 3991169699Skan 0, /* static_pass_number */ 3992169699Skan TV_FINAL, /* tv_id */ 3993169699Skan 0, /* properties_required */ 3994169699Skan 0, /* properties_provided */ 3995169699Skan 0, /* properties_destroyed */ 3996169699Skan 0, /* todo_flags_start */ 3997169699Skan TODO_dump_func, /* todo_flags_finish */ 3998169699Skan 0 /* letter */ 3999169699Skan}; 4000169699Skan 4001169699Skan 4002169699Skanstatic unsigned int 4003169699Skanrest_of_clean_state (void) 4004169699Skan{ 4005169699Skan rtx insn, next; 4006169699Skan 4007169699Skan /* It is very important to decompose the RTL instruction chain here: 4008169699Skan debug information keeps pointing into CODE_LABEL insns inside the function 4009169699Skan body. If these remain pointing to the other insns, we end up preserving 4010169699Skan whole RTL chain and attached detailed debug info in memory. */ 4011169699Skan for (insn = get_insns (); insn; insn = next) 4012169699Skan { 4013169699Skan next = NEXT_INSN (insn); 4014169699Skan NEXT_INSN (insn) = NULL; 4015169699Skan PREV_INSN (insn) = NULL; 4016169699Skan } 4017169699Skan 4018169699Skan /* In case the function was not output, 4019169699Skan don't leave any temporary anonymous types 4020169699Skan queued up for sdb output. */ 4021169699Skan#ifdef SDB_DEBUGGING_INFO 4022169699Skan if (write_symbols == SDB_DEBUG) 4023169699Skan sdbout_types (NULL_TREE); 4024169699Skan#endif 4025169699Skan 4026169699Skan reload_completed = 0; 4027169699Skan epilogue_completed = 0; 4028169699Skan flow2_completed = 0; 4029169699Skan no_new_pseudos = 0; 4030169699Skan#ifdef STACK_REGS 4031169699Skan regstack_completed = 0; 4032169699Skan#endif 4033169699Skan 4034169699Skan /* Clear out the insn_length contents now that they are no 4035169699Skan longer valid. */ 4036169699Skan init_insn_lengths (); 4037169699Skan 4038169699Skan /* Show no temporary slots allocated. */ 4039169699Skan init_temp_slots (); 4040169699Skan 4041169699Skan free_basic_block_vars (); 4042169699Skan free_bb_for_insn (); 4043169699Skan 4044169699Skan 4045169699Skan if (targetm.binds_local_p (current_function_decl)) 4046169699Skan { 4047169699Skan int pref = cfun->preferred_stack_boundary; 4048169699Skan if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary) 4049169699Skan pref = cfun->stack_alignment_needed; 4050169699Skan cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary 4051169699Skan = pref; 4052169699Skan } 4053169699Skan 4054169699Skan /* Make sure volatile mem refs aren't considered valid operands for 4055169699Skan arithmetic insns. We must call this here if this is a nested inline 4056169699Skan function, since the above code leaves us in the init_recog state, 4057169699Skan and the function context push/pop code does not save/restore volatile_ok. 4058169699Skan 4059169699Skan ??? Maybe it isn't necessary for expand_start_function to call this 4060169699Skan anymore if we do it here? */ 4061169699Skan 4062169699Skan init_recog_no_volatile (); 4063169699Skan 4064169699Skan /* We're done with this function. Free up memory if we can. */ 4065169699Skan free_after_parsing (cfun); 4066169699Skan free_after_compilation (cfun); 4067169699Skan return 0; 4068169699Skan} 4069169699Skan 4070169699Skanstruct tree_opt_pass pass_clean_state = 4071169699Skan{ 4072169699Skan NULL, /* name */ 4073169699Skan NULL, /* gate */ 4074169699Skan rest_of_clean_state, /* execute */ 4075169699Skan NULL, /* sub */ 4076169699Skan NULL, /* next */ 4077169699Skan 0, /* static_pass_number */ 4078169699Skan TV_FINAL, /* tv_id */ 4079169699Skan 0, /* properties_required */ 4080169699Skan 0, /* properties_provided */ 4081169699Skan PROP_rtl, /* properties_destroyed */ 4082169699Skan 0, /* todo_flags_start */ 4083169699Skan 0, /* todo_flags_finish */ 4084169699Skan 0 /* letter */ 4085169699Skan}; 4086169699Skan 4087