1*e4b17023SJohn Marino /* Convert RTL to assembler code and output it, for GNU compiler. 2*e4b17023SJohn Marino Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 3*e4b17023SJohn Marino 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 4*e4b17023SJohn Marino 2010, 2011 5*e4b17023SJohn Marino Free Software Foundation, Inc. 6*e4b17023SJohn Marino 7*e4b17023SJohn Marino This file is part of GCC. 8*e4b17023SJohn Marino 9*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under 10*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free 11*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later 12*e4b17023SJohn Marino version. 13*e4b17023SJohn Marino 14*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or 16*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17*e4b17023SJohn Marino for more details. 18*e4b17023SJohn Marino 19*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 20*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 21*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 22*e4b17023SJohn Marino 23*e4b17023SJohn Marino /* This is the final pass of the compiler. 24*e4b17023SJohn Marino It looks at the rtl code for a function and outputs assembler code. 25*e4b17023SJohn Marino 26*e4b17023SJohn Marino Call `final_start_function' to output the assembler code for function entry, 27*e4b17023SJohn Marino `final' to output assembler code for some RTL code, 28*e4b17023SJohn Marino `final_end_function' to output assembler code for function exit. 29*e4b17023SJohn Marino If a function is compiled in several pieces, each piece is 30*e4b17023SJohn Marino output separately with `final'. 31*e4b17023SJohn Marino 32*e4b17023SJohn Marino Some optimizations are also done at this level. 33*e4b17023SJohn Marino Move instructions that were made unnecessary by good register allocation 34*e4b17023SJohn Marino are detected and omitted from the output. (Though most of these 35*e4b17023SJohn Marino are removed by the last jump pass.) 36*e4b17023SJohn Marino 37*e4b17023SJohn Marino Instructions to set the condition codes are omitted when it can be 38*e4b17023SJohn Marino seen that the condition codes already had the desired values. 39*e4b17023SJohn Marino 40*e4b17023SJohn Marino In some cases it is sufficient if the inherited condition codes 41*e4b17023SJohn Marino have related values, but this may require the following insn 42*e4b17023SJohn Marino (the one that tests the condition codes) to be modified. 43*e4b17023SJohn Marino 44*e4b17023SJohn Marino The code for the function prologue and epilogue are generated 45*e4b17023SJohn Marino directly in assembler by the target functions function_prologue and 46*e4b17023SJohn Marino function_epilogue. Those instructions never exist as rtl. */ 47*e4b17023SJohn Marino 48*e4b17023SJohn Marino #include "config.h" 49*e4b17023SJohn Marino #include "system.h" 50*e4b17023SJohn Marino #include "coretypes.h" 51*e4b17023SJohn Marino #include "tm.h" 52*e4b17023SJohn Marino 53*e4b17023SJohn Marino #include "tree.h" 54*e4b17023SJohn Marino #include "rtl.h" 55*e4b17023SJohn Marino #include "tm_p.h" 56*e4b17023SJohn Marino #include "regs.h" 57*e4b17023SJohn Marino #include "insn-config.h" 58*e4b17023SJohn Marino #include "insn-attr.h" 59*e4b17023SJohn Marino #include "recog.h" 60*e4b17023SJohn Marino #include "conditions.h" 61*e4b17023SJohn Marino #include "flags.h" 62*e4b17023SJohn Marino #include "hard-reg-set.h" 63*e4b17023SJohn Marino #include "output.h" 64*e4b17023SJohn Marino #include "except.h" 65*e4b17023SJohn Marino #include "function.h" 66*e4b17023SJohn Marino #include "rtl-error.h" 67*e4b17023SJohn Marino #include "toplev.h" /* exact_log2, floor_log2 */ 68*e4b17023SJohn Marino #include "reload.h" 69*e4b17023SJohn Marino #include "intl.h" 70*e4b17023SJohn Marino #include "basic-block.h" 71*e4b17023SJohn Marino #include "target.h" 72*e4b17023SJohn Marino #include "targhooks.h" 73*e4b17023SJohn Marino #include "debug.h" 74*e4b17023SJohn Marino #include "expr.h" 75*e4b17023SJohn Marino #include "cfglayout.h" 76*e4b17023SJohn Marino #include "tree-pass.h" 77*e4b17023SJohn Marino #include "tree-flow.h" 78*e4b17023SJohn Marino #include "timevar.h" 79*e4b17023SJohn Marino #include "cgraph.h" 80*e4b17023SJohn Marino #include "coverage.h" 81*e4b17023SJohn Marino #include "df.h" 82*e4b17023SJohn Marino #include "vecprim.h" 83*e4b17023SJohn Marino #include "ggc.h" 84*e4b17023SJohn Marino #include "cfgloop.h" 85*e4b17023SJohn Marino #include "params.h" 86*e4b17023SJohn Marino #include "tree-pretty-print.h" 87*e4b17023SJohn Marino 88*e4b17023SJohn Marino #ifdef XCOFF_DEBUGGING_INFO 89*e4b17023SJohn Marino #include "xcoffout.h" /* Needed for external data 90*e4b17023SJohn Marino declarations for e.g. AIX 4.x. */ 91*e4b17023SJohn Marino #endif 92*e4b17023SJohn Marino 93*e4b17023SJohn Marino #include "dwarf2out.h" 94*e4b17023SJohn Marino 95*e4b17023SJohn Marino #ifdef DBX_DEBUGGING_INFO 96*e4b17023SJohn Marino #include "dbxout.h" 97*e4b17023SJohn Marino #endif 98*e4b17023SJohn Marino 99*e4b17023SJohn Marino #ifdef SDB_DEBUGGING_INFO 100*e4b17023SJohn Marino #include "sdbout.h" 101*e4b17023SJohn Marino #endif 102*e4b17023SJohn Marino 103*e4b17023SJohn Marino /* Most ports that aren't using cc0 don't need to define CC_STATUS_INIT. 104*e4b17023SJohn Marino So define a null default for it to save conditionalization later. */ 105*e4b17023SJohn Marino #ifndef CC_STATUS_INIT 106*e4b17023SJohn Marino #define CC_STATUS_INIT 107*e4b17023SJohn Marino #endif 108*e4b17023SJohn Marino 109*e4b17023SJohn Marino /* Is the given character a logical line separator for the assembler? */ 110*e4b17023SJohn Marino #ifndef IS_ASM_LOGICAL_LINE_SEPARATOR 111*e4b17023SJohn Marino #define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == ';') 112*e4b17023SJohn Marino #endif 113*e4b17023SJohn Marino 114*e4b17023SJohn Marino #ifndef JUMP_TABLES_IN_TEXT_SECTION 115*e4b17023SJohn Marino #define JUMP_TABLES_IN_TEXT_SECTION 0 116*e4b17023SJohn Marino #endif 117*e4b17023SJohn Marino 118*e4b17023SJohn Marino /* Bitflags used by final_scan_insn. */ 119*e4b17023SJohn Marino #define SEEN_BB 1 120*e4b17023SJohn Marino #define SEEN_NOTE 2 121*e4b17023SJohn Marino #define SEEN_EMITTED 4 122*e4b17023SJohn Marino 123*e4b17023SJohn Marino /* Last insn processed by final_scan_insn. */ 124*e4b17023SJohn Marino static rtx debug_insn; 125*e4b17023SJohn Marino rtx current_output_insn; 126*e4b17023SJohn Marino 127*e4b17023SJohn Marino /* Line number of last NOTE. */ 128*e4b17023SJohn Marino static int last_linenum; 129*e4b17023SJohn Marino 130*e4b17023SJohn Marino /* Last discriminator written to assembly. */ 131*e4b17023SJohn Marino static int last_discriminator; 132*e4b17023SJohn Marino 133*e4b17023SJohn Marino /* Discriminator of current block. */ 134*e4b17023SJohn Marino static int discriminator; 135*e4b17023SJohn Marino 136*e4b17023SJohn Marino /* Highest line number in current block. */ 137*e4b17023SJohn Marino static int high_block_linenum; 138*e4b17023SJohn Marino 139*e4b17023SJohn Marino /* Likewise for function. */ 140*e4b17023SJohn Marino static int high_function_linenum; 141*e4b17023SJohn Marino 142*e4b17023SJohn Marino /* Filename of last NOTE. */ 143*e4b17023SJohn Marino static const char *last_filename; 144*e4b17023SJohn Marino 145*e4b17023SJohn Marino /* Override filename and line number. */ 146*e4b17023SJohn Marino static const char *override_filename; 147*e4b17023SJohn Marino static int override_linenum; 148*e4b17023SJohn Marino 149*e4b17023SJohn Marino /* Whether to force emission of a line note before the next insn. */ 150*e4b17023SJohn Marino static bool force_source_line = false; 151*e4b17023SJohn Marino 152*e4b17023SJohn Marino extern const int length_unit_log; /* This is defined in insn-attrtab.c. */ 153*e4b17023SJohn Marino 154*e4b17023SJohn Marino /* Nonzero while outputting an `asm' with operands. 155*e4b17023SJohn Marino This means that inconsistencies are the user's fault, so don't die. 156*e4b17023SJohn Marino The precise value is the insn being output, to pass to error_for_asm. */ 157*e4b17023SJohn Marino rtx this_is_asm_operands; 158*e4b17023SJohn Marino 159*e4b17023SJohn Marino /* Number of operands of this insn, for an `asm' with operands. */ 160*e4b17023SJohn Marino static unsigned int insn_noperands; 161*e4b17023SJohn Marino 162*e4b17023SJohn Marino /* Compare optimization flag. */ 163*e4b17023SJohn Marino 164*e4b17023SJohn Marino static rtx last_ignored_compare = 0; 165*e4b17023SJohn Marino 166*e4b17023SJohn Marino /* Assign a unique number to each insn that is output. 167*e4b17023SJohn Marino This can be used to generate unique local labels. */ 168*e4b17023SJohn Marino 169*e4b17023SJohn Marino static int insn_counter = 0; 170*e4b17023SJohn Marino 171*e4b17023SJohn Marino #ifdef HAVE_cc0 172*e4b17023SJohn Marino /* This variable contains machine-dependent flags (defined in tm.h) 173*e4b17023SJohn Marino set and examined by output routines 174*e4b17023SJohn Marino that describe how to interpret the condition codes properly. */ 175*e4b17023SJohn Marino 176*e4b17023SJohn Marino CC_STATUS cc_status; 177*e4b17023SJohn Marino 178*e4b17023SJohn Marino /* During output of an insn, this contains a copy of cc_status 179*e4b17023SJohn Marino from before the insn. */ 180*e4b17023SJohn Marino 181*e4b17023SJohn Marino CC_STATUS cc_prev_status; 182*e4b17023SJohn Marino #endif 183*e4b17023SJohn Marino 184*e4b17023SJohn Marino /* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen. */ 185*e4b17023SJohn Marino 186*e4b17023SJohn Marino static int block_depth; 187*e4b17023SJohn Marino 188*e4b17023SJohn Marino /* Nonzero if have enabled APP processing of our assembler output. */ 189*e4b17023SJohn Marino 190*e4b17023SJohn Marino static int app_on; 191*e4b17023SJohn Marino 192*e4b17023SJohn Marino /* If we are outputting an insn sequence, this contains the sequence rtx. 193*e4b17023SJohn Marino Zero otherwise. */ 194*e4b17023SJohn Marino 195*e4b17023SJohn Marino rtx final_sequence; 196*e4b17023SJohn Marino 197*e4b17023SJohn Marino #ifdef ASSEMBLER_DIALECT 198*e4b17023SJohn Marino 199*e4b17023SJohn Marino /* Number of the assembler dialect to use, starting at 0. */ 200*e4b17023SJohn Marino static int dialect_number; 201*e4b17023SJohn Marino #endif 202*e4b17023SJohn Marino 203*e4b17023SJohn Marino /* Nonnull if the insn currently being emitted was a COND_EXEC pattern. */ 204*e4b17023SJohn Marino rtx current_insn_predicate; 205*e4b17023SJohn Marino 206*e4b17023SJohn Marino /* True if printing into -fdump-final-insns= dump. */ 207*e4b17023SJohn Marino bool final_insns_dump_p; 208*e4b17023SJohn Marino 209*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 210*e4b17023SJohn Marino static int asm_insn_count (rtx); 211*e4b17023SJohn Marino #endif 212*e4b17023SJohn Marino static void profile_function (FILE *); 213*e4b17023SJohn Marino static void profile_after_prologue (FILE *); 214*e4b17023SJohn Marino static bool notice_source_line (rtx, bool *); 215*e4b17023SJohn Marino static rtx walk_alter_subreg (rtx *, bool *); 216*e4b17023SJohn Marino static void output_asm_name (void); 217*e4b17023SJohn Marino static void output_alternate_entry_point (FILE *, rtx); 218*e4b17023SJohn Marino static tree get_mem_expr_from_op (rtx, int *); 219*e4b17023SJohn Marino static void output_asm_operand_names (rtx *, int *, int); 220*e4b17023SJohn Marino #ifdef LEAF_REGISTERS 221*e4b17023SJohn Marino static void leaf_renumber_regs (rtx); 222*e4b17023SJohn Marino #endif 223*e4b17023SJohn Marino #ifdef HAVE_cc0 224*e4b17023SJohn Marino static int alter_cond (rtx); 225*e4b17023SJohn Marino #endif 226*e4b17023SJohn Marino #ifndef ADDR_VEC_ALIGN 227*e4b17023SJohn Marino static int final_addr_vec_align (rtx); 228*e4b17023SJohn Marino #endif 229*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 230*e4b17023SJohn Marino static int align_fuzz (rtx, rtx, int, unsigned); 231*e4b17023SJohn Marino #endif 232*e4b17023SJohn Marino 233*e4b17023SJohn Marino /* Initialize data in final at the beginning of a compilation. */ 234*e4b17023SJohn Marino 235*e4b17023SJohn Marino void 236*e4b17023SJohn Marino init_final (const char *filename ATTRIBUTE_UNUSED) 237*e4b17023SJohn Marino { 238*e4b17023SJohn Marino app_on = 0; 239*e4b17023SJohn Marino final_sequence = 0; 240*e4b17023SJohn Marino 241*e4b17023SJohn Marino #ifdef ASSEMBLER_DIALECT 242*e4b17023SJohn Marino dialect_number = ASSEMBLER_DIALECT; 243*e4b17023SJohn Marino #endif 244*e4b17023SJohn Marino } 245*e4b17023SJohn Marino 246*e4b17023SJohn Marino /* Default target function prologue and epilogue assembler output. 247*e4b17023SJohn Marino 248*e4b17023SJohn Marino If not overridden for epilogue code, then the function body itself 249*e4b17023SJohn Marino contains return instructions wherever needed. */ 250*e4b17023SJohn Marino void 251*e4b17023SJohn Marino default_function_pro_epilogue (FILE *file ATTRIBUTE_UNUSED, 252*e4b17023SJohn Marino HOST_WIDE_INT size ATTRIBUTE_UNUSED) 253*e4b17023SJohn Marino { 254*e4b17023SJohn Marino } 255*e4b17023SJohn Marino 256*e4b17023SJohn Marino void 257*e4b17023SJohn Marino default_function_switched_text_sections (FILE *file ATTRIBUTE_UNUSED, 258*e4b17023SJohn Marino tree decl ATTRIBUTE_UNUSED, 259*e4b17023SJohn Marino bool new_is_cold ATTRIBUTE_UNUSED) 260*e4b17023SJohn Marino { 261*e4b17023SJohn Marino } 262*e4b17023SJohn Marino 263*e4b17023SJohn Marino /* Default target hook that outputs nothing to a stream. */ 264*e4b17023SJohn Marino void 265*e4b17023SJohn Marino no_asm_to_stream (FILE *file ATTRIBUTE_UNUSED) 266*e4b17023SJohn Marino { 267*e4b17023SJohn Marino } 268*e4b17023SJohn Marino 269*e4b17023SJohn Marino /* Enable APP processing of subsequent output. 270*e4b17023SJohn Marino Used before the output from an `asm' statement. */ 271*e4b17023SJohn Marino 272*e4b17023SJohn Marino void 273*e4b17023SJohn Marino app_enable (void) 274*e4b17023SJohn Marino { 275*e4b17023SJohn Marino if (! app_on) 276*e4b17023SJohn Marino { 277*e4b17023SJohn Marino fputs (ASM_APP_ON, asm_out_file); 278*e4b17023SJohn Marino app_on = 1; 279*e4b17023SJohn Marino } 280*e4b17023SJohn Marino } 281*e4b17023SJohn Marino 282*e4b17023SJohn Marino /* Disable APP processing of subsequent output. 283*e4b17023SJohn Marino Called from varasm.c before most kinds of output. */ 284*e4b17023SJohn Marino 285*e4b17023SJohn Marino void 286*e4b17023SJohn Marino app_disable (void) 287*e4b17023SJohn Marino { 288*e4b17023SJohn Marino if (app_on) 289*e4b17023SJohn Marino { 290*e4b17023SJohn Marino fputs (ASM_APP_OFF, asm_out_file); 291*e4b17023SJohn Marino app_on = 0; 292*e4b17023SJohn Marino } 293*e4b17023SJohn Marino } 294*e4b17023SJohn Marino 295*e4b17023SJohn Marino /* Return the number of slots filled in the current 296*e4b17023SJohn Marino delayed branch sequence (we don't count the insn needing the 297*e4b17023SJohn Marino delay slot). Zero if not in a delayed branch sequence. */ 298*e4b17023SJohn Marino 299*e4b17023SJohn Marino #ifdef DELAY_SLOTS 300*e4b17023SJohn Marino int 301*e4b17023SJohn Marino dbr_sequence_length (void) 302*e4b17023SJohn Marino { 303*e4b17023SJohn Marino if (final_sequence != 0) 304*e4b17023SJohn Marino return XVECLEN (final_sequence, 0) - 1; 305*e4b17023SJohn Marino else 306*e4b17023SJohn Marino return 0; 307*e4b17023SJohn Marino } 308*e4b17023SJohn Marino #endif 309*e4b17023SJohn Marino 310*e4b17023SJohn Marino /* The next two pages contain routines used to compute the length of an insn 311*e4b17023SJohn Marino and to shorten branches. */ 312*e4b17023SJohn Marino 313*e4b17023SJohn Marino /* Arrays for insn lengths, and addresses. The latter is referenced by 314*e4b17023SJohn Marino `insn_current_length'. */ 315*e4b17023SJohn Marino 316*e4b17023SJohn Marino static int *insn_lengths; 317*e4b17023SJohn Marino 318*e4b17023SJohn Marino VEC(int,heap) *insn_addresses_; 319*e4b17023SJohn Marino 320*e4b17023SJohn Marino /* Max uid for which the above arrays are valid. */ 321*e4b17023SJohn Marino static int insn_lengths_max_uid; 322*e4b17023SJohn Marino 323*e4b17023SJohn Marino /* Address of insn being processed. Used by `insn_current_length'. */ 324*e4b17023SJohn Marino int insn_current_address; 325*e4b17023SJohn Marino 326*e4b17023SJohn Marino /* Address of insn being processed in previous iteration. */ 327*e4b17023SJohn Marino int insn_last_address; 328*e4b17023SJohn Marino 329*e4b17023SJohn Marino /* known invariant alignment of insn being processed. */ 330*e4b17023SJohn Marino int insn_current_align; 331*e4b17023SJohn Marino 332*e4b17023SJohn Marino /* After shorten_branches, for any insn, uid_align[INSN_UID (insn)] 333*e4b17023SJohn Marino gives the next following alignment insn that increases the known 334*e4b17023SJohn Marino alignment, or NULL_RTX if there is no such insn. 335*e4b17023SJohn Marino For any alignment obtained this way, we can again index uid_align with 336*e4b17023SJohn Marino its uid to obtain the next following align that in turn increases the 337*e4b17023SJohn Marino alignment, till we reach NULL_RTX; the sequence obtained this way 338*e4b17023SJohn Marino for each insn we'll call the alignment chain of this insn in the following 339*e4b17023SJohn Marino comments. */ 340*e4b17023SJohn Marino 341*e4b17023SJohn Marino struct label_alignment 342*e4b17023SJohn Marino { 343*e4b17023SJohn Marino short alignment; 344*e4b17023SJohn Marino short max_skip; 345*e4b17023SJohn Marino }; 346*e4b17023SJohn Marino 347*e4b17023SJohn Marino static rtx *uid_align; 348*e4b17023SJohn Marino static int *uid_shuid; 349*e4b17023SJohn Marino static struct label_alignment *label_align; 350*e4b17023SJohn Marino 351*e4b17023SJohn Marino /* Indicate that branch shortening hasn't yet been done. */ 352*e4b17023SJohn Marino 353*e4b17023SJohn Marino void 354*e4b17023SJohn Marino init_insn_lengths (void) 355*e4b17023SJohn Marino { 356*e4b17023SJohn Marino if (uid_shuid) 357*e4b17023SJohn Marino { 358*e4b17023SJohn Marino free (uid_shuid); 359*e4b17023SJohn Marino uid_shuid = 0; 360*e4b17023SJohn Marino } 361*e4b17023SJohn Marino if (insn_lengths) 362*e4b17023SJohn Marino { 363*e4b17023SJohn Marino free (insn_lengths); 364*e4b17023SJohn Marino insn_lengths = 0; 365*e4b17023SJohn Marino insn_lengths_max_uid = 0; 366*e4b17023SJohn Marino } 367*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 368*e4b17023SJohn Marino INSN_ADDRESSES_FREE (); 369*e4b17023SJohn Marino #endif 370*e4b17023SJohn Marino if (uid_align) 371*e4b17023SJohn Marino { 372*e4b17023SJohn Marino free (uid_align); 373*e4b17023SJohn Marino uid_align = 0; 374*e4b17023SJohn Marino } 375*e4b17023SJohn Marino } 376*e4b17023SJohn Marino 377*e4b17023SJohn Marino /* Obtain the current length of an insn. If branch shortening has been done, 378*e4b17023SJohn Marino get its actual length. Otherwise, use FALLBACK_FN to calculate the 379*e4b17023SJohn Marino length. */ 380*e4b17023SJohn Marino static inline int 381*e4b17023SJohn Marino get_attr_length_1 (rtx insn ATTRIBUTE_UNUSED, 382*e4b17023SJohn Marino int (*fallback_fn) (rtx) ATTRIBUTE_UNUSED) 383*e4b17023SJohn Marino { 384*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 385*e4b17023SJohn Marino rtx body; 386*e4b17023SJohn Marino int i; 387*e4b17023SJohn Marino int length = 0; 388*e4b17023SJohn Marino 389*e4b17023SJohn Marino if (insn_lengths_max_uid > INSN_UID (insn)) 390*e4b17023SJohn Marino return insn_lengths[INSN_UID (insn)]; 391*e4b17023SJohn Marino else 392*e4b17023SJohn Marino switch (GET_CODE (insn)) 393*e4b17023SJohn Marino { 394*e4b17023SJohn Marino case NOTE: 395*e4b17023SJohn Marino case BARRIER: 396*e4b17023SJohn Marino case CODE_LABEL: 397*e4b17023SJohn Marino case DEBUG_INSN: 398*e4b17023SJohn Marino return 0; 399*e4b17023SJohn Marino 400*e4b17023SJohn Marino case CALL_INSN: 401*e4b17023SJohn Marino length = fallback_fn (insn); 402*e4b17023SJohn Marino break; 403*e4b17023SJohn Marino 404*e4b17023SJohn Marino case JUMP_INSN: 405*e4b17023SJohn Marino body = PATTERN (insn); 406*e4b17023SJohn Marino if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 407*e4b17023SJohn Marino { 408*e4b17023SJohn Marino /* Alignment is machine-dependent and should be handled by 409*e4b17023SJohn Marino ADDR_VEC_ALIGN. */ 410*e4b17023SJohn Marino } 411*e4b17023SJohn Marino else 412*e4b17023SJohn Marino length = fallback_fn (insn); 413*e4b17023SJohn Marino break; 414*e4b17023SJohn Marino 415*e4b17023SJohn Marino case INSN: 416*e4b17023SJohn Marino body = PATTERN (insn); 417*e4b17023SJohn Marino if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER) 418*e4b17023SJohn Marino return 0; 419*e4b17023SJohn Marino 420*e4b17023SJohn Marino else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) 421*e4b17023SJohn Marino length = asm_insn_count (body) * fallback_fn (insn); 422*e4b17023SJohn Marino else if (GET_CODE (body) == SEQUENCE) 423*e4b17023SJohn Marino for (i = 0; i < XVECLEN (body, 0); i++) 424*e4b17023SJohn Marino length += get_attr_length_1 (XVECEXP (body, 0, i), fallback_fn); 425*e4b17023SJohn Marino else 426*e4b17023SJohn Marino length = fallback_fn (insn); 427*e4b17023SJohn Marino break; 428*e4b17023SJohn Marino 429*e4b17023SJohn Marino default: 430*e4b17023SJohn Marino break; 431*e4b17023SJohn Marino } 432*e4b17023SJohn Marino 433*e4b17023SJohn Marino #ifdef ADJUST_INSN_LENGTH 434*e4b17023SJohn Marino ADJUST_INSN_LENGTH (insn, length); 435*e4b17023SJohn Marino #endif 436*e4b17023SJohn Marino return length; 437*e4b17023SJohn Marino #else /* not HAVE_ATTR_length */ 438*e4b17023SJohn Marino return 0; 439*e4b17023SJohn Marino #define insn_default_length 0 440*e4b17023SJohn Marino #define insn_min_length 0 441*e4b17023SJohn Marino #endif /* not HAVE_ATTR_length */ 442*e4b17023SJohn Marino } 443*e4b17023SJohn Marino 444*e4b17023SJohn Marino /* Obtain the current length of an insn. If branch shortening has been done, 445*e4b17023SJohn Marino get its actual length. Otherwise, get its maximum length. */ 446*e4b17023SJohn Marino int 447*e4b17023SJohn Marino get_attr_length (rtx insn) 448*e4b17023SJohn Marino { 449*e4b17023SJohn Marino return get_attr_length_1 (insn, insn_default_length); 450*e4b17023SJohn Marino } 451*e4b17023SJohn Marino 452*e4b17023SJohn Marino /* Obtain the current length of an insn. If branch shortening has been done, 453*e4b17023SJohn Marino get its actual length. Otherwise, get its minimum length. */ 454*e4b17023SJohn Marino int 455*e4b17023SJohn Marino get_attr_min_length (rtx insn) 456*e4b17023SJohn Marino { 457*e4b17023SJohn Marino return get_attr_length_1 (insn, insn_min_length); 458*e4b17023SJohn Marino } 459*e4b17023SJohn Marino 460*e4b17023SJohn Marino /* Code to handle alignment inside shorten_branches. */ 461*e4b17023SJohn Marino 462*e4b17023SJohn Marino /* Here is an explanation how the algorithm in align_fuzz can give 463*e4b17023SJohn Marino proper results: 464*e4b17023SJohn Marino 465*e4b17023SJohn Marino Call a sequence of instructions beginning with alignment point X 466*e4b17023SJohn Marino and continuing until the next alignment point `block X'. When `X' 467*e4b17023SJohn Marino is used in an expression, it means the alignment value of the 468*e4b17023SJohn Marino alignment point. 469*e4b17023SJohn Marino 470*e4b17023SJohn Marino Call the distance between the start of the first insn of block X, and 471*e4b17023SJohn Marino the end of the last insn of block X `IX', for the `inner size of X'. 472*e4b17023SJohn Marino This is clearly the sum of the instruction lengths. 473*e4b17023SJohn Marino 474*e4b17023SJohn Marino Likewise with the next alignment-delimited block following X, which we 475*e4b17023SJohn Marino shall call block Y. 476*e4b17023SJohn Marino 477*e4b17023SJohn Marino Call the distance between the start of the first insn of block X, and 478*e4b17023SJohn Marino the start of the first insn of block Y `OX', for the `outer size of X'. 479*e4b17023SJohn Marino 480*e4b17023SJohn Marino The estimated padding is then OX - IX. 481*e4b17023SJohn Marino 482*e4b17023SJohn Marino OX can be safely estimated as 483*e4b17023SJohn Marino 484*e4b17023SJohn Marino if (X >= Y) 485*e4b17023SJohn Marino OX = round_up(IX, Y) 486*e4b17023SJohn Marino else 487*e4b17023SJohn Marino OX = round_up(IX, X) + Y - X 488*e4b17023SJohn Marino 489*e4b17023SJohn Marino Clearly est(IX) >= real(IX), because that only depends on the 490*e4b17023SJohn Marino instruction lengths, and those being overestimated is a given. 491*e4b17023SJohn Marino 492*e4b17023SJohn Marino Clearly round_up(foo, Z) >= round_up(bar, Z) if foo >= bar, so 493*e4b17023SJohn Marino we needn't worry about that when thinking about OX. 494*e4b17023SJohn Marino 495*e4b17023SJohn Marino When X >= Y, the alignment provided by Y adds no uncertainty factor 496*e4b17023SJohn Marino for branch ranges starting before X, so we can just round what we have. 497*e4b17023SJohn Marino But when X < Y, we don't know anything about the, so to speak, 498*e4b17023SJohn Marino `middle bits', so we have to assume the worst when aligning up from an 499*e4b17023SJohn Marino address mod X to one mod Y, which is Y - X. */ 500*e4b17023SJohn Marino 501*e4b17023SJohn Marino #ifndef LABEL_ALIGN 502*e4b17023SJohn Marino #define LABEL_ALIGN(LABEL) align_labels_log 503*e4b17023SJohn Marino #endif 504*e4b17023SJohn Marino 505*e4b17023SJohn Marino #ifndef LOOP_ALIGN 506*e4b17023SJohn Marino #define LOOP_ALIGN(LABEL) align_loops_log 507*e4b17023SJohn Marino #endif 508*e4b17023SJohn Marino 509*e4b17023SJohn Marino #ifndef LABEL_ALIGN_AFTER_BARRIER 510*e4b17023SJohn Marino #define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0 511*e4b17023SJohn Marino #endif 512*e4b17023SJohn Marino 513*e4b17023SJohn Marino #ifndef JUMP_ALIGN 514*e4b17023SJohn Marino #define JUMP_ALIGN(LABEL) align_jumps_log 515*e4b17023SJohn Marino #endif 516*e4b17023SJohn Marino 517*e4b17023SJohn Marino int 518*e4b17023SJohn Marino default_label_align_after_barrier_max_skip (rtx insn ATTRIBUTE_UNUSED) 519*e4b17023SJohn Marino { 520*e4b17023SJohn Marino return 0; 521*e4b17023SJohn Marino } 522*e4b17023SJohn Marino 523*e4b17023SJohn Marino int 524*e4b17023SJohn Marino default_loop_align_max_skip (rtx insn ATTRIBUTE_UNUSED) 525*e4b17023SJohn Marino { 526*e4b17023SJohn Marino return align_loops_max_skip; 527*e4b17023SJohn Marino } 528*e4b17023SJohn Marino 529*e4b17023SJohn Marino int 530*e4b17023SJohn Marino default_label_align_max_skip (rtx insn ATTRIBUTE_UNUSED) 531*e4b17023SJohn Marino { 532*e4b17023SJohn Marino return align_labels_max_skip; 533*e4b17023SJohn Marino } 534*e4b17023SJohn Marino 535*e4b17023SJohn Marino int 536*e4b17023SJohn Marino default_jump_align_max_skip (rtx insn ATTRIBUTE_UNUSED) 537*e4b17023SJohn Marino { 538*e4b17023SJohn Marino return align_jumps_max_skip; 539*e4b17023SJohn Marino } 540*e4b17023SJohn Marino 541*e4b17023SJohn Marino #ifndef ADDR_VEC_ALIGN 542*e4b17023SJohn Marino static int 543*e4b17023SJohn Marino final_addr_vec_align (rtx addr_vec) 544*e4b17023SJohn Marino { 545*e4b17023SJohn Marino int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec))); 546*e4b17023SJohn Marino 547*e4b17023SJohn Marino if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT) 548*e4b17023SJohn Marino align = BIGGEST_ALIGNMENT / BITS_PER_UNIT; 549*e4b17023SJohn Marino return exact_log2 (align); 550*e4b17023SJohn Marino 551*e4b17023SJohn Marino } 552*e4b17023SJohn Marino 553*e4b17023SJohn Marino #define ADDR_VEC_ALIGN(ADDR_VEC) final_addr_vec_align (ADDR_VEC) 554*e4b17023SJohn Marino #endif 555*e4b17023SJohn Marino 556*e4b17023SJohn Marino #ifndef INSN_LENGTH_ALIGNMENT 557*e4b17023SJohn Marino #define INSN_LENGTH_ALIGNMENT(INSN) length_unit_log 558*e4b17023SJohn Marino #endif 559*e4b17023SJohn Marino 560*e4b17023SJohn Marino #define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)]) 561*e4b17023SJohn Marino 562*e4b17023SJohn Marino static int min_labelno, max_labelno; 563*e4b17023SJohn Marino 564*e4b17023SJohn Marino #define LABEL_TO_ALIGNMENT(LABEL) \ 565*e4b17023SJohn Marino (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].alignment) 566*e4b17023SJohn Marino 567*e4b17023SJohn Marino #define LABEL_TO_MAX_SKIP(LABEL) \ 568*e4b17023SJohn Marino (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].max_skip) 569*e4b17023SJohn Marino 570*e4b17023SJohn Marino /* For the benefit of port specific code do this also as a function. */ 571*e4b17023SJohn Marino 572*e4b17023SJohn Marino int 573*e4b17023SJohn Marino label_to_alignment (rtx label) 574*e4b17023SJohn Marino { 575*e4b17023SJohn Marino if (CODE_LABEL_NUMBER (label) <= max_labelno) 576*e4b17023SJohn Marino return LABEL_TO_ALIGNMENT (label); 577*e4b17023SJohn Marino return 0; 578*e4b17023SJohn Marino } 579*e4b17023SJohn Marino 580*e4b17023SJohn Marino int 581*e4b17023SJohn Marino label_to_max_skip (rtx label) 582*e4b17023SJohn Marino { 583*e4b17023SJohn Marino if (CODE_LABEL_NUMBER (label) <= max_labelno) 584*e4b17023SJohn Marino return LABEL_TO_MAX_SKIP (label); 585*e4b17023SJohn Marino return 0; 586*e4b17023SJohn Marino } 587*e4b17023SJohn Marino 588*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 589*e4b17023SJohn Marino /* The differences in addresses 590*e4b17023SJohn Marino between a branch and its target might grow or shrink depending on 591*e4b17023SJohn Marino the alignment the start insn of the range (the branch for a forward 592*e4b17023SJohn Marino branch or the label for a backward branch) starts out on; if these 593*e4b17023SJohn Marino differences are used naively, they can even oscillate infinitely. 594*e4b17023SJohn Marino We therefore want to compute a 'worst case' address difference that 595*e4b17023SJohn Marino is independent of the alignment the start insn of the range end 596*e4b17023SJohn Marino up on, and that is at least as large as the actual difference. 597*e4b17023SJohn Marino The function align_fuzz calculates the amount we have to add to the 598*e4b17023SJohn Marino naively computed difference, by traversing the part of the alignment 599*e4b17023SJohn Marino chain of the start insn of the range that is in front of the end insn 600*e4b17023SJohn Marino of the range, and considering for each alignment the maximum amount 601*e4b17023SJohn Marino that it might contribute to a size increase. 602*e4b17023SJohn Marino 603*e4b17023SJohn Marino For casesi tables, we also want to know worst case minimum amounts of 604*e4b17023SJohn Marino address difference, in case a machine description wants to introduce 605*e4b17023SJohn Marino some common offset that is added to all offsets in a table. 606*e4b17023SJohn Marino For this purpose, align_fuzz with a growth argument of 0 computes the 607*e4b17023SJohn Marino appropriate adjustment. */ 608*e4b17023SJohn Marino 609*e4b17023SJohn Marino /* Compute the maximum delta by which the difference of the addresses of 610*e4b17023SJohn Marino START and END might grow / shrink due to a different address for start 611*e4b17023SJohn Marino which changes the size of alignment insns between START and END. 612*e4b17023SJohn Marino KNOWN_ALIGN_LOG is the alignment known for START. 613*e4b17023SJohn Marino GROWTH should be ~0 if the objective is to compute potential code size 614*e4b17023SJohn Marino increase, and 0 if the objective is to compute potential shrink. 615*e4b17023SJohn Marino The return value is undefined for any other value of GROWTH. */ 616*e4b17023SJohn Marino 617*e4b17023SJohn Marino static int 618*e4b17023SJohn Marino align_fuzz (rtx start, rtx end, int known_align_log, unsigned int growth) 619*e4b17023SJohn Marino { 620*e4b17023SJohn Marino int uid = INSN_UID (start); 621*e4b17023SJohn Marino rtx align_label; 622*e4b17023SJohn Marino int known_align = 1 << known_align_log; 623*e4b17023SJohn Marino int end_shuid = INSN_SHUID (end); 624*e4b17023SJohn Marino int fuzz = 0; 625*e4b17023SJohn Marino 626*e4b17023SJohn Marino for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid]) 627*e4b17023SJohn Marino { 628*e4b17023SJohn Marino int align_addr, new_align; 629*e4b17023SJohn Marino 630*e4b17023SJohn Marino uid = INSN_UID (align_label); 631*e4b17023SJohn Marino align_addr = INSN_ADDRESSES (uid) - insn_lengths[uid]; 632*e4b17023SJohn Marino if (uid_shuid[uid] > end_shuid) 633*e4b17023SJohn Marino break; 634*e4b17023SJohn Marino known_align_log = LABEL_TO_ALIGNMENT (align_label); 635*e4b17023SJohn Marino new_align = 1 << known_align_log; 636*e4b17023SJohn Marino if (new_align < known_align) 637*e4b17023SJohn Marino continue; 638*e4b17023SJohn Marino fuzz += (-align_addr ^ growth) & (new_align - known_align); 639*e4b17023SJohn Marino known_align = new_align; 640*e4b17023SJohn Marino } 641*e4b17023SJohn Marino return fuzz; 642*e4b17023SJohn Marino } 643*e4b17023SJohn Marino 644*e4b17023SJohn Marino /* Compute a worst-case reference address of a branch so that it 645*e4b17023SJohn Marino can be safely used in the presence of aligned labels. Since the 646*e4b17023SJohn Marino size of the branch itself is unknown, the size of the branch is 647*e4b17023SJohn Marino not included in the range. I.e. for a forward branch, the reference 648*e4b17023SJohn Marino address is the end address of the branch as known from the previous 649*e4b17023SJohn Marino branch shortening pass, minus a value to account for possible size 650*e4b17023SJohn Marino increase due to alignment. For a backward branch, it is the start 651*e4b17023SJohn Marino address of the branch as known from the current pass, plus a value 652*e4b17023SJohn Marino to account for possible size increase due to alignment. 653*e4b17023SJohn Marino NB.: Therefore, the maximum offset allowed for backward branches needs 654*e4b17023SJohn Marino to exclude the branch size. */ 655*e4b17023SJohn Marino 656*e4b17023SJohn Marino int 657*e4b17023SJohn Marino insn_current_reference_address (rtx branch) 658*e4b17023SJohn Marino { 659*e4b17023SJohn Marino rtx dest, seq; 660*e4b17023SJohn Marino int seq_uid; 661*e4b17023SJohn Marino 662*e4b17023SJohn Marino if (! INSN_ADDRESSES_SET_P ()) 663*e4b17023SJohn Marino return 0; 664*e4b17023SJohn Marino 665*e4b17023SJohn Marino seq = NEXT_INSN (PREV_INSN (branch)); 666*e4b17023SJohn Marino seq_uid = INSN_UID (seq); 667*e4b17023SJohn Marino if (!JUMP_P (branch)) 668*e4b17023SJohn Marino /* This can happen for example on the PA; the objective is to know the 669*e4b17023SJohn Marino offset to address something in front of the start of the function. 670*e4b17023SJohn Marino Thus, we can treat it like a backward branch. 671*e4b17023SJohn Marino We assume here that FUNCTION_BOUNDARY / BITS_PER_UNIT is larger than 672*e4b17023SJohn Marino any alignment we'd encounter, so we skip the call to align_fuzz. */ 673*e4b17023SJohn Marino return insn_current_address; 674*e4b17023SJohn Marino dest = JUMP_LABEL (branch); 675*e4b17023SJohn Marino 676*e4b17023SJohn Marino /* BRANCH has no proper alignment chain set, so use SEQ. 677*e4b17023SJohn Marino BRANCH also has no INSN_SHUID. */ 678*e4b17023SJohn Marino if (INSN_SHUID (seq) < INSN_SHUID (dest)) 679*e4b17023SJohn Marino { 680*e4b17023SJohn Marino /* Forward branch. */ 681*e4b17023SJohn Marino return (insn_last_address + insn_lengths[seq_uid] 682*e4b17023SJohn Marino - align_fuzz (seq, dest, length_unit_log, ~0)); 683*e4b17023SJohn Marino } 684*e4b17023SJohn Marino else 685*e4b17023SJohn Marino { 686*e4b17023SJohn Marino /* Backward branch. */ 687*e4b17023SJohn Marino return (insn_current_address 688*e4b17023SJohn Marino + align_fuzz (dest, seq, length_unit_log, ~0)); 689*e4b17023SJohn Marino } 690*e4b17023SJohn Marino } 691*e4b17023SJohn Marino #endif /* HAVE_ATTR_length */ 692*e4b17023SJohn Marino 693*e4b17023SJohn Marino /* Compute branch alignments based on frequency information in the 694*e4b17023SJohn Marino CFG. */ 695*e4b17023SJohn Marino 696*e4b17023SJohn Marino unsigned int 697*e4b17023SJohn Marino compute_alignments (void) 698*e4b17023SJohn Marino { 699*e4b17023SJohn Marino int log, max_skip, max_log; 700*e4b17023SJohn Marino basic_block bb; 701*e4b17023SJohn Marino int freq_max = 0; 702*e4b17023SJohn Marino int freq_threshold = 0; 703*e4b17023SJohn Marino 704*e4b17023SJohn Marino if (label_align) 705*e4b17023SJohn Marino { 706*e4b17023SJohn Marino free (label_align); 707*e4b17023SJohn Marino label_align = 0; 708*e4b17023SJohn Marino } 709*e4b17023SJohn Marino 710*e4b17023SJohn Marino max_labelno = max_label_num (); 711*e4b17023SJohn Marino min_labelno = get_first_label_num (); 712*e4b17023SJohn Marino label_align = XCNEWVEC (struct label_alignment, max_labelno - min_labelno + 1); 713*e4b17023SJohn Marino 714*e4b17023SJohn Marino /* If not optimizing or optimizing for size, don't assign any alignments. */ 715*e4b17023SJohn Marino if (! optimize || optimize_function_for_size_p (cfun)) 716*e4b17023SJohn Marino return 0; 717*e4b17023SJohn Marino 718*e4b17023SJohn Marino if (dump_file) 719*e4b17023SJohn Marino { 720*e4b17023SJohn Marino dump_flow_info (dump_file, TDF_DETAILS); 721*e4b17023SJohn Marino flow_loops_dump (dump_file, NULL, 1); 722*e4b17023SJohn Marino } 723*e4b17023SJohn Marino loop_optimizer_init (AVOID_CFG_MODIFICATIONS); 724*e4b17023SJohn Marino FOR_EACH_BB (bb) 725*e4b17023SJohn Marino if (bb->frequency > freq_max) 726*e4b17023SJohn Marino freq_max = bb->frequency; 727*e4b17023SJohn Marino freq_threshold = freq_max / PARAM_VALUE (PARAM_ALIGN_THRESHOLD); 728*e4b17023SJohn Marino 729*e4b17023SJohn Marino if (dump_file) 730*e4b17023SJohn Marino fprintf(dump_file, "freq_max: %i\n",freq_max); 731*e4b17023SJohn Marino FOR_EACH_BB (bb) 732*e4b17023SJohn Marino { 733*e4b17023SJohn Marino rtx label = BB_HEAD (bb); 734*e4b17023SJohn Marino int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0; 735*e4b17023SJohn Marino edge e; 736*e4b17023SJohn Marino edge_iterator ei; 737*e4b17023SJohn Marino 738*e4b17023SJohn Marino if (!LABEL_P (label) 739*e4b17023SJohn Marino || optimize_bb_for_size_p (bb)) 740*e4b17023SJohn Marino { 741*e4b17023SJohn Marino if (dump_file) 742*e4b17023SJohn Marino fprintf(dump_file, "BB %4i freq %4i loop %2i loop_depth %2i skipped.\n", 743*e4b17023SJohn Marino bb->index, bb->frequency, bb->loop_father->num, bb->loop_depth); 744*e4b17023SJohn Marino continue; 745*e4b17023SJohn Marino } 746*e4b17023SJohn Marino max_log = LABEL_ALIGN (label); 747*e4b17023SJohn Marino max_skip = targetm.asm_out.label_align_max_skip (label); 748*e4b17023SJohn Marino 749*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds) 750*e4b17023SJohn Marino { 751*e4b17023SJohn Marino if (e->flags & EDGE_FALLTHRU) 752*e4b17023SJohn Marino has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e); 753*e4b17023SJohn Marino else 754*e4b17023SJohn Marino branch_frequency += EDGE_FREQUENCY (e); 755*e4b17023SJohn Marino } 756*e4b17023SJohn Marino if (dump_file) 757*e4b17023SJohn Marino { 758*e4b17023SJohn Marino fprintf(dump_file, "BB %4i freq %4i loop %2i loop_depth %2i fall %4i branch %4i", 759*e4b17023SJohn Marino bb->index, bb->frequency, bb->loop_father->num, 760*e4b17023SJohn Marino bb->loop_depth, 761*e4b17023SJohn Marino fallthru_frequency, branch_frequency); 762*e4b17023SJohn Marino if (!bb->loop_father->inner && bb->loop_father->num) 763*e4b17023SJohn Marino fprintf (dump_file, " inner_loop"); 764*e4b17023SJohn Marino if (bb->loop_father->header == bb) 765*e4b17023SJohn Marino fprintf (dump_file, " loop_header"); 766*e4b17023SJohn Marino fprintf (dump_file, "\n"); 767*e4b17023SJohn Marino } 768*e4b17023SJohn Marino 769*e4b17023SJohn Marino /* There are two purposes to align block with no fallthru incoming edge: 770*e4b17023SJohn Marino 1) to avoid fetch stalls when branch destination is near cache boundary 771*e4b17023SJohn Marino 2) to improve cache efficiency in case the previous block is not executed 772*e4b17023SJohn Marino (so it does not need to be in the cache). 773*e4b17023SJohn Marino 774*e4b17023SJohn Marino We to catch first case, we align frequently executed blocks. 775*e4b17023SJohn Marino To catch the second, we align blocks that are executed more frequently 776*e4b17023SJohn Marino than the predecessor and the predecessor is likely to not be executed 777*e4b17023SJohn Marino when function is called. */ 778*e4b17023SJohn Marino 779*e4b17023SJohn Marino if (!has_fallthru 780*e4b17023SJohn Marino && (branch_frequency > freq_threshold 781*e4b17023SJohn Marino || (bb->frequency > bb->prev_bb->frequency * 10 782*e4b17023SJohn Marino && (bb->prev_bb->frequency 783*e4b17023SJohn Marino <= ENTRY_BLOCK_PTR->frequency / 2)))) 784*e4b17023SJohn Marino { 785*e4b17023SJohn Marino log = JUMP_ALIGN (label); 786*e4b17023SJohn Marino if (dump_file) 787*e4b17023SJohn Marino fprintf(dump_file, " jump alignment added.\n"); 788*e4b17023SJohn Marino if (max_log < log) 789*e4b17023SJohn Marino { 790*e4b17023SJohn Marino max_log = log; 791*e4b17023SJohn Marino max_skip = targetm.asm_out.jump_align_max_skip (label); 792*e4b17023SJohn Marino } 793*e4b17023SJohn Marino } 794*e4b17023SJohn Marino /* In case block is frequent and reached mostly by non-fallthru edge, 795*e4b17023SJohn Marino align it. It is most likely a first block of loop. */ 796*e4b17023SJohn Marino if (has_fallthru 797*e4b17023SJohn Marino && optimize_bb_for_speed_p (bb) 798*e4b17023SJohn Marino && branch_frequency + fallthru_frequency > freq_threshold 799*e4b17023SJohn Marino && (branch_frequency 800*e4b17023SJohn Marino > fallthru_frequency * PARAM_VALUE (PARAM_ALIGN_LOOP_ITERATIONS))) 801*e4b17023SJohn Marino { 802*e4b17023SJohn Marino log = LOOP_ALIGN (label); 803*e4b17023SJohn Marino if (dump_file) 804*e4b17023SJohn Marino fprintf(dump_file, " internal loop alignment added.\n"); 805*e4b17023SJohn Marino if (max_log < log) 806*e4b17023SJohn Marino { 807*e4b17023SJohn Marino max_log = log; 808*e4b17023SJohn Marino max_skip = targetm.asm_out.loop_align_max_skip (label); 809*e4b17023SJohn Marino } 810*e4b17023SJohn Marino } 811*e4b17023SJohn Marino LABEL_TO_ALIGNMENT (label) = max_log; 812*e4b17023SJohn Marino LABEL_TO_MAX_SKIP (label) = max_skip; 813*e4b17023SJohn Marino } 814*e4b17023SJohn Marino 815*e4b17023SJohn Marino loop_optimizer_finalize (); 816*e4b17023SJohn Marino free_dominance_info (CDI_DOMINATORS); 817*e4b17023SJohn Marino return 0; 818*e4b17023SJohn Marino } 819*e4b17023SJohn Marino 820*e4b17023SJohn Marino struct rtl_opt_pass pass_compute_alignments = 821*e4b17023SJohn Marino { 822*e4b17023SJohn Marino { 823*e4b17023SJohn Marino RTL_PASS, 824*e4b17023SJohn Marino "alignments", /* name */ 825*e4b17023SJohn Marino NULL, /* gate */ 826*e4b17023SJohn Marino compute_alignments, /* execute */ 827*e4b17023SJohn Marino NULL, /* sub */ 828*e4b17023SJohn Marino NULL, /* next */ 829*e4b17023SJohn Marino 0, /* static_pass_number */ 830*e4b17023SJohn Marino TV_NONE, /* tv_id */ 831*e4b17023SJohn Marino 0, /* properties_required */ 832*e4b17023SJohn Marino 0, /* properties_provided */ 833*e4b17023SJohn Marino 0, /* properties_destroyed */ 834*e4b17023SJohn Marino 0, /* todo_flags_start */ 835*e4b17023SJohn Marino TODO_verify_rtl_sharing 836*e4b17023SJohn Marino | TODO_ggc_collect /* todo_flags_finish */ 837*e4b17023SJohn Marino } 838*e4b17023SJohn Marino }; 839*e4b17023SJohn Marino 840*e4b17023SJohn Marino 841*e4b17023SJohn Marino /* Make a pass over all insns and compute their actual lengths by shortening 842*e4b17023SJohn Marino any branches of variable length if possible. */ 843*e4b17023SJohn Marino 844*e4b17023SJohn Marino /* shorten_branches might be called multiple times: for example, the SH 845*e4b17023SJohn Marino port splits out-of-range conditional branches in MACHINE_DEPENDENT_REORG. 846*e4b17023SJohn Marino In order to do this, it needs proper length information, which it obtains 847*e4b17023SJohn Marino by calling shorten_branches. This cannot be collapsed with 848*e4b17023SJohn Marino shorten_branches itself into a single pass unless we also want to integrate 849*e4b17023SJohn Marino reorg.c, since the branch splitting exposes new instructions with delay 850*e4b17023SJohn Marino slots. */ 851*e4b17023SJohn Marino 852*e4b17023SJohn Marino void 853*e4b17023SJohn Marino shorten_branches (rtx first ATTRIBUTE_UNUSED) 854*e4b17023SJohn Marino { 855*e4b17023SJohn Marino rtx insn; 856*e4b17023SJohn Marino int max_uid; 857*e4b17023SJohn Marino int i; 858*e4b17023SJohn Marino int max_log; 859*e4b17023SJohn Marino int max_skip; 860*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 861*e4b17023SJohn Marino #define MAX_CODE_ALIGN 16 862*e4b17023SJohn Marino rtx seq; 863*e4b17023SJohn Marino int something_changed = 1; 864*e4b17023SJohn Marino char *varying_length; 865*e4b17023SJohn Marino rtx body; 866*e4b17023SJohn Marino int uid; 867*e4b17023SJohn Marino rtx align_tab[MAX_CODE_ALIGN]; 868*e4b17023SJohn Marino 869*e4b17023SJohn Marino #endif 870*e4b17023SJohn Marino 871*e4b17023SJohn Marino /* Compute maximum UID and allocate label_align / uid_shuid. */ 872*e4b17023SJohn Marino max_uid = get_max_uid (); 873*e4b17023SJohn Marino 874*e4b17023SJohn Marino /* Free uid_shuid before reallocating it. */ 875*e4b17023SJohn Marino free (uid_shuid); 876*e4b17023SJohn Marino 877*e4b17023SJohn Marino uid_shuid = XNEWVEC (int, max_uid); 878*e4b17023SJohn Marino 879*e4b17023SJohn Marino if (max_labelno != max_label_num ()) 880*e4b17023SJohn Marino { 881*e4b17023SJohn Marino int old = max_labelno; 882*e4b17023SJohn Marino int n_labels; 883*e4b17023SJohn Marino int n_old_labels; 884*e4b17023SJohn Marino 885*e4b17023SJohn Marino max_labelno = max_label_num (); 886*e4b17023SJohn Marino 887*e4b17023SJohn Marino n_labels = max_labelno - min_labelno + 1; 888*e4b17023SJohn Marino n_old_labels = old - min_labelno + 1; 889*e4b17023SJohn Marino 890*e4b17023SJohn Marino label_align = XRESIZEVEC (struct label_alignment, label_align, n_labels); 891*e4b17023SJohn Marino 892*e4b17023SJohn Marino /* Range of labels grows monotonically in the function. Failing here 893*e4b17023SJohn Marino means that the initialization of array got lost. */ 894*e4b17023SJohn Marino gcc_assert (n_old_labels <= n_labels); 895*e4b17023SJohn Marino 896*e4b17023SJohn Marino memset (label_align + n_old_labels, 0, 897*e4b17023SJohn Marino (n_labels - n_old_labels) * sizeof (struct label_alignment)); 898*e4b17023SJohn Marino } 899*e4b17023SJohn Marino 900*e4b17023SJohn Marino /* Initialize label_align and set up uid_shuid to be strictly 901*e4b17023SJohn Marino monotonically rising with insn order. */ 902*e4b17023SJohn Marino /* We use max_log here to keep track of the maximum alignment we want to 903*e4b17023SJohn Marino impose on the next CODE_LABEL (or the current one if we are processing 904*e4b17023SJohn Marino the CODE_LABEL itself). */ 905*e4b17023SJohn Marino 906*e4b17023SJohn Marino max_log = 0; 907*e4b17023SJohn Marino max_skip = 0; 908*e4b17023SJohn Marino 909*e4b17023SJohn Marino for (insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn)) 910*e4b17023SJohn Marino { 911*e4b17023SJohn Marino int log; 912*e4b17023SJohn Marino 913*e4b17023SJohn Marino INSN_SHUID (insn) = i++; 914*e4b17023SJohn Marino if (INSN_P (insn)) 915*e4b17023SJohn Marino continue; 916*e4b17023SJohn Marino 917*e4b17023SJohn Marino if (LABEL_P (insn)) 918*e4b17023SJohn Marino { 919*e4b17023SJohn Marino rtx next; 920*e4b17023SJohn Marino bool next_is_jumptable; 921*e4b17023SJohn Marino 922*e4b17023SJohn Marino /* Merge in alignments computed by compute_alignments. */ 923*e4b17023SJohn Marino log = LABEL_TO_ALIGNMENT (insn); 924*e4b17023SJohn Marino if (max_log < log) 925*e4b17023SJohn Marino { 926*e4b17023SJohn Marino max_log = log; 927*e4b17023SJohn Marino max_skip = LABEL_TO_MAX_SKIP (insn); 928*e4b17023SJohn Marino } 929*e4b17023SJohn Marino 930*e4b17023SJohn Marino next = next_nonnote_insn (insn); 931*e4b17023SJohn Marino next_is_jumptable = next && JUMP_TABLE_DATA_P (next); 932*e4b17023SJohn Marino if (!next_is_jumptable) 933*e4b17023SJohn Marino { 934*e4b17023SJohn Marino log = LABEL_ALIGN (insn); 935*e4b17023SJohn Marino if (max_log < log) 936*e4b17023SJohn Marino { 937*e4b17023SJohn Marino max_log = log; 938*e4b17023SJohn Marino max_skip = targetm.asm_out.label_align_max_skip (insn); 939*e4b17023SJohn Marino } 940*e4b17023SJohn Marino } 941*e4b17023SJohn Marino /* ADDR_VECs only take room if read-only data goes into the text 942*e4b17023SJohn Marino section. */ 943*e4b17023SJohn Marino if ((JUMP_TABLES_IN_TEXT_SECTION 944*e4b17023SJohn Marino || readonly_data_section == text_section) 945*e4b17023SJohn Marino && next_is_jumptable) 946*e4b17023SJohn Marino { 947*e4b17023SJohn Marino log = ADDR_VEC_ALIGN (next); 948*e4b17023SJohn Marino if (max_log < log) 949*e4b17023SJohn Marino { 950*e4b17023SJohn Marino max_log = log; 951*e4b17023SJohn Marino max_skip = targetm.asm_out.label_align_max_skip (insn); 952*e4b17023SJohn Marino } 953*e4b17023SJohn Marino } 954*e4b17023SJohn Marino LABEL_TO_ALIGNMENT (insn) = max_log; 955*e4b17023SJohn Marino LABEL_TO_MAX_SKIP (insn) = max_skip; 956*e4b17023SJohn Marino max_log = 0; 957*e4b17023SJohn Marino max_skip = 0; 958*e4b17023SJohn Marino } 959*e4b17023SJohn Marino else if (BARRIER_P (insn)) 960*e4b17023SJohn Marino { 961*e4b17023SJohn Marino rtx label; 962*e4b17023SJohn Marino 963*e4b17023SJohn Marino for (label = insn; label && ! INSN_P (label); 964*e4b17023SJohn Marino label = NEXT_INSN (label)) 965*e4b17023SJohn Marino if (LABEL_P (label)) 966*e4b17023SJohn Marino { 967*e4b17023SJohn Marino log = LABEL_ALIGN_AFTER_BARRIER (insn); 968*e4b17023SJohn Marino if (max_log < log) 969*e4b17023SJohn Marino { 970*e4b17023SJohn Marino max_log = log; 971*e4b17023SJohn Marino max_skip = targetm.asm_out.label_align_after_barrier_max_skip (label); 972*e4b17023SJohn Marino } 973*e4b17023SJohn Marino break; 974*e4b17023SJohn Marino } 975*e4b17023SJohn Marino } 976*e4b17023SJohn Marino } 977*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 978*e4b17023SJohn Marino 979*e4b17023SJohn Marino /* Allocate the rest of the arrays. */ 980*e4b17023SJohn Marino insn_lengths = XNEWVEC (int, max_uid); 981*e4b17023SJohn Marino insn_lengths_max_uid = max_uid; 982*e4b17023SJohn Marino /* Syntax errors can lead to labels being outside of the main insn stream. 983*e4b17023SJohn Marino Initialize insn_addresses, so that we get reproducible results. */ 984*e4b17023SJohn Marino INSN_ADDRESSES_ALLOC (max_uid); 985*e4b17023SJohn Marino 986*e4b17023SJohn Marino varying_length = XCNEWVEC (char, max_uid); 987*e4b17023SJohn Marino 988*e4b17023SJohn Marino /* Initialize uid_align. We scan instructions 989*e4b17023SJohn Marino from end to start, and keep in align_tab[n] the last seen insn 990*e4b17023SJohn Marino that does an alignment of at least n+1, i.e. the successor 991*e4b17023SJohn Marino in the alignment chain for an insn that does / has a known 992*e4b17023SJohn Marino alignment of n. */ 993*e4b17023SJohn Marino uid_align = XCNEWVEC (rtx, max_uid); 994*e4b17023SJohn Marino 995*e4b17023SJohn Marino for (i = MAX_CODE_ALIGN; --i >= 0;) 996*e4b17023SJohn Marino align_tab[i] = NULL_RTX; 997*e4b17023SJohn Marino seq = get_last_insn (); 998*e4b17023SJohn Marino for (; seq; seq = PREV_INSN (seq)) 999*e4b17023SJohn Marino { 1000*e4b17023SJohn Marino int uid = INSN_UID (seq); 1001*e4b17023SJohn Marino int log; 1002*e4b17023SJohn Marino log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq) : 0); 1003*e4b17023SJohn Marino uid_align[uid] = align_tab[0]; 1004*e4b17023SJohn Marino if (log) 1005*e4b17023SJohn Marino { 1006*e4b17023SJohn Marino /* Found an alignment label. */ 1007*e4b17023SJohn Marino uid_align[uid] = align_tab[log]; 1008*e4b17023SJohn Marino for (i = log - 1; i >= 0; i--) 1009*e4b17023SJohn Marino align_tab[i] = seq; 1010*e4b17023SJohn Marino } 1011*e4b17023SJohn Marino } 1012*e4b17023SJohn Marino #ifdef CASE_VECTOR_SHORTEN_MODE 1013*e4b17023SJohn Marino if (optimize) 1014*e4b17023SJohn Marino { 1015*e4b17023SJohn Marino /* Look for ADDR_DIFF_VECs, and initialize their minimum and maximum 1016*e4b17023SJohn Marino label fields. */ 1017*e4b17023SJohn Marino 1018*e4b17023SJohn Marino int min_shuid = INSN_SHUID (get_insns ()) - 1; 1019*e4b17023SJohn Marino int max_shuid = INSN_SHUID (get_last_insn ()) + 1; 1020*e4b17023SJohn Marino int rel; 1021*e4b17023SJohn Marino 1022*e4b17023SJohn Marino for (insn = first; insn != 0; insn = NEXT_INSN (insn)) 1023*e4b17023SJohn Marino { 1024*e4b17023SJohn Marino rtx min_lab = NULL_RTX, max_lab = NULL_RTX, pat; 1025*e4b17023SJohn Marino int len, i, min, max, insn_shuid; 1026*e4b17023SJohn Marino int min_align; 1027*e4b17023SJohn Marino addr_diff_vec_flags flags; 1028*e4b17023SJohn Marino 1029*e4b17023SJohn Marino if (!JUMP_P (insn) 1030*e4b17023SJohn Marino || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) 1031*e4b17023SJohn Marino continue; 1032*e4b17023SJohn Marino pat = PATTERN (insn); 1033*e4b17023SJohn Marino len = XVECLEN (pat, 1); 1034*e4b17023SJohn Marino gcc_assert (len > 0); 1035*e4b17023SJohn Marino min_align = MAX_CODE_ALIGN; 1036*e4b17023SJohn Marino for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--) 1037*e4b17023SJohn Marino { 1038*e4b17023SJohn Marino rtx lab = XEXP (XVECEXP (pat, 1, i), 0); 1039*e4b17023SJohn Marino int shuid = INSN_SHUID (lab); 1040*e4b17023SJohn Marino if (shuid < min) 1041*e4b17023SJohn Marino { 1042*e4b17023SJohn Marino min = shuid; 1043*e4b17023SJohn Marino min_lab = lab; 1044*e4b17023SJohn Marino } 1045*e4b17023SJohn Marino if (shuid > max) 1046*e4b17023SJohn Marino { 1047*e4b17023SJohn Marino max = shuid; 1048*e4b17023SJohn Marino max_lab = lab; 1049*e4b17023SJohn Marino } 1050*e4b17023SJohn Marino if (min_align > LABEL_TO_ALIGNMENT (lab)) 1051*e4b17023SJohn Marino min_align = LABEL_TO_ALIGNMENT (lab); 1052*e4b17023SJohn Marino } 1053*e4b17023SJohn Marino XEXP (pat, 2) = gen_rtx_LABEL_REF (Pmode, min_lab); 1054*e4b17023SJohn Marino XEXP (pat, 3) = gen_rtx_LABEL_REF (Pmode, max_lab); 1055*e4b17023SJohn Marino insn_shuid = INSN_SHUID (insn); 1056*e4b17023SJohn Marino rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0)); 1057*e4b17023SJohn Marino memset (&flags, 0, sizeof (flags)); 1058*e4b17023SJohn Marino flags.min_align = min_align; 1059*e4b17023SJohn Marino flags.base_after_vec = rel > insn_shuid; 1060*e4b17023SJohn Marino flags.min_after_vec = min > insn_shuid; 1061*e4b17023SJohn Marino flags.max_after_vec = max > insn_shuid; 1062*e4b17023SJohn Marino flags.min_after_base = min > rel; 1063*e4b17023SJohn Marino flags.max_after_base = max > rel; 1064*e4b17023SJohn Marino ADDR_DIFF_VEC_FLAGS (pat) = flags; 1065*e4b17023SJohn Marino } 1066*e4b17023SJohn Marino } 1067*e4b17023SJohn Marino #endif /* CASE_VECTOR_SHORTEN_MODE */ 1068*e4b17023SJohn Marino 1069*e4b17023SJohn Marino /* Compute initial lengths, addresses, and varying flags for each insn. */ 1070*e4b17023SJohn Marino for (insn_current_address = 0, insn = first; 1071*e4b17023SJohn Marino insn != 0; 1072*e4b17023SJohn Marino insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) 1073*e4b17023SJohn Marino { 1074*e4b17023SJohn Marino uid = INSN_UID (insn); 1075*e4b17023SJohn Marino 1076*e4b17023SJohn Marino insn_lengths[uid] = 0; 1077*e4b17023SJohn Marino 1078*e4b17023SJohn Marino if (LABEL_P (insn)) 1079*e4b17023SJohn Marino { 1080*e4b17023SJohn Marino int log = LABEL_TO_ALIGNMENT (insn); 1081*e4b17023SJohn Marino if (log) 1082*e4b17023SJohn Marino { 1083*e4b17023SJohn Marino int align = 1 << log; 1084*e4b17023SJohn Marino int new_address = (insn_current_address + align - 1) & -align; 1085*e4b17023SJohn Marino insn_lengths[uid] = new_address - insn_current_address; 1086*e4b17023SJohn Marino } 1087*e4b17023SJohn Marino } 1088*e4b17023SJohn Marino 1089*e4b17023SJohn Marino INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid]; 1090*e4b17023SJohn Marino 1091*e4b17023SJohn Marino if (NOTE_P (insn) || BARRIER_P (insn) 1092*e4b17023SJohn Marino || LABEL_P (insn) || DEBUG_INSN_P(insn)) 1093*e4b17023SJohn Marino continue; 1094*e4b17023SJohn Marino if (INSN_DELETED_P (insn)) 1095*e4b17023SJohn Marino continue; 1096*e4b17023SJohn Marino 1097*e4b17023SJohn Marino body = PATTERN (insn); 1098*e4b17023SJohn Marino if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 1099*e4b17023SJohn Marino { 1100*e4b17023SJohn Marino /* This only takes room if read-only data goes into the text 1101*e4b17023SJohn Marino section. */ 1102*e4b17023SJohn Marino if (JUMP_TABLES_IN_TEXT_SECTION 1103*e4b17023SJohn Marino || readonly_data_section == text_section) 1104*e4b17023SJohn Marino insn_lengths[uid] = (XVECLEN (body, 1105*e4b17023SJohn Marino GET_CODE (body) == ADDR_DIFF_VEC) 1106*e4b17023SJohn Marino * GET_MODE_SIZE (GET_MODE (body))); 1107*e4b17023SJohn Marino /* Alignment is handled by ADDR_VEC_ALIGN. */ 1108*e4b17023SJohn Marino } 1109*e4b17023SJohn Marino else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) 1110*e4b17023SJohn Marino insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn); 1111*e4b17023SJohn Marino else if (GET_CODE (body) == SEQUENCE) 1112*e4b17023SJohn Marino { 1113*e4b17023SJohn Marino int i; 1114*e4b17023SJohn Marino int const_delay_slots; 1115*e4b17023SJohn Marino #ifdef DELAY_SLOTS 1116*e4b17023SJohn Marino const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0)); 1117*e4b17023SJohn Marino #else 1118*e4b17023SJohn Marino const_delay_slots = 0; 1119*e4b17023SJohn Marino #endif 1120*e4b17023SJohn Marino /* Inside a delay slot sequence, we do not do any branch shortening 1121*e4b17023SJohn Marino if the shortening could change the number of delay slots 1122*e4b17023SJohn Marino of the branch. */ 1123*e4b17023SJohn Marino for (i = 0; i < XVECLEN (body, 0); i++) 1124*e4b17023SJohn Marino { 1125*e4b17023SJohn Marino rtx inner_insn = XVECEXP (body, 0, i); 1126*e4b17023SJohn Marino int inner_uid = INSN_UID (inner_insn); 1127*e4b17023SJohn Marino int inner_length; 1128*e4b17023SJohn Marino 1129*e4b17023SJohn Marino if (GET_CODE (body) == ASM_INPUT 1130*e4b17023SJohn Marino || asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0) 1131*e4b17023SJohn Marino inner_length = (asm_insn_count (PATTERN (inner_insn)) 1132*e4b17023SJohn Marino * insn_default_length (inner_insn)); 1133*e4b17023SJohn Marino else 1134*e4b17023SJohn Marino inner_length = insn_default_length (inner_insn); 1135*e4b17023SJohn Marino 1136*e4b17023SJohn Marino insn_lengths[inner_uid] = inner_length; 1137*e4b17023SJohn Marino if (const_delay_slots) 1138*e4b17023SJohn Marino { 1139*e4b17023SJohn Marino if ((varying_length[inner_uid] 1140*e4b17023SJohn Marino = insn_variable_length_p (inner_insn)) != 0) 1141*e4b17023SJohn Marino varying_length[uid] = 1; 1142*e4b17023SJohn Marino INSN_ADDRESSES (inner_uid) = (insn_current_address 1143*e4b17023SJohn Marino + insn_lengths[uid]); 1144*e4b17023SJohn Marino } 1145*e4b17023SJohn Marino else 1146*e4b17023SJohn Marino varying_length[inner_uid] = 0; 1147*e4b17023SJohn Marino insn_lengths[uid] += inner_length; 1148*e4b17023SJohn Marino } 1149*e4b17023SJohn Marino } 1150*e4b17023SJohn Marino else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER) 1151*e4b17023SJohn Marino { 1152*e4b17023SJohn Marino insn_lengths[uid] = insn_default_length (insn); 1153*e4b17023SJohn Marino varying_length[uid] = insn_variable_length_p (insn); 1154*e4b17023SJohn Marino } 1155*e4b17023SJohn Marino 1156*e4b17023SJohn Marino /* If needed, do any adjustment. */ 1157*e4b17023SJohn Marino #ifdef ADJUST_INSN_LENGTH 1158*e4b17023SJohn Marino ADJUST_INSN_LENGTH (insn, insn_lengths[uid]); 1159*e4b17023SJohn Marino if (insn_lengths[uid] < 0) 1160*e4b17023SJohn Marino fatal_insn ("negative insn length", insn); 1161*e4b17023SJohn Marino #endif 1162*e4b17023SJohn Marino } 1163*e4b17023SJohn Marino 1164*e4b17023SJohn Marino /* Now loop over all the insns finding varying length insns. For each, 1165*e4b17023SJohn Marino get the current insn length. If it has changed, reflect the change. 1166*e4b17023SJohn Marino When nothing changes for a full pass, we are done. */ 1167*e4b17023SJohn Marino 1168*e4b17023SJohn Marino while (something_changed) 1169*e4b17023SJohn Marino { 1170*e4b17023SJohn Marino something_changed = 0; 1171*e4b17023SJohn Marino insn_current_align = MAX_CODE_ALIGN - 1; 1172*e4b17023SJohn Marino for (insn_current_address = 0, insn = first; 1173*e4b17023SJohn Marino insn != 0; 1174*e4b17023SJohn Marino insn = NEXT_INSN (insn)) 1175*e4b17023SJohn Marino { 1176*e4b17023SJohn Marino int new_length; 1177*e4b17023SJohn Marino #ifdef ADJUST_INSN_LENGTH 1178*e4b17023SJohn Marino int tmp_length; 1179*e4b17023SJohn Marino #endif 1180*e4b17023SJohn Marino int length_align; 1181*e4b17023SJohn Marino 1182*e4b17023SJohn Marino uid = INSN_UID (insn); 1183*e4b17023SJohn Marino 1184*e4b17023SJohn Marino if (LABEL_P (insn)) 1185*e4b17023SJohn Marino { 1186*e4b17023SJohn Marino int log = LABEL_TO_ALIGNMENT (insn); 1187*e4b17023SJohn Marino if (log > insn_current_align) 1188*e4b17023SJohn Marino { 1189*e4b17023SJohn Marino int align = 1 << log; 1190*e4b17023SJohn Marino int new_address= (insn_current_address + align - 1) & -align; 1191*e4b17023SJohn Marino insn_lengths[uid] = new_address - insn_current_address; 1192*e4b17023SJohn Marino insn_current_align = log; 1193*e4b17023SJohn Marino insn_current_address = new_address; 1194*e4b17023SJohn Marino } 1195*e4b17023SJohn Marino else 1196*e4b17023SJohn Marino insn_lengths[uid] = 0; 1197*e4b17023SJohn Marino INSN_ADDRESSES (uid) = insn_current_address; 1198*e4b17023SJohn Marino continue; 1199*e4b17023SJohn Marino } 1200*e4b17023SJohn Marino 1201*e4b17023SJohn Marino length_align = INSN_LENGTH_ALIGNMENT (insn); 1202*e4b17023SJohn Marino if (length_align < insn_current_align) 1203*e4b17023SJohn Marino insn_current_align = length_align; 1204*e4b17023SJohn Marino 1205*e4b17023SJohn Marino insn_last_address = INSN_ADDRESSES (uid); 1206*e4b17023SJohn Marino INSN_ADDRESSES (uid) = insn_current_address; 1207*e4b17023SJohn Marino 1208*e4b17023SJohn Marino #ifdef CASE_VECTOR_SHORTEN_MODE 1209*e4b17023SJohn Marino if (optimize && JUMP_P (insn) 1210*e4b17023SJohn Marino && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) 1211*e4b17023SJohn Marino { 1212*e4b17023SJohn Marino rtx body = PATTERN (insn); 1213*e4b17023SJohn Marino int old_length = insn_lengths[uid]; 1214*e4b17023SJohn Marino rtx rel_lab = XEXP (XEXP (body, 0), 0); 1215*e4b17023SJohn Marino rtx min_lab = XEXP (XEXP (body, 2), 0); 1216*e4b17023SJohn Marino rtx max_lab = XEXP (XEXP (body, 3), 0); 1217*e4b17023SJohn Marino int rel_addr = INSN_ADDRESSES (INSN_UID (rel_lab)); 1218*e4b17023SJohn Marino int min_addr = INSN_ADDRESSES (INSN_UID (min_lab)); 1219*e4b17023SJohn Marino int max_addr = INSN_ADDRESSES (INSN_UID (max_lab)); 1220*e4b17023SJohn Marino rtx prev; 1221*e4b17023SJohn Marino int rel_align = 0; 1222*e4b17023SJohn Marino addr_diff_vec_flags flags; 1223*e4b17023SJohn Marino 1224*e4b17023SJohn Marino /* Avoid automatic aggregate initialization. */ 1225*e4b17023SJohn Marino flags = ADDR_DIFF_VEC_FLAGS (body); 1226*e4b17023SJohn Marino 1227*e4b17023SJohn Marino /* Try to find a known alignment for rel_lab. */ 1228*e4b17023SJohn Marino for (prev = rel_lab; 1229*e4b17023SJohn Marino prev 1230*e4b17023SJohn Marino && ! insn_lengths[INSN_UID (prev)] 1231*e4b17023SJohn Marino && ! (varying_length[INSN_UID (prev)] & 1); 1232*e4b17023SJohn Marino prev = PREV_INSN (prev)) 1233*e4b17023SJohn Marino if (varying_length[INSN_UID (prev)] & 2) 1234*e4b17023SJohn Marino { 1235*e4b17023SJohn Marino rel_align = LABEL_TO_ALIGNMENT (prev); 1236*e4b17023SJohn Marino break; 1237*e4b17023SJohn Marino } 1238*e4b17023SJohn Marino 1239*e4b17023SJohn Marino /* See the comment on addr_diff_vec_flags in rtl.h for the 1240*e4b17023SJohn Marino meaning of the flags values. base: REL_LAB vec: INSN */ 1241*e4b17023SJohn Marino /* Anything after INSN has still addresses from the last 1242*e4b17023SJohn Marino pass; adjust these so that they reflect our current 1243*e4b17023SJohn Marino estimate for this pass. */ 1244*e4b17023SJohn Marino if (flags.base_after_vec) 1245*e4b17023SJohn Marino rel_addr += insn_current_address - insn_last_address; 1246*e4b17023SJohn Marino if (flags.min_after_vec) 1247*e4b17023SJohn Marino min_addr += insn_current_address - insn_last_address; 1248*e4b17023SJohn Marino if (flags.max_after_vec) 1249*e4b17023SJohn Marino max_addr += insn_current_address - insn_last_address; 1250*e4b17023SJohn Marino /* We want to know the worst case, i.e. lowest possible value 1251*e4b17023SJohn Marino for the offset of MIN_LAB. If MIN_LAB is after REL_LAB, 1252*e4b17023SJohn Marino its offset is positive, and we have to be wary of code shrink; 1253*e4b17023SJohn Marino otherwise, it is negative, and we have to be vary of code 1254*e4b17023SJohn Marino size increase. */ 1255*e4b17023SJohn Marino if (flags.min_after_base) 1256*e4b17023SJohn Marino { 1257*e4b17023SJohn Marino /* If INSN is between REL_LAB and MIN_LAB, the size 1258*e4b17023SJohn Marino changes we are about to make can change the alignment 1259*e4b17023SJohn Marino within the observed offset, therefore we have to break 1260*e4b17023SJohn Marino it up into two parts that are independent. */ 1261*e4b17023SJohn Marino if (! flags.base_after_vec && flags.min_after_vec) 1262*e4b17023SJohn Marino { 1263*e4b17023SJohn Marino min_addr -= align_fuzz (rel_lab, insn, rel_align, 0); 1264*e4b17023SJohn Marino min_addr -= align_fuzz (insn, min_lab, 0, 0); 1265*e4b17023SJohn Marino } 1266*e4b17023SJohn Marino else 1267*e4b17023SJohn Marino min_addr -= align_fuzz (rel_lab, min_lab, rel_align, 0); 1268*e4b17023SJohn Marino } 1269*e4b17023SJohn Marino else 1270*e4b17023SJohn Marino { 1271*e4b17023SJohn Marino if (flags.base_after_vec && ! flags.min_after_vec) 1272*e4b17023SJohn Marino { 1273*e4b17023SJohn Marino min_addr -= align_fuzz (min_lab, insn, 0, ~0); 1274*e4b17023SJohn Marino min_addr -= align_fuzz (insn, rel_lab, 0, ~0); 1275*e4b17023SJohn Marino } 1276*e4b17023SJohn Marino else 1277*e4b17023SJohn Marino min_addr -= align_fuzz (min_lab, rel_lab, 0, ~0); 1278*e4b17023SJohn Marino } 1279*e4b17023SJohn Marino /* Likewise, determine the highest lowest possible value 1280*e4b17023SJohn Marino for the offset of MAX_LAB. */ 1281*e4b17023SJohn Marino if (flags.max_after_base) 1282*e4b17023SJohn Marino { 1283*e4b17023SJohn Marino if (! flags.base_after_vec && flags.max_after_vec) 1284*e4b17023SJohn Marino { 1285*e4b17023SJohn Marino max_addr += align_fuzz (rel_lab, insn, rel_align, ~0); 1286*e4b17023SJohn Marino max_addr += align_fuzz (insn, max_lab, 0, ~0); 1287*e4b17023SJohn Marino } 1288*e4b17023SJohn Marino else 1289*e4b17023SJohn Marino max_addr += align_fuzz (rel_lab, max_lab, rel_align, ~0); 1290*e4b17023SJohn Marino } 1291*e4b17023SJohn Marino else 1292*e4b17023SJohn Marino { 1293*e4b17023SJohn Marino if (flags.base_after_vec && ! flags.max_after_vec) 1294*e4b17023SJohn Marino { 1295*e4b17023SJohn Marino max_addr += align_fuzz (max_lab, insn, 0, 0); 1296*e4b17023SJohn Marino max_addr += align_fuzz (insn, rel_lab, 0, 0); 1297*e4b17023SJohn Marino } 1298*e4b17023SJohn Marino else 1299*e4b17023SJohn Marino max_addr += align_fuzz (max_lab, rel_lab, 0, 0); 1300*e4b17023SJohn Marino } 1301*e4b17023SJohn Marino PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr, 1302*e4b17023SJohn Marino max_addr - rel_addr, 1303*e4b17023SJohn Marino body)); 1304*e4b17023SJohn Marino if (JUMP_TABLES_IN_TEXT_SECTION 1305*e4b17023SJohn Marino || readonly_data_section == text_section) 1306*e4b17023SJohn Marino { 1307*e4b17023SJohn Marino insn_lengths[uid] 1308*e4b17023SJohn Marino = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body))); 1309*e4b17023SJohn Marino insn_current_address += insn_lengths[uid]; 1310*e4b17023SJohn Marino if (insn_lengths[uid] != old_length) 1311*e4b17023SJohn Marino something_changed = 1; 1312*e4b17023SJohn Marino } 1313*e4b17023SJohn Marino 1314*e4b17023SJohn Marino continue; 1315*e4b17023SJohn Marino } 1316*e4b17023SJohn Marino #endif /* CASE_VECTOR_SHORTEN_MODE */ 1317*e4b17023SJohn Marino 1318*e4b17023SJohn Marino if (! (varying_length[uid])) 1319*e4b17023SJohn Marino { 1320*e4b17023SJohn Marino if (NONJUMP_INSN_P (insn) 1321*e4b17023SJohn Marino && GET_CODE (PATTERN (insn)) == SEQUENCE) 1322*e4b17023SJohn Marino { 1323*e4b17023SJohn Marino int i; 1324*e4b17023SJohn Marino 1325*e4b17023SJohn Marino body = PATTERN (insn); 1326*e4b17023SJohn Marino for (i = 0; i < XVECLEN (body, 0); i++) 1327*e4b17023SJohn Marino { 1328*e4b17023SJohn Marino rtx inner_insn = XVECEXP (body, 0, i); 1329*e4b17023SJohn Marino int inner_uid = INSN_UID (inner_insn); 1330*e4b17023SJohn Marino 1331*e4b17023SJohn Marino INSN_ADDRESSES (inner_uid) = insn_current_address; 1332*e4b17023SJohn Marino 1333*e4b17023SJohn Marino insn_current_address += insn_lengths[inner_uid]; 1334*e4b17023SJohn Marino } 1335*e4b17023SJohn Marino } 1336*e4b17023SJohn Marino else 1337*e4b17023SJohn Marino insn_current_address += insn_lengths[uid]; 1338*e4b17023SJohn Marino 1339*e4b17023SJohn Marino continue; 1340*e4b17023SJohn Marino } 1341*e4b17023SJohn Marino 1342*e4b17023SJohn Marino if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE) 1343*e4b17023SJohn Marino { 1344*e4b17023SJohn Marino int i; 1345*e4b17023SJohn Marino 1346*e4b17023SJohn Marino body = PATTERN (insn); 1347*e4b17023SJohn Marino new_length = 0; 1348*e4b17023SJohn Marino for (i = 0; i < XVECLEN (body, 0); i++) 1349*e4b17023SJohn Marino { 1350*e4b17023SJohn Marino rtx inner_insn = XVECEXP (body, 0, i); 1351*e4b17023SJohn Marino int inner_uid = INSN_UID (inner_insn); 1352*e4b17023SJohn Marino int inner_length; 1353*e4b17023SJohn Marino 1354*e4b17023SJohn Marino INSN_ADDRESSES (inner_uid) = insn_current_address; 1355*e4b17023SJohn Marino 1356*e4b17023SJohn Marino /* insn_current_length returns 0 for insns with a 1357*e4b17023SJohn Marino non-varying length. */ 1358*e4b17023SJohn Marino if (! varying_length[inner_uid]) 1359*e4b17023SJohn Marino inner_length = insn_lengths[inner_uid]; 1360*e4b17023SJohn Marino else 1361*e4b17023SJohn Marino inner_length = insn_current_length (inner_insn); 1362*e4b17023SJohn Marino 1363*e4b17023SJohn Marino if (inner_length != insn_lengths[inner_uid]) 1364*e4b17023SJohn Marino { 1365*e4b17023SJohn Marino insn_lengths[inner_uid] = inner_length; 1366*e4b17023SJohn Marino something_changed = 1; 1367*e4b17023SJohn Marino } 1368*e4b17023SJohn Marino insn_current_address += insn_lengths[inner_uid]; 1369*e4b17023SJohn Marino new_length += inner_length; 1370*e4b17023SJohn Marino } 1371*e4b17023SJohn Marino } 1372*e4b17023SJohn Marino else 1373*e4b17023SJohn Marino { 1374*e4b17023SJohn Marino new_length = insn_current_length (insn); 1375*e4b17023SJohn Marino insn_current_address += new_length; 1376*e4b17023SJohn Marino } 1377*e4b17023SJohn Marino 1378*e4b17023SJohn Marino #ifdef ADJUST_INSN_LENGTH 1379*e4b17023SJohn Marino /* If needed, do any adjustment. */ 1380*e4b17023SJohn Marino tmp_length = new_length; 1381*e4b17023SJohn Marino ADJUST_INSN_LENGTH (insn, new_length); 1382*e4b17023SJohn Marino insn_current_address += (new_length - tmp_length); 1383*e4b17023SJohn Marino #endif 1384*e4b17023SJohn Marino 1385*e4b17023SJohn Marino if (new_length != insn_lengths[uid]) 1386*e4b17023SJohn Marino { 1387*e4b17023SJohn Marino insn_lengths[uid] = new_length; 1388*e4b17023SJohn Marino something_changed = 1; 1389*e4b17023SJohn Marino } 1390*e4b17023SJohn Marino } 1391*e4b17023SJohn Marino /* For a non-optimizing compile, do only a single pass. */ 1392*e4b17023SJohn Marino if (!optimize) 1393*e4b17023SJohn Marino break; 1394*e4b17023SJohn Marino } 1395*e4b17023SJohn Marino 1396*e4b17023SJohn Marino free (varying_length); 1397*e4b17023SJohn Marino 1398*e4b17023SJohn Marino #endif /* HAVE_ATTR_length */ 1399*e4b17023SJohn Marino } 1400*e4b17023SJohn Marino 1401*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 1402*e4b17023SJohn Marino /* Given the body of an INSN known to be generated by an ASM statement, return 1403*e4b17023SJohn Marino the number of machine instructions likely to be generated for this insn. 1404*e4b17023SJohn Marino This is used to compute its length. */ 1405*e4b17023SJohn Marino 1406*e4b17023SJohn Marino static int 1407*e4b17023SJohn Marino asm_insn_count (rtx body) 1408*e4b17023SJohn Marino { 1409*e4b17023SJohn Marino const char *templ; 1410*e4b17023SJohn Marino 1411*e4b17023SJohn Marino if (GET_CODE (body) == ASM_INPUT) 1412*e4b17023SJohn Marino templ = XSTR (body, 0); 1413*e4b17023SJohn Marino else 1414*e4b17023SJohn Marino templ = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL); 1415*e4b17023SJohn Marino 1416*e4b17023SJohn Marino return asm_str_count (templ); 1417*e4b17023SJohn Marino } 1418*e4b17023SJohn Marino #endif 1419*e4b17023SJohn Marino 1420*e4b17023SJohn Marino /* Return the number of machine instructions likely to be generated for the 1421*e4b17023SJohn Marino inline-asm template. */ 1422*e4b17023SJohn Marino int 1423*e4b17023SJohn Marino asm_str_count (const char *templ) 1424*e4b17023SJohn Marino { 1425*e4b17023SJohn Marino int count = 1; 1426*e4b17023SJohn Marino 1427*e4b17023SJohn Marino if (!*templ) 1428*e4b17023SJohn Marino return 0; 1429*e4b17023SJohn Marino 1430*e4b17023SJohn Marino for (; *templ; templ++) 1431*e4b17023SJohn Marino if (IS_ASM_LOGICAL_LINE_SEPARATOR (*templ, templ) 1432*e4b17023SJohn Marino || *templ == '\n') 1433*e4b17023SJohn Marino count++; 1434*e4b17023SJohn Marino 1435*e4b17023SJohn Marino return count; 1436*e4b17023SJohn Marino } 1437*e4b17023SJohn Marino 1438*e4b17023SJohn Marino /* ??? This is probably the wrong place for these. */ 1439*e4b17023SJohn Marino /* Structure recording the mapping from source file and directory 1440*e4b17023SJohn Marino names at compile time to those to be embedded in debug 1441*e4b17023SJohn Marino information. */ 1442*e4b17023SJohn Marino typedef struct debug_prefix_map 1443*e4b17023SJohn Marino { 1444*e4b17023SJohn Marino const char *old_prefix; 1445*e4b17023SJohn Marino const char *new_prefix; 1446*e4b17023SJohn Marino size_t old_len; 1447*e4b17023SJohn Marino size_t new_len; 1448*e4b17023SJohn Marino struct debug_prefix_map *next; 1449*e4b17023SJohn Marino } debug_prefix_map; 1450*e4b17023SJohn Marino 1451*e4b17023SJohn Marino /* Linked list of such structures. */ 1452*e4b17023SJohn Marino debug_prefix_map *debug_prefix_maps; 1453*e4b17023SJohn Marino 1454*e4b17023SJohn Marino 1455*e4b17023SJohn Marino /* Record a debug file prefix mapping. ARG is the argument to 1456*e4b17023SJohn Marino -fdebug-prefix-map and must be of the form OLD=NEW. */ 1457*e4b17023SJohn Marino 1458*e4b17023SJohn Marino void 1459*e4b17023SJohn Marino add_debug_prefix_map (const char *arg) 1460*e4b17023SJohn Marino { 1461*e4b17023SJohn Marino debug_prefix_map *map; 1462*e4b17023SJohn Marino const char *p; 1463*e4b17023SJohn Marino 1464*e4b17023SJohn Marino p = strchr (arg, '='); 1465*e4b17023SJohn Marino if (!p) 1466*e4b17023SJohn Marino { 1467*e4b17023SJohn Marino error ("invalid argument %qs to -fdebug-prefix-map", arg); 1468*e4b17023SJohn Marino return; 1469*e4b17023SJohn Marino } 1470*e4b17023SJohn Marino map = XNEW (debug_prefix_map); 1471*e4b17023SJohn Marino map->old_prefix = xstrndup (arg, p - arg); 1472*e4b17023SJohn Marino map->old_len = p - arg; 1473*e4b17023SJohn Marino p++; 1474*e4b17023SJohn Marino map->new_prefix = xstrdup (p); 1475*e4b17023SJohn Marino map->new_len = strlen (p); 1476*e4b17023SJohn Marino map->next = debug_prefix_maps; 1477*e4b17023SJohn Marino debug_prefix_maps = map; 1478*e4b17023SJohn Marino } 1479*e4b17023SJohn Marino 1480*e4b17023SJohn Marino /* Perform user-specified mapping of debug filename prefixes. Return 1481*e4b17023SJohn Marino the new name corresponding to FILENAME. */ 1482*e4b17023SJohn Marino 1483*e4b17023SJohn Marino const char * 1484*e4b17023SJohn Marino remap_debug_filename (const char *filename) 1485*e4b17023SJohn Marino { 1486*e4b17023SJohn Marino debug_prefix_map *map; 1487*e4b17023SJohn Marino char *s; 1488*e4b17023SJohn Marino const char *name; 1489*e4b17023SJohn Marino size_t name_len; 1490*e4b17023SJohn Marino 1491*e4b17023SJohn Marino for (map = debug_prefix_maps; map; map = map->next) 1492*e4b17023SJohn Marino if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0) 1493*e4b17023SJohn Marino break; 1494*e4b17023SJohn Marino if (!map) 1495*e4b17023SJohn Marino return filename; 1496*e4b17023SJohn Marino name = filename + map->old_len; 1497*e4b17023SJohn Marino name_len = strlen (name) + 1; 1498*e4b17023SJohn Marino s = (char *) alloca (name_len + map->new_len); 1499*e4b17023SJohn Marino memcpy (s, map->new_prefix, map->new_len); 1500*e4b17023SJohn Marino memcpy (s + map->new_len, name, name_len); 1501*e4b17023SJohn Marino return ggc_strdup (s); 1502*e4b17023SJohn Marino } 1503*e4b17023SJohn Marino 1504*e4b17023SJohn Marino /* Return true if DWARF2 debug info can be emitted for DECL. */ 1505*e4b17023SJohn Marino 1506*e4b17023SJohn Marino static bool 1507*e4b17023SJohn Marino dwarf2_debug_info_emitted_p (tree decl) 1508*e4b17023SJohn Marino { 1509*e4b17023SJohn Marino if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG) 1510*e4b17023SJohn Marino return false; 1511*e4b17023SJohn Marino 1512*e4b17023SJohn Marino if (DECL_IGNORED_P (decl)) 1513*e4b17023SJohn Marino return false; 1514*e4b17023SJohn Marino 1515*e4b17023SJohn Marino return true; 1516*e4b17023SJohn Marino } 1517*e4b17023SJohn Marino 1518*e4b17023SJohn Marino /* Output assembler code for the start of a function, 1519*e4b17023SJohn Marino and initialize some of the variables in this file 1520*e4b17023SJohn Marino for the new function. The label for the function and associated 1521*e4b17023SJohn Marino assembler pseudo-ops have already been output in `assemble_start_function'. 1522*e4b17023SJohn Marino 1523*e4b17023SJohn Marino FIRST is the first insn of the rtl for the function being compiled. 1524*e4b17023SJohn Marino FILE is the file to write assembler code to. 1525*e4b17023SJohn Marino OPTIMIZE_P is nonzero if we should eliminate redundant 1526*e4b17023SJohn Marino test and compare insns. */ 1527*e4b17023SJohn Marino 1528*e4b17023SJohn Marino void 1529*e4b17023SJohn Marino final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, 1530*e4b17023SJohn Marino int optimize_p ATTRIBUTE_UNUSED) 1531*e4b17023SJohn Marino { 1532*e4b17023SJohn Marino block_depth = 0; 1533*e4b17023SJohn Marino 1534*e4b17023SJohn Marino this_is_asm_operands = 0; 1535*e4b17023SJohn Marino 1536*e4b17023SJohn Marino last_filename = locator_file (prologue_locator); 1537*e4b17023SJohn Marino last_linenum = locator_line (prologue_locator); 1538*e4b17023SJohn Marino last_discriminator = discriminator = 0; 1539*e4b17023SJohn Marino 1540*e4b17023SJohn Marino high_block_linenum = high_function_linenum = last_linenum; 1541*e4b17023SJohn Marino 1542*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 1543*e4b17023SJohn Marino debug_hooks->begin_prologue (last_linenum, last_filename); 1544*e4b17023SJohn Marino 1545*e4b17023SJohn Marino if (!dwarf2_debug_info_emitted_p (current_function_decl)) 1546*e4b17023SJohn Marino dwarf2out_begin_prologue (0, NULL); 1547*e4b17023SJohn Marino 1548*e4b17023SJohn Marino #ifdef LEAF_REG_REMAP 1549*e4b17023SJohn Marino if (current_function_uses_only_leaf_regs) 1550*e4b17023SJohn Marino leaf_renumber_regs (first); 1551*e4b17023SJohn Marino #endif 1552*e4b17023SJohn Marino 1553*e4b17023SJohn Marino /* The Sun386i and perhaps other machines don't work right 1554*e4b17023SJohn Marino if the profiling code comes after the prologue. */ 1555*e4b17023SJohn Marino if (targetm.profile_before_prologue () && crtl->profile) 1556*e4b17023SJohn Marino profile_function (file); 1557*e4b17023SJohn Marino 1558*e4b17023SJohn Marino /* If debugging, assign block numbers to all of the blocks in this 1559*e4b17023SJohn Marino function. */ 1560*e4b17023SJohn Marino if (write_symbols) 1561*e4b17023SJohn Marino { 1562*e4b17023SJohn Marino reemit_insn_block_notes (); 1563*e4b17023SJohn Marino number_blocks (current_function_decl); 1564*e4b17023SJohn Marino /* We never actually put out begin/end notes for the top-level 1565*e4b17023SJohn Marino block in the function. But, conceptually, that block is 1566*e4b17023SJohn Marino always needed. */ 1567*e4b17023SJohn Marino TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1; 1568*e4b17023SJohn Marino } 1569*e4b17023SJohn Marino 1570*e4b17023SJohn Marino if (warn_frame_larger_than 1571*e4b17023SJohn Marino && get_frame_size () > frame_larger_than_size) 1572*e4b17023SJohn Marino { 1573*e4b17023SJohn Marino /* Issue a warning */ 1574*e4b17023SJohn Marino warning (OPT_Wframe_larger_than_, 1575*e4b17023SJohn Marino "the frame size of %wd bytes is larger than %wd bytes", 1576*e4b17023SJohn Marino get_frame_size (), frame_larger_than_size); 1577*e4b17023SJohn Marino } 1578*e4b17023SJohn Marino 1579*e4b17023SJohn Marino /* First output the function prologue: code to set up the stack frame. */ 1580*e4b17023SJohn Marino targetm.asm_out.function_prologue (file, get_frame_size ()); 1581*e4b17023SJohn Marino 1582*e4b17023SJohn Marino /* If the machine represents the prologue as RTL, the profiling code must 1583*e4b17023SJohn Marino be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ 1584*e4b17023SJohn Marino #ifdef HAVE_prologue 1585*e4b17023SJohn Marino if (! HAVE_prologue) 1586*e4b17023SJohn Marino #endif 1587*e4b17023SJohn Marino profile_after_prologue (file); 1588*e4b17023SJohn Marino } 1589*e4b17023SJohn Marino 1590*e4b17023SJohn Marino static void 1591*e4b17023SJohn Marino profile_after_prologue (FILE *file ATTRIBUTE_UNUSED) 1592*e4b17023SJohn Marino { 1593*e4b17023SJohn Marino if (!targetm.profile_before_prologue () && crtl->profile) 1594*e4b17023SJohn Marino profile_function (file); 1595*e4b17023SJohn Marino } 1596*e4b17023SJohn Marino 1597*e4b17023SJohn Marino static void 1598*e4b17023SJohn Marino profile_function (FILE *file ATTRIBUTE_UNUSED) 1599*e4b17023SJohn Marino { 1600*e4b17023SJohn Marino #ifndef NO_PROFILE_COUNTERS 1601*e4b17023SJohn Marino # define NO_PROFILE_COUNTERS 0 1602*e4b17023SJohn Marino #endif 1603*e4b17023SJohn Marino #ifdef ASM_OUTPUT_REG_PUSH 1604*e4b17023SJohn Marino rtx sval = NULL, chain = NULL; 1605*e4b17023SJohn Marino 1606*e4b17023SJohn Marino if (cfun->returns_struct) 1607*e4b17023SJohn Marino sval = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1608*e4b17023SJohn Marino true); 1609*e4b17023SJohn Marino if (cfun->static_chain_decl) 1610*e4b17023SJohn Marino chain = targetm.calls.static_chain (current_function_decl, true); 1611*e4b17023SJohn Marino #endif /* ASM_OUTPUT_REG_PUSH */ 1612*e4b17023SJohn Marino 1613*e4b17023SJohn Marino if (! NO_PROFILE_COUNTERS) 1614*e4b17023SJohn Marino { 1615*e4b17023SJohn Marino int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE); 1616*e4b17023SJohn Marino switch_to_section (data_section); 1617*e4b17023SJohn Marino ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); 1618*e4b17023SJohn Marino targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no); 1619*e4b17023SJohn Marino assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1); 1620*e4b17023SJohn Marino } 1621*e4b17023SJohn Marino 1622*e4b17023SJohn Marino switch_to_section (current_function_section ()); 1623*e4b17023SJohn Marino 1624*e4b17023SJohn Marino #ifdef ASM_OUTPUT_REG_PUSH 1625*e4b17023SJohn Marino if (sval && REG_P (sval)) 1626*e4b17023SJohn Marino ASM_OUTPUT_REG_PUSH (file, REGNO (sval)); 1627*e4b17023SJohn Marino if (chain && REG_P (chain)) 1628*e4b17023SJohn Marino ASM_OUTPUT_REG_PUSH (file, REGNO (chain)); 1629*e4b17023SJohn Marino #endif 1630*e4b17023SJohn Marino 1631*e4b17023SJohn Marino FUNCTION_PROFILER (file, current_function_funcdef_no); 1632*e4b17023SJohn Marino 1633*e4b17023SJohn Marino #ifdef ASM_OUTPUT_REG_PUSH 1634*e4b17023SJohn Marino if (chain && REG_P (chain)) 1635*e4b17023SJohn Marino ASM_OUTPUT_REG_POP (file, REGNO (chain)); 1636*e4b17023SJohn Marino if (sval && REG_P (sval)) 1637*e4b17023SJohn Marino ASM_OUTPUT_REG_POP (file, REGNO (sval)); 1638*e4b17023SJohn Marino #endif 1639*e4b17023SJohn Marino } 1640*e4b17023SJohn Marino 1641*e4b17023SJohn Marino /* Output assembler code for the end of a function. 1642*e4b17023SJohn Marino For clarity, args are same as those of `final_start_function' 1643*e4b17023SJohn Marino even though not all of them are needed. */ 1644*e4b17023SJohn Marino 1645*e4b17023SJohn Marino void 1646*e4b17023SJohn Marino final_end_function (void) 1647*e4b17023SJohn Marino { 1648*e4b17023SJohn Marino app_disable (); 1649*e4b17023SJohn Marino 1650*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 1651*e4b17023SJohn Marino debug_hooks->end_function (high_function_linenum); 1652*e4b17023SJohn Marino 1653*e4b17023SJohn Marino /* Finally, output the function epilogue: 1654*e4b17023SJohn Marino code to restore the stack frame and return to the caller. */ 1655*e4b17023SJohn Marino targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ()); 1656*e4b17023SJohn Marino 1657*e4b17023SJohn Marino /* And debug output. */ 1658*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 1659*e4b17023SJohn Marino debug_hooks->end_epilogue (last_linenum, last_filename); 1660*e4b17023SJohn Marino 1661*e4b17023SJohn Marino if (!dwarf2_debug_info_emitted_p (current_function_decl) 1662*e4b17023SJohn Marino && dwarf2out_do_frame ()) 1663*e4b17023SJohn Marino dwarf2out_end_epilogue (last_linenum, last_filename); 1664*e4b17023SJohn Marino } 1665*e4b17023SJohn Marino 1666*e4b17023SJohn Marino 1667*e4b17023SJohn Marino /* Dumper helper for basic block information. FILE is the assembly 1668*e4b17023SJohn Marino output file, and INSN is the instruction being emitted. */ 1669*e4b17023SJohn Marino 1670*e4b17023SJohn Marino static void 1671*e4b17023SJohn Marino dump_basic_block_info (FILE *file, rtx insn, basic_block *start_to_bb, 1672*e4b17023SJohn Marino basic_block *end_to_bb, int bb_map_size, int *bb_seqn) 1673*e4b17023SJohn Marino { 1674*e4b17023SJohn Marino basic_block bb; 1675*e4b17023SJohn Marino 1676*e4b17023SJohn Marino if (!flag_debug_asm) 1677*e4b17023SJohn Marino return; 1678*e4b17023SJohn Marino 1679*e4b17023SJohn Marino if (INSN_UID (insn) < bb_map_size 1680*e4b17023SJohn Marino && (bb = start_to_bb[INSN_UID (insn)]) != NULL) 1681*e4b17023SJohn Marino { 1682*e4b17023SJohn Marino edge e; 1683*e4b17023SJohn Marino edge_iterator ei; 1684*e4b17023SJohn Marino 1685*e4b17023SJohn Marino fprintf (file, "%s BLOCK %d", ASM_COMMENT_START, bb->index); 1686*e4b17023SJohn Marino if (bb->frequency) 1687*e4b17023SJohn Marino fprintf (file, " freq:%d", bb->frequency); 1688*e4b17023SJohn Marino if (bb->count) 1689*e4b17023SJohn Marino fprintf (file, " count:" HOST_WIDEST_INT_PRINT_DEC, 1690*e4b17023SJohn Marino bb->count); 1691*e4b17023SJohn Marino fprintf (file, " seq:%d", (*bb_seqn)++); 1692*e4b17023SJohn Marino fprintf (file, "\n%s PRED:", ASM_COMMENT_START); 1693*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds) 1694*e4b17023SJohn Marino { 1695*e4b17023SJohn Marino dump_edge_info (file, e, 0); 1696*e4b17023SJohn Marino } 1697*e4b17023SJohn Marino fprintf (file, "\n"); 1698*e4b17023SJohn Marino } 1699*e4b17023SJohn Marino if (INSN_UID (insn) < bb_map_size 1700*e4b17023SJohn Marino && (bb = end_to_bb[INSN_UID (insn)]) != NULL) 1701*e4b17023SJohn Marino { 1702*e4b17023SJohn Marino edge e; 1703*e4b17023SJohn Marino edge_iterator ei; 1704*e4b17023SJohn Marino 1705*e4b17023SJohn Marino fprintf (asm_out_file, "%s SUCC:", ASM_COMMENT_START); 1706*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs) 1707*e4b17023SJohn Marino { 1708*e4b17023SJohn Marino dump_edge_info (asm_out_file, e, 1); 1709*e4b17023SJohn Marino } 1710*e4b17023SJohn Marino fprintf (file, "\n"); 1711*e4b17023SJohn Marino } 1712*e4b17023SJohn Marino } 1713*e4b17023SJohn Marino 1714*e4b17023SJohn Marino /* Output assembler code for some insns: all or part of a function. 1715*e4b17023SJohn Marino For description of args, see `final_start_function', above. */ 1716*e4b17023SJohn Marino 1717*e4b17023SJohn Marino void 1718*e4b17023SJohn Marino final (rtx first, FILE *file, int optimize_p) 1719*e4b17023SJohn Marino { 1720*e4b17023SJohn Marino rtx insn, next; 1721*e4b17023SJohn Marino int max_uid = 0; 1722*e4b17023SJohn Marino int seen = 0; 1723*e4b17023SJohn Marino 1724*e4b17023SJohn Marino /* Used for -dA dump. */ 1725*e4b17023SJohn Marino basic_block *start_to_bb = NULL; 1726*e4b17023SJohn Marino basic_block *end_to_bb = NULL; 1727*e4b17023SJohn Marino int bb_map_size = 0; 1728*e4b17023SJohn Marino int bb_seqn = 0; 1729*e4b17023SJohn Marino 1730*e4b17023SJohn Marino last_ignored_compare = 0; 1731*e4b17023SJohn Marino 1732*e4b17023SJohn Marino for (insn = first; insn; insn = NEXT_INSN (insn)) 1733*e4b17023SJohn Marino { 1734*e4b17023SJohn Marino if (INSN_UID (insn) > max_uid) /* Find largest UID. */ 1735*e4b17023SJohn Marino max_uid = INSN_UID (insn); 1736*e4b17023SJohn Marino #ifdef HAVE_cc0 1737*e4b17023SJohn Marino /* If CC tracking across branches is enabled, record the insn which 1738*e4b17023SJohn Marino jumps to each branch only reached from one place. */ 1739*e4b17023SJohn Marino if (optimize_p && JUMP_P (insn)) 1740*e4b17023SJohn Marino { 1741*e4b17023SJohn Marino rtx lab = JUMP_LABEL (insn); 1742*e4b17023SJohn Marino if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1) 1743*e4b17023SJohn Marino { 1744*e4b17023SJohn Marino LABEL_REFS (lab) = insn; 1745*e4b17023SJohn Marino } 1746*e4b17023SJohn Marino } 1747*e4b17023SJohn Marino #endif 1748*e4b17023SJohn Marino } 1749*e4b17023SJohn Marino 1750*e4b17023SJohn Marino init_recog (); 1751*e4b17023SJohn Marino 1752*e4b17023SJohn Marino CC_STATUS_INIT; 1753*e4b17023SJohn Marino 1754*e4b17023SJohn Marino if (flag_debug_asm) 1755*e4b17023SJohn Marino { 1756*e4b17023SJohn Marino basic_block bb; 1757*e4b17023SJohn Marino 1758*e4b17023SJohn Marino bb_map_size = get_max_uid () + 1; 1759*e4b17023SJohn Marino start_to_bb = XCNEWVEC (basic_block, bb_map_size); 1760*e4b17023SJohn Marino end_to_bb = XCNEWVEC (basic_block, bb_map_size); 1761*e4b17023SJohn Marino 1762*e4b17023SJohn Marino FOR_EACH_BB_REVERSE (bb) 1763*e4b17023SJohn Marino { 1764*e4b17023SJohn Marino start_to_bb[INSN_UID (BB_HEAD (bb))] = bb; 1765*e4b17023SJohn Marino end_to_bb[INSN_UID (BB_END (bb))] = bb; 1766*e4b17023SJohn Marino } 1767*e4b17023SJohn Marino } 1768*e4b17023SJohn Marino 1769*e4b17023SJohn Marino /* Output the insns. */ 1770*e4b17023SJohn Marino for (insn = first; insn;) 1771*e4b17023SJohn Marino { 1772*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 1773*e4b17023SJohn Marino if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ()) 1774*e4b17023SJohn Marino { 1775*e4b17023SJohn Marino /* This can be triggered by bugs elsewhere in the compiler if 1776*e4b17023SJohn Marino new insns are created after init_insn_lengths is called. */ 1777*e4b17023SJohn Marino gcc_assert (NOTE_P (insn)); 1778*e4b17023SJohn Marino insn_current_address = -1; 1779*e4b17023SJohn Marino } 1780*e4b17023SJohn Marino else 1781*e4b17023SJohn Marino insn_current_address = INSN_ADDRESSES (INSN_UID (insn)); 1782*e4b17023SJohn Marino #endif /* HAVE_ATTR_length */ 1783*e4b17023SJohn Marino 1784*e4b17023SJohn Marino dump_basic_block_info (file, insn, start_to_bb, end_to_bb, 1785*e4b17023SJohn Marino bb_map_size, &bb_seqn); 1786*e4b17023SJohn Marino insn = final_scan_insn (insn, file, optimize_p, 0, &seen); 1787*e4b17023SJohn Marino } 1788*e4b17023SJohn Marino 1789*e4b17023SJohn Marino if (flag_debug_asm) 1790*e4b17023SJohn Marino { 1791*e4b17023SJohn Marino free (start_to_bb); 1792*e4b17023SJohn Marino free (end_to_bb); 1793*e4b17023SJohn Marino } 1794*e4b17023SJohn Marino 1795*e4b17023SJohn Marino /* Remove CFI notes, to avoid compare-debug failures. */ 1796*e4b17023SJohn Marino for (insn = first; insn; insn = next) 1797*e4b17023SJohn Marino { 1798*e4b17023SJohn Marino next = NEXT_INSN (insn); 1799*e4b17023SJohn Marino if (NOTE_P (insn) 1800*e4b17023SJohn Marino && (NOTE_KIND (insn) == NOTE_INSN_CFI 1801*e4b17023SJohn Marino || NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL)) 1802*e4b17023SJohn Marino delete_insn (insn); 1803*e4b17023SJohn Marino } 1804*e4b17023SJohn Marino } 1805*e4b17023SJohn Marino 1806*e4b17023SJohn Marino const char * 1807*e4b17023SJohn Marino get_insn_template (int code, rtx insn) 1808*e4b17023SJohn Marino { 1809*e4b17023SJohn Marino switch (insn_data[code].output_format) 1810*e4b17023SJohn Marino { 1811*e4b17023SJohn Marino case INSN_OUTPUT_FORMAT_SINGLE: 1812*e4b17023SJohn Marino return insn_data[code].output.single; 1813*e4b17023SJohn Marino case INSN_OUTPUT_FORMAT_MULTI: 1814*e4b17023SJohn Marino return insn_data[code].output.multi[which_alternative]; 1815*e4b17023SJohn Marino case INSN_OUTPUT_FORMAT_FUNCTION: 1816*e4b17023SJohn Marino gcc_assert (insn); 1817*e4b17023SJohn Marino return (*insn_data[code].output.function) (recog_data.operand, insn); 1818*e4b17023SJohn Marino 1819*e4b17023SJohn Marino default: 1820*e4b17023SJohn Marino gcc_unreachable (); 1821*e4b17023SJohn Marino } 1822*e4b17023SJohn Marino } 1823*e4b17023SJohn Marino 1824*e4b17023SJohn Marino /* Emit the appropriate declaration for an alternate-entry-point 1825*e4b17023SJohn Marino symbol represented by INSN, to FILE. INSN is a CODE_LABEL with 1826*e4b17023SJohn Marino LABEL_KIND != LABEL_NORMAL. 1827*e4b17023SJohn Marino 1828*e4b17023SJohn Marino The case fall-through in this function is intentional. */ 1829*e4b17023SJohn Marino static void 1830*e4b17023SJohn Marino output_alternate_entry_point (FILE *file, rtx insn) 1831*e4b17023SJohn Marino { 1832*e4b17023SJohn Marino const char *name = LABEL_NAME (insn); 1833*e4b17023SJohn Marino 1834*e4b17023SJohn Marino switch (LABEL_KIND (insn)) 1835*e4b17023SJohn Marino { 1836*e4b17023SJohn Marino case LABEL_WEAK_ENTRY: 1837*e4b17023SJohn Marino #ifdef ASM_WEAKEN_LABEL 1838*e4b17023SJohn Marino ASM_WEAKEN_LABEL (file, name); 1839*e4b17023SJohn Marino #endif 1840*e4b17023SJohn Marino case LABEL_GLOBAL_ENTRY: 1841*e4b17023SJohn Marino targetm.asm_out.globalize_label (file, name); 1842*e4b17023SJohn Marino case LABEL_STATIC_ENTRY: 1843*e4b17023SJohn Marino #ifdef ASM_OUTPUT_TYPE_DIRECTIVE 1844*e4b17023SJohn Marino ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); 1845*e4b17023SJohn Marino #endif 1846*e4b17023SJohn Marino ASM_OUTPUT_LABEL (file, name); 1847*e4b17023SJohn Marino break; 1848*e4b17023SJohn Marino 1849*e4b17023SJohn Marino case LABEL_NORMAL: 1850*e4b17023SJohn Marino default: 1851*e4b17023SJohn Marino gcc_unreachable (); 1852*e4b17023SJohn Marino } 1853*e4b17023SJohn Marino } 1854*e4b17023SJohn Marino 1855*e4b17023SJohn Marino /* Given a CALL_INSN, find and return the nested CALL. */ 1856*e4b17023SJohn Marino static rtx 1857*e4b17023SJohn Marino call_from_call_insn (rtx insn) 1858*e4b17023SJohn Marino { 1859*e4b17023SJohn Marino rtx x; 1860*e4b17023SJohn Marino gcc_assert (CALL_P (insn)); 1861*e4b17023SJohn Marino x = PATTERN (insn); 1862*e4b17023SJohn Marino 1863*e4b17023SJohn Marino while (GET_CODE (x) != CALL) 1864*e4b17023SJohn Marino { 1865*e4b17023SJohn Marino switch (GET_CODE (x)) 1866*e4b17023SJohn Marino { 1867*e4b17023SJohn Marino default: 1868*e4b17023SJohn Marino gcc_unreachable (); 1869*e4b17023SJohn Marino case COND_EXEC: 1870*e4b17023SJohn Marino x = COND_EXEC_CODE (x); 1871*e4b17023SJohn Marino break; 1872*e4b17023SJohn Marino case PARALLEL: 1873*e4b17023SJohn Marino x = XVECEXP (x, 0, 0); 1874*e4b17023SJohn Marino break; 1875*e4b17023SJohn Marino case SET: 1876*e4b17023SJohn Marino x = XEXP (x, 1); 1877*e4b17023SJohn Marino break; 1878*e4b17023SJohn Marino } 1879*e4b17023SJohn Marino } 1880*e4b17023SJohn Marino return x; 1881*e4b17023SJohn Marino } 1882*e4b17023SJohn Marino 1883*e4b17023SJohn Marino /* The final scan for one insn, INSN. 1884*e4b17023SJohn Marino Args are same as in `final', except that INSN 1885*e4b17023SJohn Marino is the insn being scanned. 1886*e4b17023SJohn Marino Value returned is the next insn to be scanned. 1887*e4b17023SJohn Marino 1888*e4b17023SJohn Marino NOPEEPHOLES is the flag to disallow peephole processing (currently 1889*e4b17023SJohn Marino used for within delayed branch sequence output). 1890*e4b17023SJohn Marino 1891*e4b17023SJohn Marino SEEN is used to track the end of the prologue, for emitting 1892*e4b17023SJohn Marino debug information. We force the emission of a line note after 1893*e4b17023SJohn Marino both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG, or 1894*e4b17023SJohn Marino at the beginning of the second basic block, whichever comes 1895*e4b17023SJohn Marino first. */ 1896*e4b17023SJohn Marino 1897*e4b17023SJohn Marino rtx 1898*e4b17023SJohn Marino final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, 1899*e4b17023SJohn Marino int nopeepholes ATTRIBUTE_UNUSED, int *seen) 1900*e4b17023SJohn Marino { 1901*e4b17023SJohn Marino #ifdef HAVE_cc0 1902*e4b17023SJohn Marino rtx set; 1903*e4b17023SJohn Marino #endif 1904*e4b17023SJohn Marino rtx next; 1905*e4b17023SJohn Marino 1906*e4b17023SJohn Marino insn_counter++; 1907*e4b17023SJohn Marino 1908*e4b17023SJohn Marino /* Ignore deleted insns. These can occur when we split insns (due to a 1909*e4b17023SJohn Marino template of "#") while not optimizing. */ 1910*e4b17023SJohn Marino if (INSN_DELETED_P (insn)) 1911*e4b17023SJohn Marino return NEXT_INSN (insn); 1912*e4b17023SJohn Marino 1913*e4b17023SJohn Marino switch (GET_CODE (insn)) 1914*e4b17023SJohn Marino { 1915*e4b17023SJohn Marino case NOTE: 1916*e4b17023SJohn Marino switch (NOTE_KIND (insn)) 1917*e4b17023SJohn Marino { 1918*e4b17023SJohn Marino case NOTE_INSN_DELETED: 1919*e4b17023SJohn Marino break; 1920*e4b17023SJohn Marino 1921*e4b17023SJohn Marino case NOTE_INSN_SWITCH_TEXT_SECTIONS: 1922*e4b17023SJohn Marino in_cold_section_p = !in_cold_section_p; 1923*e4b17023SJohn Marino 1924*e4b17023SJohn Marino if (dwarf2out_do_frame ()) 1925*e4b17023SJohn Marino dwarf2out_switch_text_section (); 1926*e4b17023SJohn Marino else if (!DECL_IGNORED_P (current_function_decl)) 1927*e4b17023SJohn Marino debug_hooks->switch_text_section (); 1928*e4b17023SJohn Marino 1929*e4b17023SJohn Marino switch_to_section (current_function_section ()); 1930*e4b17023SJohn Marino targetm.asm_out.function_switched_text_sections (asm_out_file, 1931*e4b17023SJohn Marino current_function_decl, 1932*e4b17023SJohn Marino in_cold_section_p); 1933*e4b17023SJohn Marino break; 1934*e4b17023SJohn Marino 1935*e4b17023SJohn Marino case NOTE_INSN_BASIC_BLOCK: 1936*e4b17023SJohn Marino if (targetm.asm_out.unwind_emit) 1937*e4b17023SJohn Marino targetm.asm_out.unwind_emit (asm_out_file, insn); 1938*e4b17023SJohn Marino 1939*e4b17023SJohn Marino if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB) 1940*e4b17023SJohn Marino { 1941*e4b17023SJohn Marino *seen |= SEEN_EMITTED; 1942*e4b17023SJohn Marino force_source_line = true; 1943*e4b17023SJohn Marino } 1944*e4b17023SJohn Marino else 1945*e4b17023SJohn Marino *seen |= SEEN_BB; 1946*e4b17023SJohn Marino 1947*e4b17023SJohn Marino discriminator = NOTE_BASIC_BLOCK (insn)->discriminator; 1948*e4b17023SJohn Marino 1949*e4b17023SJohn Marino break; 1950*e4b17023SJohn Marino 1951*e4b17023SJohn Marino case NOTE_INSN_EH_REGION_BEG: 1952*e4b17023SJohn Marino ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB", 1953*e4b17023SJohn Marino NOTE_EH_HANDLER (insn)); 1954*e4b17023SJohn Marino break; 1955*e4b17023SJohn Marino 1956*e4b17023SJohn Marino case NOTE_INSN_EH_REGION_END: 1957*e4b17023SJohn Marino ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE", 1958*e4b17023SJohn Marino NOTE_EH_HANDLER (insn)); 1959*e4b17023SJohn Marino break; 1960*e4b17023SJohn Marino 1961*e4b17023SJohn Marino case NOTE_INSN_PROLOGUE_END: 1962*e4b17023SJohn Marino targetm.asm_out.function_end_prologue (file); 1963*e4b17023SJohn Marino profile_after_prologue (file); 1964*e4b17023SJohn Marino 1965*e4b17023SJohn Marino if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE) 1966*e4b17023SJohn Marino { 1967*e4b17023SJohn Marino *seen |= SEEN_EMITTED; 1968*e4b17023SJohn Marino force_source_line = true; 1969*e4b17023SJohn Marino } 1970*e4b17023SJohn Marino else 1971*e4b17023SJohn Marino *seen |= SEEN_NOTE; 1972*e4b17023SJohn Marino 1973*e4b17023SJohn Marino break; 1974*e4b17023SJohn Marino 1975*e4b17023SJohn Marino case NOTE_INSN_EPILOGUE_BEG: 1976*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 1977*e4b17023SJohn Marino (*debug_hooks->begin_epilogue) (last_linenum, last_filename); 1978*e4b17023SJohn Marino targetm.asm_out.function_begin_epilogue (file); 1979*e4b17023SJohn Marino break; 1980*e4b17023SJohn Marino 1981*e4b17023SJohn Marino case NOTE_INSN_CFI: 1982*e4b17023SJohn Marino dwarf2out_emit_cfi (NOTE_CFI (insn)); 1983*e4b17023SJohn Marino break; 1984*e4b17023SJohn Marino 1985*e4b17023SJohn Marino case NOTE_INSN_CFI_LABEL: 1986*e4b17023SJohn Marino ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", 1987*e4b17023SJohn Marino NOTE_LABEL_NUMBER (insn)); 1988*e4b17023SJohn Marino break; 1989*e4b17023SJohn Marino 1990*e4b17023SJohn Marino case NOTE_INSN_FUNCTION_BEG: 1991*e4b17023SJohn Marino app_disable (); 1992*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 1993*e4b17023SJohn Marino debug_hooks->end_prologue (last_linenum, last_filename); 1994*e4b17023SJohn Marino 1995*e4b17023SJohn Marino if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE) 1996*e4b17023SJohn Marino { 1997*e4b17023SJohn Marino *seen |= SEEN_EMITTED; 1998*e4b17023SJohn Marino force_source_line = true; 1999*e4b17023SJohn Marino } 2000*e4b17023SJohn Marino else 2001*e4b17023SJohn Marino *seen |= SEEN_NOTE; 2002*e4b17023SJohn Marino 2003*e4b17023SJohn Marino break; 2004*e4b17023SJohn Marino 2005*e4b17023SJohn Marino case NOTE_INSN_BLOCK_BEG: 2006*e4b17023SJohn Marino if (debug_info_level == DINFO_LEVEL_NORMAL 2007*e4b17023SJohn Marino || debug_info_level == DINFO_LEVEL_VERBOSE 2008*e4b17023SJohn Marino || write_symbols == DWARF2_DEBUG 2009*e4b17023SJohn Marino || write_symbols == VMS_AND_DWARF2_DEBUG 2010*e4b17023SJohn Marino || write_symbols == VMS_DEBUG) 2011*e4b17023SJohn Marino { 2012*e4b17023SJohn Marino int n = BLOCK_NUMBER (NOTE_BLOCK (insn)); 2013*e4b17023SJohn Marino 2014*e4b17023SJohn Marino app_disable (); 2015*e4b17023SJohn Marino ++block_depth; 2016*e4b17023SJohn Marino high_block_linenum = last_linenum; 2017*e4b17023SJohn Marino 2018*e4b17023SJohn Marino /* Output debugging info about the symbol-block beginning. */ 2019*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 2020*e4b17023SJohn Marino debug_hooks->begin_block (last_linenum, n); 2021*e4b17023SJohn Marino 2022*e4b17023SJohn Marino /* Mark this block as output. */ 2023*e4b17023SJohn Marino TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1; 2024*e4b17023SJohn Marino } 2025*e4b17023SJohn Marino if (write_symbols == DBX_DEBUG 2026*e4b17023SJohn Marino || write_symbols == SDB_DEBUG) 2027*e4b17023SJohn Marino { 2028*e4b17023SJohn Marino location_t *locus_ptr 2029*e4b17023SJohn Marino = block_nonartificial_location (NOTE_BLOCK (insn)); 2030*e4b17023SJohn Marino 2031*e4b17023SJohn Marino if (locus_ptr != NULL) 2032*e4b17023SJohn Marino { 2033*e4b17023SJohn Marino override_filename = LOCATION_FILE (*locus_ptr); 2034*e4b17023SJohn Marino override_linenum = LOCATION_LINE (*locus_ptr); 2035*e4b17023SJohn Marino } 2036*e4b17023SJohn Marino } 2037*e4b17023SJohn Marino break; 2038*e4b17023SJohn Marino 2039*e4b17023SJohn Marino case NOTE_INSN_BLOCK_END: 2040*e4b17023SJohn Marino if (debug_info_level == DINFO_LEVEL_NORMAL 2041*e4b17023SJohn Marino || debug_info_level == DINFO_LEVEL_VERBOSE 2042*e4b17023SJohn Marino || write_symbols == DWARF2_DEBUG 2043*e4b17023SJohn Marino || write_symbols == VMS_AND_DWARF2_DEBUG 2044*e4b17023SJohn Marino || write_symbols == VMS_DEBUG) 2045*e4b17023SJohn Marino { 2046*e4b17023SJohn Marino int n = BLOCK_NUMBER (NOTE_BLOCK (insn)); 2047*e4b17023SJohn Marino 2048*e4b17023SJohn Marino app_disable (); 2049*e4b17023SJohn Marino 2050*e4b17023SJohn Marino /* End of a symbol-block. */ 2051*e4b17023SJohn Marino --block_depth; 2052*e4b17023SJohn Marino gcc_assert (block_depth >= 0); 2053*e4b17023SJohn Marino 2054*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 2055*e4b17023SJohn Marino debug_hooks->end_block (high_block_linenum, n); 2056*e4b17023SJohn Marino } 2057*e4b17023SJohn Marino if (write_symbols == DBX_DEBUG 2058*e4b17023SJohn Marino || write_symbols == SDB_DEBUG) 2059*e4b17023SJohn Marino { 2060*e4b17023SJohn Marino tree outer_block = BLOCK_SUPERCONTEXT (NOTE_BLOCK (insn)); 2061*e4b17023SJohn Marino location_t *locus_ptr 2062*e4b17023SJohn Marino = block_nonartificial_location (outer_block); 2063*e4b17023SJohn Marino 2064*e4b17023SJohn Marino if (locus_ptr != NULL) 2065*e4b17023SJohn Marino { 2066*e4b17023SJohn Marino override_filename = LOCATION_FILE (*locus_ptr); 2067*e4b17023SJohn Marino override_linenum = LOCATION_LINE (*locus_ptr); 2068*e4b17023SJohn Marino } 2069*e4b17023SJohn Marino else 2070*e4b17023SJohn Marino { 2071*e4b17023SJohn Marino override_filename = NULL; 2072*e4b17023SJohn Marino override_linenum = 0; 2073*e4b17023SJohn Marino } 2074*e4b17023SJohn Marino } 2075*e4b17023SJohn Marino break; 2076*e4b17023SJohn Marino 2077*e4b17023SJohn Marino case NOTE_INSN_DELETED_LABEL: 2078*e4b17023SJohn Marino /* Emit the label. We may have deleted the CODE_LABEL because 2079*e4b17023SJohn Marino the label could be proved to be unreachable, though still 2080*e4b17023SJohn Marino referenced (in the form of having its address taken. */ 2081*e4b17023SJohn Marino ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); 2082*e4b17023SJohn Marino break; 2083*e4b17023SJohn Marino 2084*e4b17023SJohn Marino case NOTE_INSN_DELETED_DEBUG_LABEL: 2085*e4b17023SJohn Marino /* Similarly, but need to use different namespace for it. */ 2086*e4b17023SJohn Marino if (CODE_LABEL_NUMBER (insn) != -1) 2087*e4b17023SJohn Marino ASM_OUTPUT_DEBUG_LABEL (file, "LDL", CODE_LABEL_NUMBER (insn)); 2088*e4b17023SJohn Marino break; 2089*e4b17023SJohn Marino 2090*e4b17023SJohn Marino case NOTE_INSN_VAR_LOCATION: 2091*e4b17023SJohn Marino case NOTE_INSN_CALL_ARG_LOCATION: 2092*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 2093*e4b17023SJohn Marino debug_hooks->var_location (insn); 2094*e4b17023SJohn Marino break; 2095*e4b17023SJohn Marino 2096*e4b17023SJohn Marino default: 2097*e4b17023SJohn Marino gcc_unreachable (); 2098*e4b17023SJohn Marino break; 2099*e4b17023SJohn Marino } 2100*e4b17023SJohn Marino break; 2101*e4b17023SJohn Marino 2102*e4b17023SJohn Marino case BARRIER: 2103*e4b17023SJohn Marino break; 2104*e4b17023SJohn Marino 2105*e4b17023SJohn Marino case CODE_LABEL: 2106*e4b17023SJohn Marino /* The target port might emit labels in the output function for 2107*e4b17023SJohn Marino some insn, e.g. sh.c output_branchy_insn. */ 2108*e4b17023SJohn Marino if (CODE_LABEL_NUMBER (insn) <= max_labelno) 2109*e4b17023SJohn Marino { 2110*e4b17023SJohn Marino int align = LABEL_TO_ALIGNMENT (insn); 2111*e4b17023SJohn Marino #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN 2112*e4b17023SJohn Marino int max_skip = LABEL_TO_MAX_SKIP (insn); 2113*e4b17023SJohn Marino #endif 2114*e4b17023SJohn Marino 2115*e4b17023SJohn Marino if (align && NEXT_INSN (insn)) 2116*e4b17023SJohn Marino { 2117*e4b17023SJohn Marino #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN 2118*e4b17023SJohn Marino ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip); 2119*e4b17023SJohn Marino #else 2120*e4b17023SJohn Marino #ifdef ASM_OUTPUT_ALIGN_WITH_NOP 2121*e4b17023SJohn Marino ASM_OUTPUT_ALIGN_WITH_NOP (file, align); 2122*e4b17023SJohn Marino #else 2123*e4b17023SJohn Marino ASM_OUTPUT_ALIGN (file, align); 2124*e4b17023SJohn Marino #endif 2125*e4b17023SJohn Marino #endif 2126*e4b17023SJohn Marino } 2127*e4b17023SJohn Marino } 2128*e4b17023SJohn Marino CC_STATUS_INIT; 2129*e4b17023SJohn Marino 2130*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn)) 2131*e4b17023SJohn Marino debug_hooks->label (insn); 2132*e4b17023SJohn Marino 2133*e4b17023SJohn Marino app_disable (); 2134*e4b17023SJohn Marino 2135*e4b17023SJohn Marino next = next_nonnote_insn (insn); 2136*e4b17023SJohn Marino /* If this label is followed by a jump-table, make sure we put 2137*e4b17023SJohn Marino the label in the read-only section. Also possibly write the 2138*e4b17023SJohn Marino label and jump table together. */ 2139*e4b17023SJohn Marino if (next != 0 && JUMP_TABLE_DATA_P (next)) 2140*e4b17023SJohn Marino { 2141*e4b17023SJohn Marino #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC) 2142*e4b17023SJohn Marino /* In this case, the case vector is being moved by the 2143*e4b17023SJohn Marino target, so don't output the label at all. Leave that 2144*e4b17023SJohn Marino to the back end macros. */ 2145*e4b17023SJohn Marino #else 2146*e4b17023SJohn Marino if (! JUMP_TABLES_IN_TEXT_SECTION) 2147*e4b17023SJohn Marino { 2148*e4b17023SJohn Marino int log_align; 2149*e4b17023SJohn Marino 2150*e4b17023SJohn Marino switch_to_section (targetm.asm_out.function_rodata_section 2151*e4b17023SJohn Marino (current_function_decl)); 2152*e4b17023SJohn Marino 2153*e4b17023SJohn Marino #ifdef ADDR_VEC_ALIGN 2154*e4b17023SJohn Marino log_align = ADDR_VEC_ALIGN (next); 2155*e4b17023SJohn Marino #else 2156*e4b17023SJohn Marino log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); 2157*e4b17023SJohn Marino #endif 2158*e4b17023SJohn Marino ASM_OUTPUT_ALIGN (file, log_align); 2159*e4b17023SJohn Marino } 2160*e4b17023SJohn Marino else 2161*e4b17023SJohn Marino switch_to_section (current_function_section ()); 2162*e4b17023SJohn Marino 2163*e4b17023SJohn Marino #ifdef ASM_OUTPUT_CASE_LABEL 2164*e4b17023SJohn Marino ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), 2165*e4b17023SJohn Marino next); 2166*e4b17023SJohn Marino #else 2167*e4b17023SJohn Marino targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); 2168*e4b17023SJohn Marino #endif 2169*e4b17023SJohn Marino #endif 2170*e4b17023SJohn Marino break; 2171*e4b17023SJohn Marino } 2172*e4b17023SJohn Marino if (LABEL_ALT_ENTRY_P (insn)) 2173*e4b17023SJohn Marino output_alternate_entry_point (file, insn); 2174*e4b17023SJohn Marino else 2175*e4b17023SJohn Marino targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); 2176*e4b17023SJohn Marino break; 2177*e4b17023SJohn Marino 2178*e4b17023SJohn Marino default: 2179*e4b17023SJohn Marino { 2180*e4b17023SJohn Marino rtx body = PATTERN (insn); 2181*e4b17023SJohn Marino int insn_code_number; 2182*e4b17023SJohn Marino const char *templ; 2183*e4b17023SJohn Marino bool is_stmt; 2184*e4b17023SJohn Marino 2185*e4b17023SJohn Marino /* Reset this early so it is correct for ASM statements. */ 2186*e4b17023SJohn Marino current_insn_predicate = NULL_RTX; 2187*e4b17023SJohn Marino 2188*e4b17023SJohn Marino /* An INSN, JUMP_INSN or CALL_INSN. 2189*e4b17023SJohn Marino First check for special kinds that recog doesn't recognize. */ 2190*e4b17023SJohn Marino 2191*e4b17023SJohn Marino if (GET_CODE (body) == USE /* These are just declarations. */ 2192*e4b17023SJohn Marino || GET_CODE (body) == CLOBBER) 2193*e4b17023SJohn Marino break; 2194*e4b17023SJohn Marino 2195*e4b17023SJohn Marino #ifdef HAVE_cc0 2196*e4b17023SJohn Marino { 2197*e4b17023SJohn Marino /* If there is a REG_CC_SETTER note on this insn, it means that 2198*e4b17023SJohn Marino the setting of the condition code was done in the delay slot 2199*e4b17023SJohn Marino of the insn that branched here. So recover the cc status 2200*e4b17023SJohn Marino from the insn that set it. */ 2201*e4b17023SJohn Marino 2202*e4b17023SJohn Marino rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); 2203*e4b17023SJohn Marino if (note) 2204*e4b17023SJohn Marino { 2205*e4b17023SJohn Marino NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0)); 2206*e4b17023SJohn Marino cc_prev_status = cc_status; 2207*e4b17023SJohn Marino } 2208*e4b17023SJohn Marino } 2209*e4b17023SJohn Marino #endif 2210*e4b17023SJohn Marino 2211*e4b17023SJohn Marino /* Detect insns that are really jump-tables 2212*e4b17023SJohn Marino and output them as such. */ 2213*e4b17023SJohn Marino 2214*e4b17023SJohn Marino if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 2215*e4b17023SJohn Marino { 2216*e4b17023SJohn Marino #if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)) 2217*e4b17023SJohn Marino int vlen, idx; 2218*e4b17023SJohn Marino #endif 2219*e4b17023SJohn Marino 2220*e4b17023SJohn Marino if (! JUMP_TABLES_IN_TEXT_SECTION) 2221*e4b17023SJohn Marino switch_to_section (targetm.asm_out.function_rodata_section 2222*e4b17023SJohn Marino (current_function_decl)); 2223*e4b17023SJohn Marino else 2224*e4b17023SJohn Marino switch_to_section (current_function_section ()); 2225*e4b17023SJohn Marino 2226*e4b17023SJohn Marino app_disable (); 2227*e4b17023SJohn Marino 2228*e4b17023SJohn Marino #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC) 2229*e4b17023SJohn Marino if (GET_CODE (body) == ADDR_VEC) 2230*e4b17023SJohn Marino { 2231*e4b17023SJohn Marino #ifdef ASM_OUTPUT_ADDR_VEC 2232*e4b17023SJohn Marino ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body); 2233*e4b17023SJohn Marino #else 2234*e4b17023SJohn Marino gcc_unreachable (); 2235*e4b17023SJohn Marino #endif 2236*e4b17023SJohn Marino } 2237*e4b17023SJohn Marino else 2238*e4b17023SJohn Marino { 2239*e4b17023SJohn Marino #ifdef ASM_OUTPUT_ADDR_DIFF_VEC 2240*e4b17023SJohn Marino ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body); 2241*e4b17023SJohn Marino #else 2242*e4b17023SJohn Marino gcc_unreachable (); 2243*e4b17023SJohn Marino #endif 2244*e4b17023SJohn Marino } 2245*e4b17023SJohn Marino #else 2246*e4b17023SJohn Marino vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC); 2247*e4b17023SJohn Marino for (idx = 0; idx < vlen; idx++) 2248*e4b17023SJohn Marino { 2249*e4b17023SJohn Marino if (GET_CODE (body) == ADDR_VEC) 2250*e4b17023SJohn Marino { 2251*e4b17023SJohn Marino #ifdef ASM_OUTPUT_ADDR_VEC_ELT 2252*e4b17023SJohn Marino ASM_OUTPUT_ADDR_VEC_ELT 2253*e4b17023SJohn Marino (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); 2254*e4b17023SJohn Marino #else 2255*e4b17023SJohn Marino gcc_unreachable (); 2256*e4b17023SJohn Marino #endif 2257*e4b17023SJohn Marino } 2258*e4b17023SJohn Marino else 2259*e4b17023SJohn Marino { 2260*e4b17023SJohn Marino #ifdef ASM_OUTPUT_ADDR_DIFF_ELT 2261*e4b17023SJohn Marino ASM_OUTPUT_ADDR_DIFF_ELT 2262*e4b17023SJohn Marino (file, 2263*e4b17023SJohn Marino body, 2264*e4b17023SJohn Marino CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), 2265*e4b17023SJohn Marino CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); 2266*e4b17023SJohn Marino #else 2267*e4b17023SJohn Marino gcc_unreachable (); 2268*e4b17023SJohn Marino #endif 2269*e4b17023SJohn Marino } 2270*e4b17023SJohn Marino } 2271*e4b17023SJohn Marino #ifdef ASM_OUTPUT_CASE_END 2272*e4b17023SJohn Marino ASM_OUTPUT_CASE_END (file, 2273*e4b17023SJohn Marino CODE_LABEL_NUMBER (PREV_INSN (insn)), 2274*e4b17023SJohn Marino insn); 2275*e4b17023SJohn Marino #endif 2276*e4b17023SJohn Marino #endif 2277*e4b17023SJohn Marino 2278*e4b17023SJohn Marino switch_to_section (current_function_section ()); 2279*e4b17023SJohn Marino 2280*e4b17023SJohn Marino break; 2281*e4b17023SJohn Marino } 2282*e4b17023SJohn Marino /* Output this line note if it is the first or the last line 2283*e4b17023SJohn Marino note in a row. */ 2284*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl) 2285*e4b17023SJohn Marino && notice_source_line (insn, &is_stmt)) 2286*e4b17023SJohn Marino (*debug_hooks->source_line) (last_linenum, last_filename, 2287*e4b17023SJohn Marino last_discriminator, is_stmt); 2288*e4b17023SJohn Marino 2289*e4b17023SJohn Marino if (GET_CODE (body) == ASM_INPUT) 2290*e4b17023SJohn Marino { 2291*e4b17023SJohn Marino const char *string = XSTR (body, 0); 2292*e4b17023SJohn Marino 2293*e4b17023SJohn Marino /* There's no telling what that did to the condition codes. */ 2294*e4b17023SJohn Marino CC_STATUS_INIT; 2295*e4b17023SJohn Marino 2296*e4b17023SJohn Marino if (string[0]) 2297*e4b17023SJohn Marino { 2298*e4b17023SJohn Marino expanded_location loc; 2299*e4b17023SJohn Marino 2300*e4b17023SJohn Marino app_enable (); 2301*e4b17023SJohn Marino loc = expand_location (ASM_INPUT_SOURCE_LOCATION (body)); 2302*e4b17023SJohn Marino if (*loc.file && loc.line) 2303*e4b17023SJohn Marino fprintf (asm_out_file, "%s %i \"%s\" 1\n", 2304*e4b17023SJohn Marino ASM_COMMENT_START, loc.line, loc.file); 2305*e4b17023SJohn Marino fprintf (asm_out_file, "\t%s\n", string); 2306*e4b17023SJohn Marino #if HAVE_AS_LINE_ZERO 2307*e4b17023SJohn Marino if (*loc.file && loc.line) 2308*e4b17023SJohn Marino fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START); 2309*e4b17023SJohn Marino #endif 2310*e4b17023SJohn Marino } 2311*e4b17023SJohn Marino break; 2312*e4b17023SJohn Marino } 2313*e4b17023SJohn Marino 2314*e4b17023SJohn Marino /* Detect `asm' construct with operands. */ 2315*e4b17023SJohn Marino if (asm_noperands (body) >= 0) 2316*e4b17023SJohn Marino { 2317*e4b17023SJohn Marino unsigned int noperands = asm_noperands (body); 2318*e4b17023SJohn Marino rtx *ops = XALLOCAVEC (rtx, noperands); 2319*e4b17023SJohn Marino const char *string; 2320*e4b17023SJohn Marino location_t loc; 2321*e4b17023SJohn Marino expanded_location expanded; 2322*e4b17023SJohn Marino 2323*e4b17023SJohn Marino /* There's no telling what that did to the condition codes. */ 2324*e4b17023SJohn Marino CC_STATUS_INIT; 2325*e4b17023SJohn Marino 2326*e4b17023SJohn Marino /* Get out the operand values. */ 2327*e4b17023SJohn Marino string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc); 2328*e4b17023SJohn Marino /* Inhibit dying on what would otherwise be compiler bugs. */ 2329*e4b17023SJohn Marino insn_noperands = noperands; 2330*e4b17023SJohn Marino this_is_asm_operands = insn; 2331*e4b17023SJohn Marino expanded = expand_location (loc); 2332*e4b17023SJohn Marino 2333*e4b17023SJohn Marino #ifdef FINAL_PRESCAN_INSN 2334*e4b17023SJohn Marino FINAL_PRESCAN_INSN (insn, ops, insn_noperands); 2335*e4b17023SJohn Marino #endif 2336*e4b17023SJohn Marino 2337*e4b17023SJohn Marino /* Output the insn using them. */ 2338*e4b17023SJohn Marino if (string[0]) 2339*e4b17023SJohn Marino { 2340*e4b17023SJohn Marino app_enable (); 2341*e4b17023SJohn Marino if (expanded.file && expanded.line) 2342*e4b17023SJohn Marino fprintf (asm_out_file, "%s %i \"%s\" 1\n", 2343*e4b17023SJohn Marino ASM_COMMENT_START, expanded.line, expanded.file); 2344*e4b17023SJohn Marino output_asm_insn (string, ops); 2345*e4b17023SJohn Marino #if HAVE_AS_LINE_ZERO 2346*e4b17023SJohn Marino if (expanded.file && expanded.line) 2347*e4b17023SJohn Marino fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START); 2348*e4b17023SJohn Marino #endif 2349*e4b17023SJohn Marino } 2350*e4b17023SJohn Marino 2351*e4b17023SJohn Marino if (targetm.asm_out.final_postscan_insn) 2352*e4b17023SJohn Marino targetm.asm_out.final_postscan_insn (file, insn, ops, 2353*e4b17023SJohn Marino insn_noperands); 2354*e4b17023SJohn Marino 2355*e4b17023SJohn Marino this_is_asm_operands = 0; 2356*e4b17023SJohn Marino break; 2357*e4b17023SJohn Marino } 2358*e4b17023SJohn Marino 2359*e4b17023SJohn Marino app_disable (); 2360*e4b17023SJohn Marino 2361*e4b17023SJohn Marino if (GET_CODE (body) == SEQUENCE) 2362*e4b17023SJohn Marino { 2363*e4b17023SJohn Marino /* A delayed-branch sequence */ 2364*e4b17023SJohn Marino int i; 2365*e4b17023SJohn Marino 2366*e4b17023SJohn Marino final_sequence = body; 2367*e4b17023SJohn Marino 2368*e4b17023SJohn Marino /* The first insn in this SEQUENCE might be a JUMP_INSN that will 2369*e4b17023SJohn Marino force the restoration of a comparison that was previously 2370*e4b17023SJohn Marino thought unnecessary. If that happens, cancel this sequence 2371*e4b17023SJohn Marino and cause that insn to be restored. */ 2372*e4b17023SJohn Marino 2373*e4b17023SJohn Marino next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, 1, seen); 2374*e4b17023SJohn Marino if (next != XVECEXP (body, 0, 1)) 2375*e4b17023SJohn Marino { 2376*e4b17023SJohn Marino final_sequence = 0; 2377*e4b17023SJohn Marino return next; 2378*e4b17023SJohn Marino } 2379*e4b17023SJohn Marino 2380*e4b17023SJohn Marino for (i = 1; i < XVECLEN (body, 0); i++) 2381*e4b17023SJohn Marino { 2382*e4b17023SJohn Marino rtx insn = XVECEXP (body, 0, i); 2383*e4b17023SJohn Marino rtx next = NEXT_INSN (insn); 2384*e4b17023SJohn Marino /* We loop in case any instruction in a delay slot gets 2385*e4b17023SJohn Marino split. */ 2386*e4b17023SJohn Marino do 2387*e4b17023SJohn Marino insn = final_scan_insn (insn, file, 0, 1, seen); 2388*e4b17023SJohn Marino while (insn != next); 2389*e4b17023SJohn Marino } 2390*e4b17023SJohn Marino #ifdef DBR_OUTPUT_SEQEND 2391*e4b17023SJohn Marino DBR_OUTPUT_SEQEND (file); 2392*e4b17023SJohn Marino #endif 2393*e4b17023SJohn Marino final_sequence = 0; 2394*e4b17023SJohn Marino 2395*e4b17023SJohn Marino /* If the insn requiring the delay slot was a CALL_INSN, the 2396*e4b17023SJohn Marino insns in the delay slot are actually executed before the 2397*e4b17023SJohn Marino called function. Hence we don't preserve any CC-setting 2398*e4b17023SJohn Marino actions in these insns and the CC must be marked as being 2399*e4b17023SJohn Marino clobbered by the function. */ 2400*e4b17023SJohn Marino if (CALL_P (XVECEXP (body, 0, 0))) 2401*e4b17023SJohn Marino { 2402*e4b17023SJohn Marino CC_STATUS_INIT; 2403*e4b17023SJohn Marino } 2404*e4b17023SJohn Marino break; 2405*e4b17023SJohn Marino } 2406*e4b17023SJohn Marino 2407*e4b17023SJohn Marino /* We have a real machine instruction as rtl. */ 2408*e4b17023SJohn Marino 2409*e4b17023SJohn Marino body = PATTERN (insn); 2410*e4b17023SJohn Marino 2411*e4b17023SJohn Marino #ifdef HAVE_cc0 2412*e4b17023SJohn Marino set = single_set (insn); 2413*e4b17023SJohn Marino 2414*e4b17023SJohn Marino /* Check for redundant test and compare instructions 2415*e4b17023SJohn Marino (when the condition codes are already set up as desired). 2416*e4b17023SJohn Marino This is done only when optimizing; if not optimizing, 2417*e4b17023SJohn Marino it should be possible for the user to alter a variable 2418*e4b17023SJohn Marino with the debugger in between statements 2419*e4b17023SJohn Marino and the next statement should reexamine the variable 2420*e4b17023SJohn Marino to compute the condition codes. */ 2421*e4b17023SJohn Marino 2422*e4b17023SJohn Marino if (optimize_p) 2423*e4b17023SJohn Marino { 2424*e4b17023SJohn Marino if (set 2425*e4b17023SJohn Marino && GET_CODE (SET_DEST (set)) == CC0 2426*e4b17023SJohn Marino && insn != last_ignored_compare) 2427*e4b17023SJohn Marino { 2428*e4b17023SJohn Marino rtx src1, src2; 2429*e4b17023SJohn Marino if (GET_CODE (SET_SRC (set)) == SUBREG) 2430*e4b17023SJohn Marino SET_SRC (set) = alter_subreg (&SET_SRC (set)); 2431*e4b17023SJohn Marino 2432*e4b17023SJohn Marino src1 = SET_SRC (set); 2433*e4b17023SJohn Marino src2 = NULL_RTX; 2434*e4b17023SJohn Marino if (GET_CODE (SET_SRC (set)) == COMPARE) 2435*e4b17023SJohn Marino { 2436*e4b17023SJohn Marino if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG) 2437*e4b17023SJohn Marino XEXP (SET_SRC (set), 0) 2438*e4b17023SJohn Marino = alter_subreg (&XEXP (SET_SRC (set), 0)); 2439*e4b17023SJohn Marino if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG) 2440*e4b17023SJohn Marino XEXP (SET_SRC (set), 1) 2441*e4b17023SJohn Marino = alter_subreg (&XEXP (SET_SRC (set), 1)); 2442*e4b17023SJohn Marino if (XEXP (SET_SRC (set), 1) 2443*e4b17023SJohn Marino == CONST0_RTX (GET_MODE (XEXP (SET_SRC (set), 0)))) 2444*e4b17023SJohn Marino src2 = XEXP (SET_SRC (set), 0); 2445*e4b17023SJohn Marino } 2446*e4b17023SJohn Marino if ((cc_status.value1 != 0 2447*e4b17023SJohn Marino && rtx_equal_p (src1, cc_status.value1)) 2448*e4b17023SJohn Marino || (cc_status.value2 != 0 2449*e4b17023SJohn Marino && rtx_equal_p (src1, cc_status.value2)) 2450*e4b17023SJohn Marino || (src2 != 0 && cc_status.value1 != 0 2451*e4b17023SJohn Marino && rtx_equal_p (src2, cc_status.value1)) 2452*e4b17023SJohn Marino || (src2 != 0 && cc_status.value2 != 0 2453*e4b17023SJohn Marino && rtx_equal_p (src2, cc_status.value2))) 2454*e4b17023SJohn Marino { 2455*e4b17023SJohn Marino /* Don't delete insn if it has an addressing side-effect. */ 2456*e4b17023SJohn Marino if (! FIND_REG_INC_NOTE (insn, NULL_RTX) 2457*e4b17023SJohn Marino /* or if anything in it is volatile. */ 2458*e4b17023SJohn Marino && ! volatile_refs_p (PATTERN (insn))) 2459*e4b17023SJohn Marino { 2460*e4b17023SJohn Marino /* We don't really delete the insn; just ignore it. */ 2461*e4b17023SJohn Marino last_ignored_compare = insn; 2462*e4b17023SJohn Marino break; 2463*e4b17023SJohn Marino } 2464*e4b17023SJohn Marino } 2465*e4b17023SJohn Marino } 2466*e4b17023SJohn Marino } 2467*e4b17023SJohn Marino 2468*e4b17023SJohn Marino /* If this is a conditional branch, maybe modify it 2469*e4b17023SJohn Marino if the cc's are in a nonstandard state 2470*e4b17023SJohn Marino so that it accomplishes the same thing that it would 2471*e4b17023SJohn Marino do straightforwardly if the cc's were set up normally. */ 2472*e4b17023SJohn Marino 2473*e4b17023SJohn Marino if (cc_status.flags != 0 2474*e4b17023SJohn Marino && JUMP_P (insn) 2475*e4b17023SJohn Marino && GET_CODE (body) == SET 2476*e4b17023SJohn Marino && SET_DEST (body) == pc_rtx 2477*e4b17023SJohn Marino && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE 2478*e4b17023SJohn Marino && COMPARISON_P (XEXP (SET_SRC (body), 0)) 2479*e4b17023SJohn Marino && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx) 2480*e4b17023SJohn Marino { 2481*e4b17023SJohn Marino /* This function may alter the contents of its argument 2482*e4b17023SJohn Marino and clear some of the cc_status.flags bits. 2483*e4b17023SJohn Marino It may also return 1 meaning condition now always true 2484*e4b17023SJohn Marino or -1 meaning condition now always false 2485*e4b17023SJohn Marino or 2 meaning condition nontrivial but altered. */ 2486*e4b17023SJohn Marino int result = alter_cond (XEXP (SET_SRC (body), 0)); 2487*e4b17023SJohn Marino /* If condition now has fixed value, replace the IF_THEN_ELSE 2488*e4b17023SJohn Marino with its then-operand or its else-operand. */ 2489*e4b17023SJohn Marino if (result == 1) 2490*e4b17023SJohn Marino SET_SRC (body) = XEXP (SET_SRC (body), 1); 2491*e4b17023SJohn Marino if (result == -1) 2492*e4b17023SJohn Marino SET_SRC (body) = XEXP (SET_SRC (body), 2); 2493*e4b17023SJohn Marino 2494*e4b17023SJohn Marino /* The jump is now either unconditional or a no-op. 2495*e4b17023SJohn Marino If it has become a no-op, don't try to output it. 2496*e4b17023SJohn Marino (It would not be recognized.) */ 2497*e4b17023SJohn Marino if (SET_SRC (body) == pc_rtx) 2498*e4b17023SJohn Marino { 2499*e4b17023SJohn Marino delete_insn (insn); 2500*e4b17023SJohn Marino break; 2501*e4b17023SJohn Marino } 2502*e4b17023SJohn Marino else if (ANY_RETURN_P (SET_SRC (body))) 2503*e4b17023SJohn Marino /* Replace (set (pc) (return)) with (return). */ 2504*e4b17023SJohn Marino PATTERN (insn) = body = SET_SRC (body); 2505*e4b17023SJohn Marino 2506*e4b17023SJohn Marino /* Rerecognize the instruction if it has changed. */ 2507*e4b17023SJohn Marino if (result != 0) 2508*e4b17023SJohn Marino INSN_CODE (insn) = -1; 2509*e4b17023SJohn Marino } 2510*e4b17023SJohn Marino 2511*e4b17023SJohn Marino /* If this is a conditional trap, maybe modify it if the cc's 2512*e4b17023SJohn Marino are in a nonstandard state so that it accomplishes the same 2513*e4b17023SJohn Marino thing that it would do straightforwardly if the cc's were 2514*e4b17023SJohn Marino set up normally. */ 2515*e4b17023SJohn Marino if (cc_status.flags != 0 2516*e4b17023SJohn Marino && NONJUMP_INSN_P (insn) 2517*e4b17023SJohn Marino && GET_CODE (body) == TRAP_IF 2518*e4b17023SJohn Marino && COMPARISON_P (TRAP_CONDITION (body)) 2519*e4b17023SJohn Marino && XEXP (TRAP_CONDITION (body), 0) == cc0_rtx) 2520*e4b17023SJohn Marino { 2521*e4b17023SJohn Marino /* This function may alter the contents of its argument 2522*e4b17023SJohn Marino and clear some of the cc_status.flags bits. 2523*e4b17023SJohn Marino It may also return 1 meaning condition now always true 2524*e4b17023SJohn Marino or -1 meaning condition now always false 2525*e4b17023SJohn Marino or 2 meaning condition nontrivial but altered. */ 2526*e4b17023SJohn Marino int result = alter_cond (TRAP_CONDITION (body)); 2527*e4b17023SJohn Marino 2528*e4b17023SJohn Marino /* If TRAP_CONDITION has become always false, delete the 2529*e4b17023SJohn Marino instruction. */ 2530*e4b17023SJohn Marino if (result == -1) 2531*e4b17023SJohn Marino { 2532*e4b17023SJohn Marino delete_insn (insn); 2533*e4b17023SJohn Marino break; 2534*e4b17023SJohn Marino } 2535*e4b17023SJohn Marino 2536*e4b17023SJohn Marino /* If TRAP_CONDITION has become always true, replace 2537*e4b17023SJohn Marino TRAP_CONDITION with const_true_rtx. */ 2538*e4b17023SJohn Marino if (result == 1) 2539*e4b17023SJohn Marino TRAP_CONDITION (body) = const_true_rtx; 2540*e4b17023SJohn Marino 2541*e4b17023SJohn Marino /* Rerecognize the instruction if it has changed. */ 2542*e4b17023SJohn Marino if (result != 0) 2543*e4b17023SJohn Marino INSN_CODE (insn) = -1; 2544*e4b17023SJohn Marino } 2545*e4b17023SJohn Marino 2546*e4b17023SJohn Marino /* Make same adjustments to instructions that examine the 2547*e4b17023SJohn Marino condition codes without jumping and instructions that 2548*e4b17023SJohn Marino handle conditional moves (if this machine has either one). */ 2549*e4b17023SJohn Marino 2550*e4b17023SJohn Marino if (cc_status.flags != 0 2551*e4b17023SJohn Marino && set != 0) 2552*e4b17023SJohn Marino { 2553*e4b17023SJohn Marino rtx cond_rtx, then_rtx, else_rtx; 2554*e4b17023SJohn Marino 2555*e4b17023SJohn Marino if (!JUMP_P (insn) 2556*e4b17023SJohn Marino && GET_CODE (SET_SRC (set)) == IF_THEN_ELSE) 2557*e4b17023SJohn Marino { 2558*e4b17023SJohn Marino cond_rtx = XEXP (SET_SRC (set), 0); 2559*e4b17023SJohn Marino then_rtx = XEXP (SET_SRC (set), 1); 2560*e4b17023SJohn Marino else_rtx = XEXP (SET_SRC (set), 2); 2561*e4b17023SJohn Marino } 2562*e4b17023SJohn Marino else 2563*e4b17023SJohn Marino { 2564*e4b17023SJohn Marino cond_rtx = SET_SRC (set); 2565*e4b17023SJohn Marino then_rtx = const_true_rtx; 2566*e4b17023SJohn Marino else_rtx = const0_rtx; 2567*e4b17023SJohn Marino } 2568*e4b17023SJohn Marino 2569*e4b17023SJohn Marino switch (GET_CODE (cond_rtx)) 2570*e4b17023SJohn Marino { 2571*e4b17023SJohn Marino case GTU: 2572*e4b17023SJohn Marino case GT: 2573*e4b17023SJohn Marino case LTU: 2574*e4b17023SJohn Marino case LT: 2575*e4b17023SJohn Marino case GEU: 2576*e4b17023SJohn Marino case GE: 2577*e4b17023SJohn Marino case LEU: 2578*e4b17023SJohn Marino case LE: 2579*e4b17023SJohn Marino case EQ: 2580*e4b17023SJohn Marino case NE: 2581*e4b17023SJohn Marino { 2582*e4b17023SJohn Marino int result; 2583*e4b17023SJohn Marino if (XEXP (cond_rtx, 0) != cc0_rtx) 2584*e4b17023SJohn Marino break; 2585*e4b17023SJohn Marino result = alter_cond (cond_rtx); 2586*e4b17023SJohn Marino if (result == 1) 2587*e4b17023SJohn Marino validate_change (insn, &SET_SRC (set), then_rtx, 0); 2588*e4b17023SJohn Marino else if (result == -1) 2589*e4b17023SJohn Marino validate_change (insn, &SET_SRC (set), else_rtx, 0); 2590*e4b17023SJohn Marino else if (result == 2) 2591*e4b17023SJohn Marino INSN_CODE (insn) = -1; 2592*e4b17023SJohn Marino if (SET_DEST (set) == SET_SRC (set)) 2593*e4b17023SJohn Marino delete_insn (insn); 2594*e4b17023SJohn Marino } 2595*e4b17023SJohn Marino break; 2596*e4b17023SJohn Marino 2597*e4b17023SJohn Marino default: 2598*e4b17023SJohn Marino break; 2599*e4b17023SJohn Marino } 2600*e4b17023SJohn Marino } 2601*e4b17023SJohn Marino 2602*e4b17023SJohn Marino #endif 2603*e4b17023SJohn Marino 2604*e4b17023SJohn Marino #ifdef HAVE_peephole 2605*e4b17023SJohn Marino /* Do machine-specific peephole optimizations if desired. */ 2606*e4b17023SJohn Marino 2607*e4b17023SJohn Marino if (optimize_p && !flag_no_peephole && !nopeepholes) 2608*e4b17023SJohn Marino { 2609*e4b17023SJohn Marino rtx next = peephole (insn); 2610*e4b17023SJohn Marino /* When peepholing, if there were notes within the peephole, 2611*e4b17023SJohn Marino emit them before the peephole. */ 2612*e4b17023SJohn Marino if (next != 0 && next != NEXT_INSN (insn)) 2613*e4b17023SJohn Marino { 2614*e4b17023SJohn Marino rtx note, prev = PREV_INSN (insn); 2615*e4b17023SJohn Marino 2616*e4b17023SJohn Marino for (note = NEXT_INSN (insn); note != next; 2617*e4b17023SJohn Marino note = NEXT_INSN (note)) 2618*e4b17023SJohn Marino final_scan_insn (note, file, optimize_p, nopeepholes, seen); 2619*e4b17023SJohn Marino 2620*e4b17023SJohn Marino /* Put the notes in the proper position for a later 2621*e4b17023SJohn Marino rescan. For example, the SH target can do this 2622*e4b17023SJohn Marino when generating a far jump in a delayed branch 2623*e4b17023SJohn Marino sequence. */ 2624*e4b17023SJohn Marino note = NEXT_INSN (insn); 2625*e4b17023SJohn Marino PREV_INSN (note) = prev; 2626*e4b17023SJohn Marino NEXT_INSN (prev) = note; 2627*e4b17023SJohn Marino NEXT_INSN (PREV_INSN (next)) = insn; 2628*e4b17023SJohn Marino PREV_INSN (insn) = PREV_INSN (next); 2629*e4b17023SJohn Marino NEXT_INSN (insn) = next; 2630*e4b17023SJohn Marino PREV_INSN (next) = insn; 2631*e4b17023SJohn Marino } 2632*e4b17023SJohn Marino 2633*e4b17023SJohn Marino /* PEEPHOLE might have changed this. */ 2634*e4b17023SJohn Marino body = PATTERN (insn); 2635*e4b17023SJohn Marino } 2636*e4b17023SJohn Marino #endif 2637*e4b17023SJohn Marino 2638*e4b17023SJohn Marino /* Try to recognize the instruction. 2639*e4b17023SJohn Marino If successful, verify that the operands satisfy the 2640*e4b17023SJohn Marino constraints for the instruction. Crash if they don't, 2641*e4b17023SJohn Marino since `reload' should have changed them so that they do. */ 2642*e4b17023SJohn Marino 2643*e4b17023SJohn Marino insn_code_number = recog_memoized (insn); 2644*e4b17023SJohn Marino cleanup_subreg_operands (insn); 2645*e4b17023SJohn Marino 2646*e4b17023SJohn Marino /* Dump the insn in the assembly for debugging. */ 2647*e4b17023SJohn Marino if (flag_dump_rtl_in_asm) 2648*e4b17023SJohn Marino { 2649*e4b17023SJohn Marino print_rtx_head = ASM_COMMENT_START; 2650*e4b17023SJohn Marino print_rtl_single (asm_out_file, insn); 2651*e4b17023SJohn Marino print_rtx_head = ""; 2652*e4b17023SJohn Marino } 2653*e4b17023SJohn Marino 2654*e4b17023SJohn Marino if (! constrain_operands_cached (1)) 2655*e4b17023SJohn Marino fatal_insn_not_found (insn); 2656*e4b17023SJohn Marino 2657*e4b17023SJohn Marino /* Some target machines need to prescan each insn before 2658*e4b17023SJohn Marino it is output. */ 2659*e4b17023SJohn Marino 2660*e4b17023SJohn Marino #ifdef FINAL_PRESCAN_INSN 2661*e4b17023SJohn Marino FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands); 2662*e4b17023SJohn Marino #endif 2663*e4b17023SJohn Marino 2664*e4b17023SJohn Marino if (targetm.have_conditional_execution () 2665*e4b17023SJohn Marino && GET_CODE (PATTERN (insn)) == COND_EXEC) 2666*e4b17023SJohn Marino current_insn_predicate = COND_EXEC_TEST (PATTERN (insn)); 2667*e4b17023SJohn Marino 2668*e4b17023SJohn Marino #ifdef HAVE_cc0 2669*e4b17023SJohn Marino cc_prev_status = cc_status; 2670*e4b17023SJohn Marino 2671*e4b17023SJohn Marino /* Update `cc_status' for this instruction. 2672*e4b17023SJohn Marino The instruction's output routine may change it further. 2673*e4b17023SJohn Marino If the output routine for a jump insn needs to depend 2674*e4b17023SJohn Marino on the cc status, it should look at cc_prev_status. */ 2675*e4b17023SJohn Marino 2676*e4b17023SJohn Marino NOTICE_UPDATE_CC (body, insn); 2677*e4b17023SJohn Marino #endif 2678*e4b17023SJohn Marino 2679*e4b17023SJohn Marino current_output_insn = debug_insn = insn; 2680*e4b17023SJohn Marino 2681*e4b17023SJohn Marino /* Find the proper template for this insn. */ 2682*e4b17023SJohn Marino templ = get_insn_template (insn_code_number, insn); 2683*e4b17023SJohn Marino 2684*e4b17023SJohn Marino /* If the C code returns 0, it means that it is a jump insn 2685*e4b17023SJohn Marino which follows a deleted test insn, and that test insn 2686*e4b17023SJohn Marino needs to be reinserted. */ 2687*e4b17023SJohn Marino if (templ == 0) 2688*e4b17023SJohn Marino { 2689*e4b17023SJohn Marino rtx prev; 2690*e4b17023SJohn Marino 2691*e4b17023SJohn Marino gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare); 2692*e4b17023SJohn Marino 2693*e4b17023SJohn Marino /* We have already processed the notes between the setter and 2694*e4b17023SJohn Marino the user. Make sure we don't process them again, this is 2695*e4b17023SJohn Marino particularly important if one of the notes is a block 2696*e4b17023SJohn Marino scope note or an EH note. */ 2697*e4b17023SJohn Marino for (prev = insn; 2698*e4b17023SJohn Marino prev != last_ignored_compare; 2699*e4b17023SJohn Marino prev = PREV_INSN (prev)) 2700*e4b17023SJohn Marino { 2701*e4b17023SJohn Marino if (NOTE_P (prev)) 2702*e4b17023SJohn Marino delete_insn (prev); /* Use delete_note. */ 2703*e4b17023SJohn Marino } 2704*e4b17023SJohn Marino 2705*e4b17023SJohn Marino return prev; 2706*e4b17023SJohn Marino } 2707*e4b17023SJohn Marino 2708*e4b17023SJohn Marino /* If the template is the string "#", it means that this insn must 2709*e4b17023SJohn Marino be split. */ 2710*e4b17023SJohn Marino if (templ[0] == '#' && templ[1] == '\0') 2711*e4b17023SJohn Marino { 2712*e4b17023SJohn Marino rtx new_rtx = try_split (body, insn, 0); 2713*e4b17023SJohn Marino 2714*e4b17023SJohn Marino /* If we didn't split the insn, go away. */ 2715*e4b17023SJohn Marino if (new_rtx == insn && PATTERN (new_rtx) == body) 2716*e4b17023SJohn Marino fatal_insn ("could not split insn", insn); 2717*e4b17023SJohn Marino 2718*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 2719*e4b17023SJohn Marino /* This instruction should have been split in shorten_branches, 2720*e4b17023SJohn Marino to ensure that we would have valid length info for the 2721*e4b17023SJohn Marino splitees. */ 2722*e4b17023SJohn Marino gcc_unreachable (); 2723*e4b17023SJohn Marino #endif 2724*e4b17023SJohn Marino 2725*e4b17023SJohn Marino return new_rtx; 2726*e4b17023SJohn Marino } 2727*e4b17023SJohn Marino 2728*e4b17023SJohn Marino /* ??? This will put the directives in the wrong place if 2729*e4b17023SJohn Marino get_insn_template outputs assembly directly. However calling it 2730*e4b17023SJohn Marino before get_insn_template breaks if the insns is split. */ 2731*e4b17023SJohn Marino if (targetm.asm_out.unwind_emit_before_insn 2732*e4b17023SJohn Marino && targetm.asm_out.unwind_emit) 2733*e4b17023SJohn Marino targetm.asm_out.unwind_emit (asm_out_file, insn); 2734*e4b17023SJohn Marino 2735*e4b17023SJohn Marino if (CALL_P (insn)) 2736*e4b17023SJohn Marino { 2737*e4b17023SJohn Marino rtx x = call_from_call_insn (insn); 2738*e4b17023SJohn Marino x = XEXP (x, 0); 2739*e4b17023SJohn Marino if (x && MEM_P (x) && GET_CODE (XEXP (x, 0)) == SYMBOL_REF) 2740*e4b17023SJohn Marino { 2741*e4b17023SJohn Marino tree t; 2742*e4b17023SJohn Marino x = XEXP (x, 0); 2743*e4b17023SJohn Marino t = SYMBOL_REF_DECL (x); 2744*e4b17023SJohn Marino if (t) 2745*e4b17023SJohn Marino assemble_external (t); 2746*e4b17023SJohn Marino } 2747*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 2748*e4b17023SJohn Marino debug_hooks->var_location (insn); 2749*e4b17023SJohn Marino } 2750*e4b17023SJohn Marino 2751*e4b17023SJohn Marino /* Output assembler code from the template. */ 2752*e4b17023SJohn Marino output_asm_insn (templ, recog_data.operand); 2753*e4b17023SJohn Marino 2754*e4b17023SJohn Marino /* Some target machines need to postscan each insn after 2755*e4b17023SJohn Marino it is output. */ 2756*e4b17023SJohn Marino if (targetm.asm_out.final_postscan_insn) 2757*e4b17023SJohn Marino targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand, 2758*e4b17023SJohn Marino recog_data.n_operands); 2759*e4b17023SJohn Marino 2760*e4b17023SJohn Marino if (!targetm.asm_out.unwind_emit_before_insn 2761*e4b17023SJohn Marino && targetm.asm_out.unwind_emit) 2762*e4b17023SJohn Marino targetm.asm_out.unwind_emit (asm_out_file, insn); 2763*e4b17023SJohn Marino 2764*e4b17023SJohn Marino current_output_insn = debug_insn = 0; 2765*e4b17023SJohn Marino } 2766*e4b17023SJohn Marino } 2767*e4b17023SJohn Marino return NEXT_INSN (insn); 2768*e4b17023SJohn Marino } 2769*e4b17023SJohn Marino 2770*e4b17023SJohn Marino /* Return whether a source line note needs to be emitted before INSN. 2771*e4b17023SJohn Marino Sets IS_STMT to TRUE if the line should be marked as a possible 2772*e4b17023SJohn Marino breakpoint location. */ 2773*e4b17023SJohn Marino 2774*e4b17023SJohn Marino static bool 2775*e4b17023SJohn Marino notice_source_line (rtx insn, bool *is_stmt) 2776*e4b17023SJohn Marino { 2777*e4b17023SJohn Marino const char *filename; 2778*e4b17023SJohn Marino int linenum; 2779*e4b17023SJohn Marino 2780*e4b17023SJohn Marino if (override_filename) 2781*e4b17023SJohn Marino { 2782*e4b17023SJohn Marino filename = override_filename; 2783*e4b17023SJohn Marino linenum = override_linenum; 2784*e4b17023SJohn Marino } 2785*e4b17023SJohn Marino else 2786*e4b17023SJohn Marino { 2787*e4b17023SJohn Marino filename = insn_file (insn); 2788*e4b17023SJohn Marino linenum = insn_line (insn); 2789*e4b17023SJohn Marino } 2790*e4b17023SJohn Marino 2791*e4b17023SJohn Marino if (filename == NULL) 2792*e4b17023SJohn Marino return false; 2793*e4b17023SJohn Marino 2794*e4b17023SJohn Marino if (force_source_line 2795*e4b17023SJohn Marino || filename != last_filename 2796*e4b17023SJohn Marino || last_linenum != linenum) 2797*e4b17023SJohn Marino { 2798*e4b17023SJohn Marino force_source_line = false; 2799*e4b17023SJohn Marino last_filename = filename; 2800*e4b17023SJohn Marino last_linenum = linenum; 2801*e4b17023SJohn Marino last_discriminator = discriminator; 2802*e4b17023SJohn Marino *is_stmt = true; 2803*e4b17023SJohn Marino high_block_linenum = MAX (last_linenum, high_block_linenum); 2804*e4b17023SJohn Marino high_function_linenum = MAX (last_linenum, high_function_linenum); 2805*e4b17023SJohn Marino return true; 2806*e4b17023SJohn Marino } 2807*e4b17023SJohn Marino 2808*e4b17023SJohn Marino if (SUPPORTS_DISCRIMINATOR && last_discriminator != discriminator) 2809*e4b17023SJohn Marino { 2810*e4b17023SJohn Marino /* If the discriminator changed, but the line number did not, 2811*e4b17023SJohn Marino output the line table entry with is_stmt false so the 2812*e4b17023SJohn Marino debugger does not treat this as a breakpoint location. */ 2813*e4b17023SJohn Marino last_discriminator = discriminator; 2814*e4b17023SJohn Marino *is_stmt = false; 2815*e4b17023SJohn Marino return true; 2816*e4b17023SJohn Marino } 2817*e4b17023SJohn Marino 2818*e4b17023SJohn Marino return false; 2819*e4b17023SJohn Marino } 2820*e4b17023SJohn Marino 2821*e4b17023SJohn Marino /* For each operand in INSN, simplify (subreg (reg)) so that it refers 2822*e4b17023SJohn Marino directly to the desired hard register. */ 2823*e4b17023SJohn Marino 2824*e4b17023SJohn Marino void 2825*e4b17023SJohn Marino cleanup_subreg_operands (rtx insn) 2826*e4b17023SJohn Marino { 2827*e4b17023SJohn Marino int i; 2828*e4b17023SJohn Marino bool changed = false; 2829*e4b17023SJohn Marino extract_insn_cached (insn); 2830*e4b17023SJohn Marino for (i = 0; i < recog_data.n_operands; i++) 2831*e4b17023SJohn Marino { 2832*e4b17023SJohn Marino /* The following test cannot use recog_data.operand when testing 2833*e4b17023SJohn Marino for a SUBREG: the underlying object might have been changed 2834*e4b17023SJohn Marino already if we are inside a match_operator expression that 2835*e4b17023SJohn Marino matches the else clause. Instead we test the underlying 2836*e4b17023SJohn Marino expression directly. */ 2837*e4b17023SJohn Marino if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG) 2838*e4b17023SJohn Marino { 2839*e4b17023SJohn Marino recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]); 2840*e4b17023SJohn Marino changed = true; 2841*e4b17023SJohn Marino } 2842*e4b17023SJohn Marino else if (GET_CODE (recog_data.operand[i]) == PLUS 2843*e4b17023SJohn Marino || GET_CODE (recog_data.operand[i]) == MULT 2844*e4b17023SJohn Marino || MEM_P (recog_data.operand[i])) 2845*e4b17023SJohn Marino recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i], &changed); 2846*e4b17023SJohn Marino } 2847*e4b17023SJohn Marino 2848*e4b17023SJohn Marino for (i = 0; i < recog_data.n_dups; i++) 2849*e4b17023SJohn Marino { 2850*e4b17023SJohn Marino if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG) 2851*e4b17023SJohn Marino { 2852*e4b17023SJohn Marino *recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]); 2853*e4b17023SJohn Marino changed = true; 2854*e4b17023SJohn Marino } 2855*e4b17023SJohn Marino else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS 2856*e4b17023SJohn Marino || GET_CODE (*recog_data.dup_loc[i]) == MULT 2857*e4b17023SJohn Marino || MEM_P (*recog_data.dup_loc[i])) 2858*e4b17023SJohn Marino *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i], &changed); 2859*e4b17023SJohn Marino } 2860*e4b17023SJohn Marino if (changed) 2861*e4b17023SJohn Marino df_insn_rescan (insn); 2862*e4b17023SJohn Marino } 2863*e4b17023SJohn Marino 2864*e4b17023SJohn Marino /* If X is a SUBREG, replace it with a REG or a MEM, 2865*e4b17023SJohn Marino based on the thing it is a subreg of. */ 2866*e4b17023SJohn Marino 2867*e4b17023SJohn Marino rtx 2868*e4b17023SJohn Marino alter_subreg (rtx *xp) 2869*e4b17023SJohn Marino { 2870*e4b17023SJohn Marino rtx x = *xp; 2871*e4b17023SJohn Marino rtx y = SUBREG_REG (x); 2872*e4b17023SJohn Marino 2873*e4b17023SJohn Marino /* simplify_subreg does not remove subreg from volatile references. 2874*e4b17023SJohn Marino We are required to. */ 2875*e4b17023SJohn Marino if (MEM_P (y)) 2876*e4b17023SJohn Marino { 2877*e4b17023SJohn Marino int offset = SUBREG_BYTE (x); 2878*e4b17023SJohn Marino 2879*e4b17023SJohn Marino /* For paradoxical subregs on big-endian machines, SUBREG_BYTE 2880*e4b17023SJohn Marino contains 0 instead of the proper offset. See simplify_subreg. */ 2881*e4b17023SJohn Marino if (offset == 0 2882*e4b17023SJohn Marino && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x))) 2883*e4b17023SJohn Marino { 2884*e4b17023SJohn Marino int difference = GET_MODE_SIZE (GET_MODE (y)) 2885*e4b17023SJohn Marino - GET_MODE_SIZE (GET_MODE (x)); 2886*e4b17023SJohn Marino if (WORDS_BIG_ENDIAN) 2887*e4b17023SJohn Marino offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 2888*e4b17023SJohn Marino if (BYTES_BIG_ENDIAN) 2889*e4b17023SJohn Marino offset += difference % UNITS_PER_WORD; 2890*e4b17023SJohn Marino } 2891*e4b17023SJohn Marino 2892*e4b17023SJohn Marino *xp = adjust_address (y, GET_MODE (x), offset); 2893*e4b17023SJohn Marino } 2894*e4b17023SJohn Marino else 2895*e4b17023SJohn Marino { 2896*e4b17023SJohn Marino rtx new_rtx = simplify_subreg (GET_MODE (x), y, GET_MODE (y), 2897*e4b17023SJohn Marino SUBREG_BYTE (x)); 2898*e4b17023SJohn Marino 2899*e4b17023SJohn Marino if (new_rtx != 0) 2900*e4b17023SJohn Marino *xp = new_rtx; 2901*e4b17023SJohn Marino else if (REG_P (y)) 2902*e4b17023SJohn Marino { 2903*e4b17023SJohn Marino /* Simplify_subreg can't handle some REG cases, but we have to. */ 2904*e4b17023SJohn Marino unsigned int regno; 2905*e4b17023SJohn Marino HOST_WIDE_INT offset; 2906*e4b17023SJohn Marino 2907*e4b17023SJohn Marino regno = subreg_regno (x); 2908*e4b17023SJohn Marino if (subreg_lowpart_p (x)) 2909*e4b17023SJohn Marino offset = byte_lowpart_offset (GET_MODE (x), GET_MODE (y)); 2910*e4b17023SJohn Marino else 2911*e4b17023SJohn Marino offset = SUBREG_BYTE (x); 2912*e4b17023SJohn Marino *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, offset); 2913*e4b17023SJohn Marino } 2914*e4b17023SJohn Marino } 2915*e4b17023SJohn Marino 2916*e4b17023SJohn Marino return *xp; 2917*e4b17023SJohn Marino } 2918*e4b17023SJohn Marino 2919*e4b17023SJohn Marino /* Do alter_subreg on all the SUBREGs contained in X. */ 2920*e4b17023SJohn Marino 2921*e4b17023SJohn Marino static rtx 2922*e4b17023SJohn Marino walk_alter_subreg (rtx *xp, bool *changed) 2923*e4b17023SJohn Marino { 2924*e4b17023SJohn Marino rtx x = *xp; 2925*e4b17023SJohn Marino switch (GET_CODE (x)) 2926*e4b17023SJohn Marino { 2927*e4b17023SJohn Marino case PLUS: 2928*e4b17023SJohn Marino case MULT: 2929*e4b17023SJohn Marino case AND: 2930*e4b17023SJohn Marino XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed); 2931*e4b17023SJohn Marino XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1), changed); 2932*e4b17023SJohn Marino break; 2933*e4b17023SJohn Marino 2934*e4b17023SJohn Marino case MEM: 2935*e4b17023SJohn Marino case ZERO_EXTEND: 2936*e4b17023SJohn Marino XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed); 2937*e4b17023SJohn Marino break; 2938*e4b17023SJohn Marino 2939*e4b17023SJohn Marino case SUBREG: 2940*e4b17023SJohn Marino *changed = true; 2941*e4b17023SJohn Marino return alter_subreg (xp); 2942*e4b17023SJohn Marino 2943*e4b17023SJohn Marino default: 2944*e4b17023SJohn Marino break; 2945*e4b17023SJohn Marino } 2946*e4b17023SJohn Marino 2947*e4b17023SJohn Marino return *xp; 2948*e4b17023SJohn Marino } 2949*e4b17023SJohn Marino 2950*e4b17023SJohn Marino #ifdef HAVE_cc0 2951*e4b17023SJohn Marino 2952*e4b17023SJohn Marino /* Given BODY, the body of a jump instruction, alter the jump condition 2953*e4b17023SJohn Marino as required by the bits that are set in cc_status.flags. 2954*e4b17023SJohn Marino Not all of the bits there can be handled at this level in all cases. 2955*e4b17023SJohn Marino 2956*e4b17023SJohn Marino The value is normally 0. 2957*e4b17023SJohn Marino 1 means that the condition has become always true. 2958*e4b17023SJohn Marino -1 means that the condition has become always false. 2959*e4b17023SJohn Marino 2 means that COND has been altered. */ 2960*e4b17023SJohn Marino 2961*e4b17023SJohn Marino static int 2962*e4b17023SJohn Marino alter_cond (rtx cond) 2963*e4b17023SJohn Marino { 2964*e4b17023SJohn Marino int value = 0; 2965*e4b17023SJohn Marino 2966*e4b17023SJohn Marino if (cc_status.flags & CC_REVERSED) 2967*e4b17023SJohn Marino { 2968*e4b17023SJohn Marino value = 2; 2969*e4b17023SJohn Marino PUT_CODE (cond, swap_condition (GET_CODE (cond))); 2970*e4b17023SJohn Marino } 2971*e4b17023SJohn Marino 2972*e4b17023SJohn Marino if (cc_status.flags & CC_INVERTED) 2973*e4b17023SJohn Marino { 2974*e4b17023SJohn Marino value = 2; 2975*e4b17023SJohn Marino PUT_CODE (cond, reverse_condition (GET_CODE (cond))); 2976*e4b17023SJohn Marino } 2977*e4b17023SJohn Marino 2978*e4b17023SJohn Marino if (cc_status.flags & CC_NOT_POSITIVE) 2979*e4b17023SJohn Marino switch (GET_CODE (cond)) 2980*e4b17023SJohn Marino { 2981*e4b17023SJohn Marino case LE: 2982*e4b17023SJohn Marino case LEU: 2983*e4b17023SJohn Marino case GEU: 2984*e4b17023SJohn Marino /* Jump becomes unconditional. */ 2985*e4b17023SJohn Marino return 1; 2986*e4b17023SJohn Marino 2987*e4b17023SJohn Marino case GT: 2988*e4b17023SJohn Marino case GTU: 2989*e4b17023SJohn Marino case LTU: 2990*e4b17023SJohn Marino /* Jump becomes no-op. */ 2991*e4b17023SJohn Marino return -1; 2992*e4b17023SJohn Marino 2993*e4b17023SJohn Marino case GE: 2994*e4b17023SJohn Marino PUT_CODE (cond, EQ); 2995*e4b17023SJohn Marino value = 2; 2996*e4b17023SJohn Marino break; 2997*e4b17023SJohn Marino 2998*e4b17023SJohn Marino case LT: 2999*e4b17023SJohn Marino PUT_CODE (cond, NE); 3000*e4b17023SJohn Marino value = 2; 3001*e4b17023SJohn Marino break; 3002*e4b17023SJohn Marino 3003*e4b17023SJohn Marino default: 3004*e4b17023SJohn Marino break; 3005*e4b17023SJohn Marino } 3006*e4b17023SJohn Marino 3007*e4b17023SJohn Marino if (cc_status.flags & CC_NOT_NEGATIVE) 3008*e4b17023SJohn Marino switch (GET_CODE (cond)) 3009*e4b17023SJohn Marino { 3010*e4b17023SJohn Marino case GE: 3011*e4b17023SJohn Marino case GEU: 3012*e4b17023SJohn Marino /* Jump becomes unconditional. */ 3013*e4b17023SJohn Marino return 1; 3014*e4b17023SJohn Marino 3015*e4b17023SJohn Marino case LT: 3016*e4b17023SJohn Marino case LTU: 3017*e4b17023SJohn Marino /* Jump becomes no-op. */ 3018*e4b17023SJohn Marino return -1; 3019*e4b17023SJohn Marino 3020*e4b17023SJohn Marino case LE: 3021*e4b17023SJohn Marino case LEU: 3022*e4b17023SJohn Marino PUT_CODE (cond, EQ); 3023*e4b17023SJohn Marino value = 2; 3024*e4b17023SJohn Marino break; 3025*e4b17023SJohn Marino 3026*e4b17023SJohn Marino case GT: 3027*e4b17023SJohn Marino case GTU: 3028*e4b17023SJohn Marino PUT_CODE (cond, NE); 3029*e4b17023SJohn Marino value = 2; 3030*e4b17023SJohn Marino break; 3031*e4b17023SJohn Marino 3032*e4b17023SJohn Marino default: 3033*e4b17023SJohn Marino break; 3034*e4b17023SJohn Marino } 3035*e4b17023SJohn Marino 3036*e4b17023SJohn Marino if (cc_status.flags & CC_NO_OVERFLOW) 3037*e4b17023SJohn Marino switch (GET_CODE (cond)) 3038*e4b17023SJohn Marino { 3039*e4b17023SJohn Marino case GEU: 3040*e4b17023SJohn Marino /* Jump becomes unconditional. */ 3041*e4b17023SJohn Marino return 1; 3042*e4b17023SJohn Marino 3043*e4b17023SJohn Marino case LEU: 3044*e4b17023SJohn Marino PUT_CODE (cond, EQ); 3045*e4b17023SJohn Marino value = 2; 3046*e4b17023SJohn Marino break; 3047*e4b17023SJohn Marino 3048*e4b17023SJohn Marino case GTU: 3049*e4b17023SJohn Marino PUT_CODE (cond, NE); 3050*e4b17023SJohn Marino value = 2; 3051*e4b17023SJohn Marino break; 3052*e4b17023SJohn Marino 3053*e4b17023SJohn Marino case LTU: 3054*e4b17023SJohn Marino /* Jump becomes no-op. */ 3055*e4b17023SJohn Marino return -1; 3056*e4b17023SJohn Marino 3057*e4b17023SJohn Marino default: 3058*e4b17023SJohn Marino break; 3059*e4b17023SJohn Marino } 3060*e4b17023SJohn Marino 3061*e4b17023SJohn Marino if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N)) 3062*e4b17023SJohn Marino switch (GET_CODE (cond)) 3063*e4b17023SJohn Marino { 3064*e4b17023SJohn Marino default: 3065*e4b17023SJohn Marino gcc_unreachable (); 3066*e4b17023SJohn Marino 3067*e4b17023SJohn Marino case NE: 3068*e4b17023SJohn Marino PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT); 3069*e4b17023SJohn Marino value = 2; 3070*e4b17023SJohn Marino break; 3071*e4b17023SJohn Marino 3072*e4b17023SJohn Marino case EQ: 3073*e4b17023SJohn Marino PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE); 3074*e4b17023SJohn Marino value = 2; 3075*e4b17023SJohn Marino break; 3076*e4b17023SJohn Marino } 3077*e4b17023SJohn Marino 3078*e4b17023SJohn Marino if (cc_status.flags & CC_NOT_SIGNED) 3079*e4b17023SJohn Marino /* The flags are valid if signed condition operators are converted 3080*e4b17023SJohn Marino to unsigned. */ 3081*e4b17023SJohn Marino switch (GET_CODE (cond)) 3082*e4b17023SJohn Marino { 3083*e4b17023SJohn Marino case LE: 3084*e4b17023SJohn Marino PUT_CODE (cond, LEU); 3085*e4b17023SJohn Marino value = 2; 3086*e4b17023SJohn Marino break; 3087*e4b17023SJohn Marino 3088*e4b17023SJohn Marino case LT: 3089*e4b17023SJohn Marino PUT_CODE (cond, LTU); 3090*e4b17023SJohn Marino value = 2; 3091*e4b17023SJohn Marino break; 3092*e4b17023SJohn Marino 3093*e4b17023SJohn Marino case GT: 3094*e4b17023SJohn Marino PUT_CODE (cond, GTU); 3095*e4b17023SJohn Marino value = 2; 3096*e4b17023SJohn Marino break; 3097*e4b17023SJohn Marino 3098*e4b17023SJohn Marino case GE: 3099*e4b17023SJohn Marino PUT_CODE (cond, GEU); 3100*e4b17023SJohn Marino value = 2; 3101*e4b17023SJohn Marino break; 3102*e4b17023SJohn Marino 3103*e4b17023SJohn Marino default: 3104*e4b17023SJohn Marino break; 3105*e4b17023SJohn Marino } 3106*e4b17023SJohn Marino 3107*e4b17023SJohn Marino return value; 3108*e4b17023SJohn Marino } 3109*e4b17023SJohn Marino #endif 3110*e4b17023SJohn Marino 3111*e4b17023SJohn Marino /* Report inconsistency between the assembler template and the operands. 3112*e4b17023SJohn Marino In an `asm', it's the user's fault; otherwise, the compiler's fault. */ 3113*e4b17023SJohn Marino 3114*e4b17023SJohn Marino void 3115*e4b17023SJohn Marino output_operand_lossage (const char *cmsgid, ...) 3116*e4b17023SJohn Marino { 3117*e4b17023SJohn Marino char *fmt_string; 3118*e4b17023SJohn Marino char *new_message; 3119*e4b17023SJohn Marino const char *pfx_str; 3120*e4b17023SJohn Marino va_list ap; 3121*e4b17023SJohn Marino 3122*e4b17023SJohn Marino va_start (ap, cmsgid); 3123*e4b17023SJohn Marino 3124*e4b17023SJohn Marino pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: "; 3125*e4b17023SJohn Marino asprintf (&fmt_string, "%s%s", pfx_str, _(cmsgid)); 3126*e4b17023SJohn Marino vasprintf (&new_message, fmt_string, ap); 3127*e4b17023SJohn Marino 3128*e4b17023SJohn Marino if (this_is_asm_operands) 3129*e4b17023SJohn Marino error_for_asm (this_is_asm_operands, "%s", new_message); 3130*e4b17023SJohn Marino else 3131*e4b17023SJohn Marino internal_error ("%s", new_message); 3132*e4b17023SJohn Marino 3133*e4b17023SJohn Marino free (fmt_string); 3134*e4b17023SJohn Marino free (new_message); 3135*e4b17023SJohn Marino va_end (ap); 3136*e4b17023SJohn Marino } 3137*e4b17023SJohn Marino 3138*e4b17023SJohn Marino /* Output of assembler code from a template, and its subroutines. */ 3139*e4b17023SJohn Marino 3140*e4b17023SJohn Marino /* Annotate the assembly with a comment describing the pattern and 3141*e4b17023SJohn Marino alternative used. */ 3142*e4b17023SJohn Marino 3143*e4b17023SJohn Marino static void 3144*e4b17023SJohn Marino output_asm_name (void) 3145*e4b17023SJohn Marino { 3146*e4b17023SJohn Marino if (debug_insn) 3147*e4b17023SJohn Marino { 3148*e4b17023SJohn Marino int num = INSN_CODE (debug_insn); 3149*e4b17023SJohn Marino fprintf (asm_out_file, "\t%s %d\t%s", 3150*e4b17023SJohn Marino ASM_COMMENT_START, INSN_UID (debug_insn), 3151*e4b17023SJohn Marino insn_data[num].name); 3152*e4b17023SJohn Marino if (insn_data[num].n_alternatives > 1) 3153*e4b17023SJohn Marino fprintf (asm_out_file, "/%d", which_alternative + 1); 3154*e4b17023SJohn Marino #ifdef HAVE_ATTR_length 3155*e4b17023SJohn Marino fprintf (asm_out_file, "\t[length = %d]", 3156*e4b17023SJohn Marino get_attr_length (debug_insn)); 3157*e4b17023SJohn Marino #endif 3158*e4b17023SJohn Marino /* Clear this so only the first assembler insn 3159*e4b17023SJohn Marino of any rtl insn will get the special comment for -dp. */ 3160*e4b17023SJohn Marino debug_insn = 0; 3161*e4b17023SJohn Marino } 3162*e4b17023SJohn Marino } 3163*e4b17023SJohn Marino 3164*e4b17023SJohn Marino /* If OP is a REG or MEM and we can find a MEM_EXPR corresponding to it 3165*e4b17023SJohn Marino or its address, return that expr . Set *PADDRESSP to 1 if the expr 3166*e4b17023SJohn Marino corresponds to the address of the object and 0 if to the object. */ 3167*e4b17023SJohn Marino 3168*e4b17023SJohn Marino static tree 3169*e4b17023SJohn Marino get_mem_expr_from_op (rtx op, int *paddressp) 3170*e4b17023SJohn Marino { 3171*e4b17023SJohn Marino tree expr; 3172*e4b17023SJohn Marino int inner_addressp; 3173*e4b17023SJohn Marino 3174*e4b17023SJohn Marino *paddressp = 0; 3175*e4b17023SJohn Marino 3176*e4b17023SJohn Marino if (REG_P (op)) 3177*e4b17023SJohn Marino return REG_EXPR (op); 3178*e4b17023SJohn Marino else if (!MEM_P (op)) 3179*e4b17023SJohn Marino return 0; 3180*e4b17023SJohn Marino 3181*e4b17023SJohn Marino if (MEM_EXPR (op) != 0) 3182*e4b17023SJohn Marino return MEM_EXPR (op); 3183*e4b17023SJohn Marino 3184*e4b17023SJohn Marino /* Otherwise we have an address, so indicate it and look at the address. */ 3185*e4b17023SJohn Marino *paddressp = 1; 3186*e4b17023SJohn Marino op = XEXP (op, 0); 3187*e4b17023SJohn Marino 3188*e4b17023SJohn Marino /* First check if we have a decl for the address, then look at the right side 3189*e4b17023SJohn Marino if it is a PLUS. Otherwise, strip off arithmetic and keep looking. 3190*e4b17023SJohn Marino But don't allow the address to itself be indirect. */ 3191*e4b17023SJohn Marino if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp) 3192*e4b17023SJohn Marino return expr; 3193*e4b17023SJohn Marino else if (GET_CODE (op) == PLUS 3194*e4b17023SJohn Marino && (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp))) 3195*e4b17023SJohn Marino return expr; 3196*e4b17023SJohn Marino 3197*e4b17023SJohn Marino while (UNARY_P (op) 3198*e4b17023SJohn Marino || GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH) 3199*e4b17023SJohn Marino op = XEXP (op, 0); 3200*e4b17023SJohn Marino 3201*e4b17023SJohn Marino expr = get_mem_expr_from_op (op, &inner_addressp); 3202*e4b17023SJohn Marino return inner_addressp ? 0 : expr; 3203*e4b17023SJohn Marino } 3204*e4b17023SJohn Marino 3205*e4b17023SJohn Marino /* Output operand names for assembler instructions. OPERANDS is the 3206*e4b17023SJohn Marino operand vector, OPORDER is the order to write the operands, and NOPS 3207*e4b17023SJohn Marino is the number of operands to write. */ 3208*e4b17023SJohn Marino 3209*e4b17023SJohn Marino static void 3210*e4b17023SJohn Marino output_asm_operand_names (rtx *operands, int *oporder, int nops) 3211*e4b17023SJohn Marino { 3212*e4b17023SJohn Marino int wrote = 0; 3213*e4b17023SJohn Marino int i; 3214*e4b17023SJohn Marino 3215*e4b17023SJohn Marino for (i = 0; i < nops; i++) 3216*e4b17023SJohn Marino { 3217*e4b17023SJohn Marino int addressp; 3218*e4b17023SJohn Marino rtx op = operands[oporder[i]]; 3219*e4b17023SJohn Marino tree expr = get_mem_expr_from_op (op, &addressp); 3220*e4b17023SJohn Marino 3221*e4b17023SJohn Marino fprintf (asm_out_file, "%c%s", 3222*e4b17023SJohn Marino wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START); 3223*e4b17023SJohn Marino wrote = 1; 3224*e4b17023SJohn Marino if (expr) 3225*e4b17023SJohn Marino { 3226*e4b17023SJohn Marino fprintf (asm_out_file, "%s", 3227*e4b17023SJohn Marino addressp ? "*" : ""); 3228*e4b17023SJohn Marino print_mem_expr (asm_out_file, expr); 3229*e4b17023SJohn Marino wrote = 1; 3230*e4b17023SJohn Marino } 3231*e4b17023SJohn Marino else if (REG_P (op) && ORIGINAL_REGNO (op) 3232*e4b17023SJohn Marino && ORIGINAL_REGNO (op) != REGNO (op)) 3233*e4b17023SJohn Marino fprintf (asm_out_file, " tmp%i", ORIGINAL_REGNO (op)); 3234*e4b17023SJohn Marino } 3235*e4b17023SJohn Marino } 3236*e4b17023SJohn Marino 3237*e4b17023SJohn Marino /* Output text from TEMPLATE to the assembler output file, 3238*e4b17023SJohn Marino obeying %-directions to substitute operands taken from 3239*e4b17023SJohn Marino the vector OPERANDS. 3240*e4b17023SJohn Marino 3241*e4b17023SJohn Marino %N (for N a digit) means print operand N in usual manner. 3242*e4b17023SJohn Marino %lN means require operand N to be a CODE_LABEL or LABEL_REF 3243*e4b17023SJohn Marino and print the label name with no punctuation. 3244*e4b17023SJohn Marino %cN means require operand N to be a constant 3245*e4b17023SJohn Marino and print the constant expression with no punctuation. 3246*e4b17023SJohn Marino %aN means expect operand N to be a memory address 3247*e4b17023SJohn Marino (not a memory reference!) and print a reference 3248*e4b17023SJohn Marino to that address. 3249*e4b17023SJohn Marino %nN means expect operand N to be a constant 3250*e4b17023SJohn Marino and print a constant expression for minus the value 3251*e4b17023SJohn Marino of the operand, with no other punctuation. */ 3252*e4b17023SJohn Marino 3253*e4b17023SJohn Marino void 3254*e4b17023SJohn Marino output_asm_insn (const char *templ, rtx *operands) 3255*e4b17023SJohn Marino { 3256*e4b17023SJohn Marino const char *p; 3257*e4b17023SJohn Marino int c; 3258*e4b17023SJohn Marino #ifdef ASSEMBLER_DIALECT 3259*e4b17023SJohn Marino int dialect = 0; 3260*e4b17023SJohn Marino #endif 3261*e4b17023SJohn Marino int oporder[MAX_RECOG_OPERANDS]; 3262*e4b17023SJohn Marino char opoutput[MAX_RECOG_OPERANDS]; 3263*e4b17023SJohn Marino int ops = 0; 3264*e4b17023SJohn Marino 3265*e4b17023SJohn Marino /* An insn may return a null string template 3266*e4b17023SJohn Marino in a case where no assembler code is needed. */ 3267*e4b17023SJohn Marino if (*templ == 0) 3268*e4b17023SJohn Marino return; 3269*e4b17023SJohn Marino 3270*e4b17023SJohn Marino memset (opoutput, 0, sizeof opoutput); 3271*e4b17023SJohn Marino p = templ; 3272*e4b17023SJohn Marino putc ('\t', asm_out_file); 3273*e4b17023SJohn Marino 3274*e4b17023SJohn Marino #ifdef ASM_OUTPUT_OPCODE 3275*e4b17023SJohn Marino ASM_OUTPUT_OPCODE (asm_out_file, p); 3276*e4b17023SJohn Marino #endif 3277*e4b17023SJohn Marino 3278*e4b17023SJohn Marino while ((c = *p++)) 3279*e4b17023SJohn Marino switch (c) 3280*e4b17023SJohn Marino { 3281*e4b17023SJohn Marino case '\n': 3282*e4b17023SJohn Marino if (flag_verbose_asm) 3283*e4b17023SJohn Marino output_asm_operand_names (operands, oporder, ops); 3284*e4b17023SJohn Marino if (flag_print_asm_name) 3285*e4b17023SJohn Marino output_asm_name (); 3286*e4b17023SJohn Marino 3287*e4b17023SJohn Marino ops = 0; 3288*e4b17023SJohn Marino memset (opoutput, 0, sizeof opoutput); 3289*e4b17023SJohn Marino 3290*e4b17023SJohn Marino putc (c, asm_out_file); 3291*e4b17023SJohn Marino #ifdef ASM_OUTPUT_OPCODE 3292*e4b17023SJohn Marino while ((c = *p) == '\t') 3293*e4b17023SJohn Marino { 3294*e4b17023SJohn Marino putc (c, asm_out_file); 3295*e4b17023SJohn Marino p++; 3296*e4b17023SJohn Marino } 3297*e4b17023SJohn Marino ASM_OUTPUT_OPCODE (asm_out_file, p); 3298*e4b17023SJohn Marino #endif 3299*e4b17023SJohn Marino break; 3300*e4b17023SJohn Marino 3301*e4b17023SJohn Marino #ifdef ASSEMBLER_DIALECT 3302*e4b17023SJohn Marino case '{': 3303*e4b17023SJohn Marino { 3304*e4b17023SJohn Marino int i; 3305*e4b17023SJohn Marino 3306*e4b17023SJohn Marino if (dialect) 3307*e4b17023SJohn Marino output_operand_lossage ("nested assembly dialect alternatives"); 3308*e4b17023SJohn Marino else 3309*e4b17023SJohn Marino dialect = 1; 3310*e4b17023SJohn Marino 3311*e4b17023SJohn Marino /* If we want the first dialect, do nothing. Otherwise, skip 3312*e4b17023SJohn Marino DIALECT_NUMBER of strings ending with '|'. */ 3313*e4b17023SJohn Marino for (i = 0; i < dialect_number; i++) 3314*e4b17023SJohn Marino { 3315*e4b17023SJohn Marino while (*p && *p != '}' && *p++ != '|') 3316*e4b17023SJohn Marino ; 3317*e4b17023SJohn Marino if (*p == '}') 3318*e4b17023SJohn Marino break; 3319*e4b17023SJohn Marino if (*p == '|') 3320*e4b17023SJohn Marino p++; 3321*e4b17023SJohn Marino } 3322*e4b17023SJohn Marino 3323*e4b17023SJohn Marino if (*p == '\0') 3324*e4b17023SJohn Marino output_operand_lossage ("unterminated assembly dialect alternative"); 3325*e4b17023SJohn Marino } 3326*e4b17023SJohn Marino break; 3327*e4b17023SJohn Marino 3328*e4b17023SJohn Marino case '|': 3329*e4b17023SJohn Marino if (dialect) 3330*e4b17023SJohn Marino { 3331*e4b17023SJohn Marino /* Skip to close brace. */ 3332*e4b17023SJohn Marino do 3333*e4b17023SJohn Marino { 3334*e4b17023SJohn Marino if (*p == '\0') 3335*e4b17023SJohn Marino { 3336*e4b17023SJohn Marino output_operand_lossage ("unterminated assembly dialect alternative"); 3337*e4b17023SJohn Marino break; 3338*e4b17023SJohn Marino } 3339*e4b17023SJohn Marino } 3340*e4b17023SJohn Marino while (*p++ != '}'); 3341*e4b17023SJohn Marino dialect = 0; 3342*e4b17023SJohn Marino } 3343*e4b17023SJohn Marino else 3344*e4b17023SJohn Marino putc (c, asm_out_file); 3345*e4b17023SJohn Marino break; 3346*e4b17023SJohn Marino 3347*e4b17023SJohn Marino case '}': 3348*e4b17023SJohn Marino if (! dialect) 3349*e4b17023SJohn Marino putc (c, asm_out_file); 3350*e4b17023SJohn Marino dialect = 0; 3351*e4b17023SJohn Marino break; 3352*e4b17023SJohn Marino #endif 3353*e4b17023SJohn Marino 3354*e4b17023SJohn Marino case '%': 3355*e4b17023SJohn Marino /* %% outputs a single %. */ 3356*e4b17023SJohn Marino if (*p == '%') 3357*e4b17023SJohn Marino { 3358*e4b17023SJohn Marino p++; 3359*e4b17023SJohn Marino putc (c, asm_out_file); 3360*e4b17023SJohn Marino } 3361*e4b17023SJohn Marino /* %= outputs a number which is unique to each insn in the entire 3362*e4b17023SJohn Marino compilation. This is useful for making local labels that are 3363*e4b17023SJohn Marino referred to more than once in a given insn. */ 3364*e4b17023SJohn Marino else if (*p == '=') 3365*e4b17023SJohn Marino { 3366*e4b17023SJohn Marino p++; 3367*e4b17023SJohn Marino fprintf (asm_out_file, "%d", insn_counter); 3368*e4b17023SJohn Marino } 3369*e4b17023SJohn Marino /* % followed by a letter and some digits 3370*e4b17023SJohn Marino outputs an operand in a special way depending on the letter. 3371*e4b17023SJohn Marino Letters `acln' are implemented directly. 3372*e4b17023SJohn Marino Other letters are passed to `output_operand' so that 3373*e4b17023SJohn Marino the TARGET_PRINT_OPERAND hook can define them. */ 3374*e4b17023SJohn Marino else if (ISALPHA (*p)) 3375*e4b17023SJohn Marino { 3376*e4b17023SJohn Marino int letter = *p++; 3377*e4b17023SJohn Marino unsigned long opnum; 3378*e4b17023SJohn Marino char *endptr; 3379*e4b17023SJohn Marino 3380*e4b17023SJohn Marino opnum = strtoul (p, &endptr, 10); 3381*e4b17023SJohn Marino 3382*e4b17023SJohn Marino if (endptr == p) 3383*e4b17023SJohn Marino output_operand_lossage ("operand number missing " 3384*e4b17023SJohn Marino "after %%-letter"); 3385*e4b17023SJohn Marino else if (this_is_asm_operands && opnum >= insn_noperands) 3386*e4b17023SJohn Marino output_operand_lossage ("operand number out of range"); 3387*e4b17023SJohn Marino else if (letter == 'l') 3388*e4b17023SJohn Marino output_asm_label (operands[opnum]); 3389*e4b17023SJohn Marino else if (letter == 'a') 3390*e4b17023SJohn Marino output_address (operands[opnum]); 3391*e4b17023SJohn Marino else if (letter == 'c') 3392*e4b17023SJohn Marino { 3393*e4b17023SJohn Marino if (CONSTANT_ADDRESS_P (operands[opnum])) 3394*e4b17023SJohn Marino output_addr_const (asm_out_file, operands[opnum]); 3395*e4b17023SJohn Marino else 3396*e4b17023SJohn Marino output_operand (operands[opnum], 'c'); 3397*e4b17023SJohn Marino } 3398*e4b17023SJohn Marino else if (letter == 'n') 3399*e4b17023SJohn Marino { 3400*e4b17023SJohn Marino if (CONST_INT_P (operands[opnum])) 3401*e4b17023SJohn Marino fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, 3402*e4b17023SJohn Marino - INTVAL (operands[opnum])); 3403*e4b17023SJohn Marino else 3404*e4b17023SJohn Marino { 3405*e4b17023SJohn Marino putc ('-', asm_out_file); 3406*e4b17023SJohn Marino output_addr_const (asm_out_file, operands[opnum]); 3407*e4b17023SJohn Marino } 3408*e4b17023SJohn Marino } 3409*e4b17023SJohn Marino else 3410*e4b17023SJohn Marino output_operand (operands[opnum], letter); 3411*e4b17023SJohn Marino 3412*e4b17023SJohn Marino if (!opoutput[opnum]) 3413*e4b17023SJohn Marino oporder[ops++] = opnum; 3414*e4b17023SJohn Marino opoutput[opnum] = 1; 3415*e4b17023SJohn Marino 3416*e4b17023SJohn Marino p = endptr; 3417*e4b17023SJohn Marino c = *p; 3418*e4b17023SJohn Marino } 3419*e4b17023SJohn Marino /* % followed by a digit outputs an operand the default way. */ 3420*e4b17023SJohn Marino else if (ISDIGIT (*p)) 3421*e4b17023SJohn Marino { 3422*e4b17023SJohn Marino unsigned long opnum; 3423*e4b17023SJohn Marino char *endptr; 3424*e4b17023SJohn Marino 3425*e4b17023SJohn Marino opnum = strtoul (p, &endptr, 10); 3426*e4b17023SJohn Marino if (this_is_asm_operands && opnum >= insn_noperands) 3427*e4b17023SJohn Marino output_operand_lossage ("operand number out of range"); 3428*e4b17023SJohn Marino else 3429*e4b17023SJohn Marino output_operand (operands[opnum], 0); 3430*e4b17023SJohn Marino 3431*e4b17023SJohn Marino if (!opoutput[opnum]) 3432*e4b17023SJohn Marino oporder[ops++] = opnum; 3433*e4b17023SJohn Marino opoutput[opnum] = 1; 3434*e4b17023SJohn Marino 3435*e4b17023SJohn Marino p = endptr; 3436*e4b17023SJohn Marino c = *p; 3437*e4b17023SJohn Marino } 3438*e4b17023SJohn Marino /* % followed by punctuation: output something for that 3439*e4b17023SJohn Marino punctuation character alone, with no operand. The 3440*e4b17023SJohn Marino TARGET_PRINT_OPERAND hook decides what is actually done. */ 3441*e4b17023SJohn Marino else if (targetm.asm_out.print_operand_punct_valid_p ((unsigned char) *p)) 3442*e4b17023SJohn Marino output_operand (NULL_RTX, *p++); 3443*e4b17023SJohn Marino else 3444*e4b17023SJohn Marino output_operand_lossage ("invalid %%-code"); 3445*e4b17023SJohn Marino break; 3446*e4b17023SJohn Marino 3447*e4b17023SJohn Marino default: 3448*e4b17023SJohn Marino putc (c, asm_out_file); 3449*e4b17023SJohn Marino } 3450*e4b17023SJohn Marino 3451*e4b17023SJohn Marino /* Write out the variable names for operands, if we know them. */ 3452*e4b17023SJohn Marino if (flag_verbose_asm) 3453*e4b17023SJohn Marino output_asm_operand_names (operands, oporder, ops); 3454*e4b17023SJohn Marino if (flag_print_asm_name) 3455*e4b17023SJohn Marino output_asm_name (); 3456*e4b17023SJohn Marino 3457*e4b17023SJohn Marino putc ('\n', asm_out_file); 3458*e4b17023SJohn Marino } 3459*e4b17023SJohn Marino 3460*e4b17023SJohn Marino /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ 3461*e4b17023SJohn Marino 3462*e4b17023SJohn Marino void 3463*e4b17023SJohn Marino output_asm_label (rtx x) 3464*e4b17023SJohn Marino { 3465*e4b17023SJohn Marino char buf[256]; 3466*e4b17023SJohn Marino 3467*e4b17023SJohn Marino if (GET_CODE (x) == LABEL_REF) 3468*e4b17023SJohn Marino x = XEXP (x, 0); 3469*e4b17023SJohn Marino if (LABEL_P (x) 3470*e4b17023SJohn Marino || (NOTE_P (x) 3471*e4b17023SJohn Marino && NOTE_KIND (x) == NOTE_INSN_DELETED_LABEL)) 3472*e4b17023SJohn Marino ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 3473*e4b17023SJohn Marino else 3474*e4b17023SJohn Marino output_operand_lossage ("'%%l' operand isn't a label"); 3475*e4b17023SJohn Marino 3476*e4b17023SJohn Marino assemble_name (asm_out_file, buf); 3477*e4b17023SJohn Marino } 3478*e4b17023SJohn Marino 3479*e4b17023SJohn Marino /* Helper rtx-iteration-function for mark_symbol_refs_as_used and 3480*e4b17023SJohn Marino output_operand. Marks SYMBOL_REFs as referenced through use of 3481*e4b17023SJohn Marino assemble_external. */ 3482*e4b17023SJohn Marino 3483*e4b17023SJohn Marino static int 3484*e4b17023SJohn Marino mark_symbol_ref_as_used (rtx *xp, void *dummy ATTRIBUTE_UNUSED) 3485*e4b17023SJohn Marino { 3486*e4b17023SJohn Marino rtx x = *xp; 3487*e4b17023SJohn Marino 3488*e4b17023SJohn Marino /* If we have a used symbol, we may have to emit assembly 3489*e4b17023SJohn Marino annotations corresponding to whether the symbol is external, weak 3490*e4b17023SJohn Marino or has non-default visibility. */ 3491*e4b17023SJohn Marino if (GET_CODE (x) == SYMBOL_REF) 3492*e4b17023SJohn Marino { 3493*e4b17023SJohn Marino tree t; 3494*e4b17023SJohn Marino 3495*e4b17023SJohn Marino t = SYMBOL_REF_DECL (x); 3496*e4b17023SJohn Marino if (t) 3497*e4b17023SJohn Marino assemble_external (t); 3498*e4b17023SJohn Marino 3499*e4b17023SJohn Marino return -1; 3500*e4b17023SJohn Marino } 3501*e4b17023SJohn Marino 3502*e4b17023SJohn Marino return 0; 3503*e4b17023SJohn Marino } 3504*e4b17023SJohn Marino 3505*e4b17023SJohn Marino /* Marks SYMBOL_REFs in x as referenced through use of assemble_external. */ 3506*e4b17023SJohn Marino 3507*e4b17023SJohn Marino void 3508*e4b17023SJohn Marino mark_symbol_refs_as_used (rtx x) 3509*e4b17023SJohn Marino { 3510*e4b17023SJohn Marino for_each_rtx (&x, mark_symbol_ref_as_used, NULL); 3511*e4b17023SJohn Marino } 3512*e4b17023SJohn Marino 3513*e4b17023SJohn Marino /* Print operand X using machine-dependent assembler syntax. 3514*e4b17023SJohn Marino CODE is a non-digit that preceded the operand-number in the % spec, 3515*e4b17023SJohn Marino such as 'z' if the spec was `%z3'. CODE is 0 if there was no char 3516*e4b17023SJohn Marino between the % and the digits. 3517*e4b17023SJohn Marino When CODE is a non-letter, X is 0. 3518*e4b17023SJohn Marino 3519*e4b17023SJohn Marino The meanings of the letters are machine-dependent and controlled 3520*e4b17023SJohn Marino by TARGET_PRINT_OPERAND. */ 3521*e4b17023SJohn Marino 3522*e4b17023SJohn Marino void 3523*e4b17023SJohn Marino output_operand (rtx x, int code ATTRIBUTE_UNUSED) 3524*e4b17023SJohn Marino { 3525*e4b17023SJohn Marino if (x && GET_CODE (x) == SUBREG) 3526*e4b17023SJohn Marino x = alter_subreg (&x); 3527*e4b17023SJohn Marino 3528*e4b17023SJohn Marino /* X must not be a pseudo reg. */ 3529*e4b17023SJohn Marino gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER); 3530*e4b17023SJohn Marino 3531*e4b17023SJohn Marino targetm.asm_out.print_operand (asm_out_file, x, code); 3532*e4b17023SJohn Marino 3533*e4b17023SJohn Marino if (x == NULL_RTX) 3534*e4b17023SJohn Marino return; 3535*e4b17023SJohn Marino 3536*e4b17023SJohn Marino for_each_rtx (&x, mark_symbol_ref_as_used, NULL); 3537*e4b17023SJohn Marino } 3538*e4b17023SJohn Marino 3539*e4b17023SJohn Marino /* Print a memory reference operand for address X using 3540*e4b17023SJohn Marino machine-dependent assembler syntax. */ 3541*e4b17023SJohn Marino 3542*e4b17023SJohn Marino void 3543*e4b17023SJohn Marino output_address (rtx x) 3544*e4b17023SJohn Marino { 3545*e4b17023SJohn Marino bool changed = false; 3546*e4b17023SJohn Marino walk_alter_subreg (&x, &changed); 3547*e4b17023SJohn Marino targetm.asm_out.print_operand_address (asm_out_file, x); 3548*e4b17023SJohn Marino } 3549*e4b17023SJohn Marino 3550*e4b17023SJohn Marino /* Print an integer constant expression in assembler syntax. 3551*e4b17023SJohn Marino Addition and subtraction are the only arithmetic 3552*e4b17023SJohn Marino that may appear in these expressions. */ 3553*e4b17023SJohn Marino 3554*e4b17023SJohn Marino void 3555*e4b17023SJohn Marino output_addr_const (FILE *file, rtx x) 3556*e4b17023SJohn Marino { 3557*e4b17023SJohn Marino char buf[256]; 3558*e4b17023SJohn Marino 3559*e4b17023SJohn Marino restart: 3560*e4b17023SJohn Marino switch (GET_CODE (x)) 3561*e4b17023SJohn Marino { 3562*e4b17023SJohn Marino case PC: 3563*e4b17023SJohn Marino putc ('.', file); 3564*e4b17023SJohn Marino break; 3565*e4b17023SJohn Marino 3566*e4b17023SJohn Marino case SYMBOL_REF: 3567*e4b17023SJohn Marino if (SYMBOL_REF_DECL (x)) 3568*e4b17023SJohn Marino assemble_external (SYMBOL_REF_DECL (x)); 3569*e4b17023SJohn Marino #ifdef ASM_OUTPUT_SYMBOL_REF 3570*e4b17023SJohn Marino ASM_OUTPUT_SYMBOL_REF (file, x); 3571*e4b17023SJohn Marino #else 3572*e4b17023SJohn Marino assemble_name (file, XSTR (x, 0)); 3573*e4b17023SJohn Marino #endif 3574*e4b17023SJohn Marino break; 3575*e4b17023SJohn Marino 3576*e4b17023SJohn Marino case LABEL_REF: 3577*e4b17023SJohn Marino x = XEXP (x, 0); 3578*e4b17023SJohn Marino /* Fall through. */ 3579*e4b17023SJohn Marino case CODE_LABEL: 3580*e4b17023SJohn Marino ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 3581*e4b17023SJohn Marino #ifdef ASM_OUTPUT_LABEL_REF 3582*e4b17023SJohn Marino ASM_OUTPUT_LABEL_REF (file, buf); 3583*e4b17023SJohn Marino #else 3584*e4b17023SJohn Marino assemble_name (file, buf); 3585*e4b17023SJohn Marino #endif 3586*e4b17023SJohn Marino break; 3587*e4b17023SJohn Marino 3588*e4b17023SJohn Marino case CONST_INT: 3589*e4b17023SJohn Marino fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 3590*e4b17023SJohn Marino break; 3591*e4b17023SJohn Marino 3592*e4b17023SJohn Marino case CONST: 3593*e4b17023SJohn Marino /* This used to output parentheses around the expression, 3594*e4b17023SJohn Marino but that does not work on the 386 (either ATT or BSD assembler). */ 3595*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 0)); 3596*e4b17023SJohn Marino break; 3597*e4b17023SJohn Marino 3598*e4b17023SJohn Marino case CONST_DOUBLE: 3599*e4b17023SJohn Marino if (GET_MODE (x) == VOIDmode) 3600*e4b17023SJohn Marino { 3601*e4b17023SJohn Marino /* We can use %d if the number is one word and positive. */ 3602*e4b17023SJohn Marino if (CONST_DOUBLE_HIGH (x)) 3603*e4b17023SJohn Marino fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX, 3604*e4b17023SJohn Marino (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x), 3605*e4b17023SJohn Marino (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x)); 3606*e4b17023SJohn Marino else if (CONST_DOUBLE_LOW (x) < 0) 3607*e4b17023SJohn Marino fprintf (file, HOST_WIDE_INT_PRINT_HEX, 3608*e4b17023SJohn Marino (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x)); 3609*e4b17023SJohn Marino else 3610*e4b17023SJohn Marino fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x)); 3611*e4b17023SJohn Marino } 3612*e4b17023SJohn Marino else 3613*e4b17023SJohn Marino /* We can't handle floating point constants; 3614*e4b17023SJohn Marino PRINT_OPERAND must handle them. */ 3615*e4b17023SJohn Marino output_operand_lossage ("floating constant misused"); 3616*e4b17023SJohn Marino break; 3617*e4b17023SJohn Marino 3618*e4b17023SJohn Marino case CONST_FIXED: 3619*e4b17023SJohn Marino fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_FIXED_VALUE_LOW (x)); 3620*e4b17023SJohn Marino break; 3621*e4b17023SJohn Marino 3622*e4b17023SJohn Marino case PLUS: 3623*e4b17023SJohn Marino /* Some assemblers need integer constants to appear last (eg masm). */ 3624*e4b17023SJohn Marino if (CONST_INT_P (XEXP (x, 0))) 3625*e4b17023SJohn Marino { 3626*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 1)); 3627*e4b17023SJohn Marino if (INTVAL (XEXP (x, 0)) >= 0) 3628*e4b17023SJohn Marino fprintf (file, "+"); 3629*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 0)); 3630*e4b17023SJohn Marino } 3631*e4b17023SJohn Marino else 3632*e4b17023SJohn Marino { 3633*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 0)); 3634*e4b17023SJohn Marino if (!CONST_INT_P (XEXP (x, 1)) 3635*e4b17023SJohn Marino || INTVAL (XEXP (x, 1)) >= 0) 3636*e4b17023SJohn Marino fprintf (file, "+"); 3637*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 1)); 3638*e4b17023SJohn Marino } 3639*e4b17023SJohn Marino break; 3640*e4b17023SJohn Marino 3641*e4b17023SJohn Marino case MINUS: 3642*e4b17023SJohn Marino /* Avoid outputting things like x-x or x+5-x, 3643*e4b17023SJohn Marino since some assemblers can't handle that. */ 3644*e4b17023SJohn Marino x = simplify_subtraction (x); 3645*e4b17023SJohn Marino if (GET_CODE (x) != MINUS) 3646*e4b17023SJohn Marino goto restart; 3647*e4b17023SJohn Marino 3648*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 0)); 3649*e4b17023SJohn Marino fprintf (file, "-"); 3650*e4b17023SJohn Marino if ((CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0) 3651*e4b17023SJohn Marino || GET_CODE (XEXP (x, 1)) == PC 3652*e4b17023SJohn Marino || GET_CODE (XEXP (x, 1)) == SYMBOL_REF) 3653*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 1)); 3654*e4b17023SJohn Marino else 3655*e4b17023SJohn Marino { 3656*e4b17023SJohn Marino fputs (targetm.asm_out.open_paren, file); 3657*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 1)); 3658*e4b17023SJohn Marino fputs (targetm.asm_out.close_paren, file); 3659*e4b17023SJohn Marino } 3660*e4b17023SJohn Marino break; 3661*e4b17023SJohn Marino 3662*e4b17023SJohn Marino case ZERO_EXTEND: 3663*e4b17023SJohn Marino case SIGN_EXTEND: 3664*e4b17023SJohn Marino case SUBREG: 3665*e4b17023SJohn Marino case TRUNCATE: 3666*e4b17023SJohn Marino output_addr_const (file, XEXP (x, 0)); 3667*e4b17023SJohn Marino break; 3668*e4b17023SJohn Marino 3669*e4b17023SJohn Marino default: 3670*e4b17023SJohn Marino if (targetm.asm_out.output_addr_const_extra (file, x)) 3671*e4b17023SJohn Marino break; 3672*e4b17023SJohn Marino 3673*e4b17023SJohn Marino output_operand_lossage ("invalid expression as operand"); 3674*e4b17023SJohn Marino } 3675*e4b17023SJohn Marino } 3676*e4b17023SJohn Marino 3677*e4b17023SJohn Marino /* Output a quoted string. */ 3678*e4b17023SJohn Marino 3679*e4b17023SJohn Marino void 3680*e4b17023SJohn Marino output_quoted_string (FILE *asm_file, const char *string) 3681*e4b17023SJohn Marino { 3682*e4b17023SJohn Marino #ifdef OUTPUT_QUOTED_STRING 3683*e4b17023SJohn Marino OUTPUT_QUOTED_STRING (asm_file, string); 3684*e4b17023SJohn Marino #else 3685*e4b17023SJohn Marino char c; 3686*e4b17023SJohn Marino 3687*e4b17023SJohn Marino putc ('\"', asm_file); 3688*e4b17023SJohn Marino while ((c = *string++) != 0) 3689*e4b17023SJohn Marino { 3690*e4b17023SJohn Marino if (ISPRINT (c)) 3691*e4b17023SJohn Marino { 3692*e4b17023SJohn Marino if (c == '\"' || c == '\\') 3693*e4b17023SJohn Marino putc ('\\', asm_file); 3694*e4b17023SJohn Marino putc (c, asm_file); 3695*e4b17023SJohn Marino } 3696*e4b17023SJohn Marino else 3697*e4b17023SJohn Marino fprintf (asm_file, "\\%03o", (unsigned char) c); 3698*e4b17023SJohn Marino } 3699*e4b17023SJohn Marino putc ('\"', asm_file); 3700*e4b17023SJohn Marino #endif 3701*e4b17023SJohn Marino } 3702*e4b17023SJohn Marino 3703*e4b17023SJohn Marino /* Write a HOST_WIDE_INT number in hex form 0x1234, fast. */ 3704*e4b17023SJohn Marino 3705*e4b17023SJohn Marino void 3706*e4b17023SJohn Marino fprint_whex (FILE *f, unsigned HOST_WIDE_INT value) 3707*e4b17023SJohn Marino { 3708*e4b17023SJohn Marino char buf[2 + CHAR_BIT * sizeof (value) / 4]; 3709*e4b17023SJohn Marino if (value == 0) 3710*e4b17023SJohn Marino putc ('0', f); 3711*e4b17023SJohn Marino else 3712*e4b17023SJohn Marino { 3713*e4b17023SJohn Marino char *p = buf + sizeof (buf); 3714*e4b17023SJohn Marino do 3715*e4b17023SJohn Marino *--p = "0123456789abcdef"[value % 16]; 3716*e4b17023SJohn Marino while ((value /= 16) != 0); 3717*e4b17023SJohn Marino *--p = 'x'; 3718*e4b17023SJohn Marino *--p = '0'; 3719*e4b17023SJohn Marino fwrite (p, 1, buf + sizeof (buf) - p, f); 3720*e4b17023SJohn Marino } 3721*e4b17023SJohn Marino } 3722*e4b17023SJohn Marino 3723*e4b17023SJohn Marino /* Internal function that prints an unsigned long in decimal in reverse. 3724*e4b17023SJohn Marino The output string IS NOT null-terminated. */ 3725*e4b17023SJohn Marino 3726*e4b17023SJohn Marino static int 3727*e4b17023SJohn Marino sprint_ul_rev (char *s, unsigned long value) 3728*e4b17023SJohn Marino { 3729*e4b17023SJohn Marino int i = 0; 3730*e4b17023SJohn Marino do 3731*e4b17023SJohn Marino { 3732*e4b17023SJohn Marino s[i] = "0123456789"[value % 10]; 3733*e4b17023SJohn Marino value /= 10; 3734*e4b17023SJohn Marino i++; 3735*e4b17023SJohn Marino /* alternate version, without modulo */ 3736*e4b17023SJohn Marino /* oldval = value; */ 3737*e4b17023SJohn Marino /* value /= 10; */ 3738*e4b17023SJohn Marino /* s[i] = "0123456789" [oldval - 10*value]; */ 3739*e4b17023SJohn Marino /* i++ */ 3740*e4b17023SJohn Marino } 3741*e4b17023SJohn Marino while (value != 0); 3742*e4b17023SJohn Marino return i; 3743*e4b17023SJohn Marino } 3744*e4b17023SJohn Marino 3745*e4b17023SJohn Marino /* Write an unsigned long as decimal to a file, fast. */ 3746*e4b17023SJohn Marino 3747*e4b17023SJohn Marino void 3748*e4b17023SJohn Marino fprint_ul (FILE *f, unsigned long value) 3749*e4b17023SJohn Marino { 3750*e4b17023SJohn Marino /* python says: len(str(2**64)) == 20 */ 3751*e4b17023SJohn Marino char s[20]; 3752*e4b17023SJohn Marino int i; 3753*e4b17023SJohn Marino 3754*e4b17023SJohn Marino i = sprint_ul_rev (s, value); 3755*e4b17023SJohn Marino 3756*e4b17023SJohn Marino /* It's probably too small to bother with string reversal and fputs. */ 3757*e4b17023SJohn Marino do 3758*e4b17023SJohn Marino { 3759*e4b17023SJohn Marino i--; 3760*e4b17023SJohn Marino putc (s[i], f); 3761*e4b17023SJohn Marino } 3762*e4b17023SJohn Marino while (i != 0); 3763*e4b17023SJohn Marino } 3764*e4b17023SJohn Marino 3765*e4b17023SJohn Marino /* Write an unsigned long as decimal to a string, fast. 3766*e4b17023SJohn Marino s must be wide enough to not overflow, at least 21 chars. 3767*e4b17023SJohn Marino Returns the length of the string (without terminating '\0'). */ 3768*e4b17023SJohn Marino 3769*e4b17023SJohn Marino int 3770*e4b17023SJohn Marino sprint_ul (char *s, unsigned long value) 3771*e4b17023SJohn Marino { 3772*e4b17023SJohn Marino int len; 3773*e4b17023SJohn Marino char tmp_c; 3774*e4b17023SJohn Marino int i; 3775*e4b17023SJohn Marino int j; 3776*e4b17023SJohn Marino 3777*e4b17023SJohn Marino len = sprint_ul_rev (s, value); 3778*e4b17023SJohn Marino s[len] = '\0'; 3779*e4b17023SJohn Marino 3780*e4b17023SJohn Marino /* Reverse the string. */ 3781*e4b17023SJohn Marino i = 0; 3782*e4b17023SJohn Marino j = len - 1; 3783*e4b17023SJohn Marino while (i < j) 3784*e4b17023SJohn Marino { 3785*e4b17023SJohn Marino tmp_c = s[i]; 3786*e4b17023SJohn Marino s[i] = s[j]; 3787*e4b17023SJohn Marino s[j] = tmp_c; 3788*e4b17023SJohn Marino i++; j--; 3789*e4b17023SJohn Marino } 3790*e4b17023SJohn Marino 3791*e4b17023SJohn Marino return len; 3792*e4b17023SJohn Marino } 3793*e4b17023SJohn Marino 3794*e4b17023SJohn Marino /* A poor man's fprintf, with the added features of %I, %R, %L, and %U. 3795*e4b17023SJohn Marino %R prints the value of REGISTER_PREFIX. 3796*e4b17023SJohn Marino %L prints the value of LOCAL_LABEL_PREFIX. 3797*e4b17023SJohn Marino %U prints the value of USER_LABEL_PREFIX. 3798*e4b17023SJohn Marino %I prints the value of IMMEDIATE_PREFIX. 3799*e4b17023SJohn Marino %O runs ASM_OUTPUT_OPCODE to transform what follows in the string. 3800*e4b17023SJohn Marino Also supported are %d, %i, %u, %x, %X, %o, %c, %s and %%. 3801*e4b17023SJohn Marino 3802*e4b17023SJohn Marino We handle alternate assembler dialects here, just like output_asm_insn. */ 3803*e4b17023SJohn Marino 3804*e4b17023SJohn Marino void 3805*e4b17023SJohn Marino asm_fprintf (FILE *file, const char *p, ...) 3806*e4b17023SJohn Marino { 3807*e4b17023SJohn Marino char buf[10]; 3808*e4b17023SJohn Marino char *q, c; 3809*e4b17023SJohn Marino va_list argptr; 3810*e4b17023SJohn Marino 3811*e4b17023SJohn Marino va_start (argptr, p); 3812*e4b17023SJohn Marino 3813*e4b17023SJohn Marino buf[0] = '%'; 3814*e4b17023SJohn Marino 3815*e4b17023SJohn Marino while ((c = *p++)) 3816*e4b17023SJohn Marino switch (c) 3817*e4b17023SJohn Marino { 3818*e4b17023SJohn Marino #ifdef ASSEMBLER_DIALECT 3819*e4b17023SJohn Marino case '{': 3820*e4b17023SJohn Marino { 3821*e4b17023SJohn Marino int i; 3822*e4b17023SJohn Marino 3823*e4b17023SJohn Marino /* If we want the first dialect, do nothing. Otherwise, skip 3824*e4b17023SJohn Marino DIALECT_NUMBER of strings ending with '|'. */ 3825*e4b17023SJohn Marino for (i = 0; i < dialect_number; i++) 3826*e4b17023SJohn Marino { 3827*e4b17023SJohn Marino while (*p && *p++ != '|') 3828*e4b17023SJohn Marino ; 3829*e4b17023SJohn Marino 3830*e4b17023SJohn Marino if (*p == '|') 3831*e4b17023SJohn Marino p++; 3832*e4b17023SJohn Marino } 3833*e4b17023SJohn Marino } 3834*e4b17023SJohn Marino break; 3835*e4b17023SJohn Marino 3836*e4b17023SJohn Marino case '|': 3837*e4b17023SJohn Marino /* Skip to close brace. */ 3838*e4b17023SJohn Marino while (*p && *p++ != '}') 3839*e4b17023SJohn Marino ; 3840*e4b17023SJohn Marino break; 3841*e4b17023SJohn Marino 3842*e4b17023SJohn Marino case '}': 3843*e4b17023SJohn Marino break; 3844*e4b17023SJohn Marino #endif 3845*e4b17023SJohn Marino 3846*e4b17023SJohn Marino case '%': 3847*e4b17023SJohn Marino c = *p++; 3848*e4b17023SJohn Marino q = &buf[1]; 3849*e4b17023SJohn Marino while (strchr ("-+ #0", c)) 3850*e4b17023SJohn Marino { 3851*e4b17023SJohn Marino *q++ = c; 3852*e4b17023SJohn Marino c = *p++; 3853*e4b17023SJohn Marino } 3854*e4b17023SJohn Marino while (ISDIGIT (c) || c == '.') 3855*e4b17023SJohn Marino { 3856*e4b17023SJohn Marino *q++ = c; 3857*e4b17023SJohn Marino c = *p++; 3858*e4b17023SJohn Marino } 3859*e4b17023SJohn Marino switch (c) 3860*e4b17023SJohn Marino { 3861*e4b17023SJohn Marino case '%': 3862*e4b17023SJohn Marino putc ('%', file); 3863*e4b17023SJohn Marino break; 3864*e4b17023SJohn Marino 3865*e4b17023SJohn Marino case 'd': case 'i': case 'u': 3866*e4b17023SJohn Marino case 'x': case 'X': case 'o': 3867*e4b17023SJohn Marino case 'c': 3868*e4b17023SJohn Marino *q++ = c; 3869*e4b17023SJohn Marino *q = 0; 3870*e4b17023SJohn Marino fprintf (file, buf, va_arg (argptr, int)); 3871*e4b17023SJohn Marino break; 3872*e4b17023SJohn Marino 3873*e4b17023SJohn Marino case 'w': 3874*e4b17023SJohn Marino /* This is a prefix to the 'd', 'i', 'u', 'x', 'X', and 3875*e4b17023SJohn Marino 'o' cases, but we do not check for those cases. It 3876*e4b17023SJohn Marino means that the value is a HOST_WIDE_INT, which may be 3877*e4b17023SJohn Marino either `long' or `long long'. */ 3878*e4b17023SJohn Marino memcpy (q, HOST_WIDE_INT_PRINT, strlen (HOST_WIDE_INT_PRINT)); 3879*e4b17023SJohn Marino q += strlen (HOST_WIDE_INT_PRINT); 3880*e4b17023SJohn Marino *q++ = *p++; 3881*e4b17023SJohn Marino *q = 0; 3882*e4b17023SJohn Marino fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT)); 3883*e4b17023SJohn Marino break; 3884*e4b17023SJohn Marino 3885*e4b17023SJohn Marino case 'l': 3886*e4b17023SJohn Marino *q++ = c; 3887*e4b17023SJohn Marino #ifdef HAVE_LONG_LONG 3888*e4b17023SJohn Marino if (*p == 'l') 3889*e4b17023SJohn Marino { 3890*e4b17023SJohn Marino *q++ = *p++; 3891*e4b17023SJohn Marino *q++ = *p++; 3892*e4b17023SJohn Marino *q = 0; 3893*e4b17023SJohn Marino fprintf (file, buf, va_arg (argptr, long long)); 3894*e4b17023SJohn Marino } 3895*e4b17023SJohn Marino else 3896*e4b17023SJohn Marino #endif 3897*e4b17023SJohn Marino { 3898*e4b17023SJohn Marino *q++ = *p++; 3899*e4b17023SJohn Marino *q = 0; 3900*e4b17023SJohn Marino fprintf (file, buf, va_arg (argptr, long)); 3901*e4b17023SJohn Marino } 3902*e4b17023SJohn Marino 3903*e4b17023SJohn Marino break; 3904*e4b17023SJohn Marino 3905*e4b17023SJohn Marino case 's': 3906*e4b17023SJohn Marino *q++ = c; 3907*e4b17023SJohn Marino *q = 0; 3908*e4b17023SJohn Marino fprintf (file, buf, va_arg (argptr, char *)); 3909*e4b17023SJohn Marino break; 3910*e4b17023SJohn Marino 3911*e4b17023SJohn Marino case 'O': 3912*e4b17023SJohn Marino #ifdef ASM_OUTPUT_OPCODE 3913*e4b17023SJohn Marino ASM_OUTPUT_OPCODE (asm_out_file, p); 3914*e4b17023SJohn Marino #endif 3915*e4b17023SJohn Marino break; 3916*e4b17023SJohn Marino 3917*e4b17023SJohn Marino case 'R': 3918*e4b17023SJohn Marino #ifdef REGISTER_PREFIX 3919*e4b17023SJohn Marino fprintf (file, "%s", REGISTER_PREFIX); 3920*e4b17023SJohn Marino #endif 3921*e4b17023SJohn Marino break; 3922*e4b17023SJohn Marino 3923*e4b17023SJohn Marino case 'I': 3924*e4b17023SJohn Marino #ifdef IMMEDIATE_PREFIX 3925*e4b17023SJohn Marino fprintf (file, "%s", IMMEDIATE_PREFIX); 3926*e4b17023SJohn Marino #endif 3927*e4b17023SJohn Marino break; 3928*e4b17023SJohn Marino 3929*e4b17023SJohn Marino case 'L': 3930*e4b17023SJohn Marino #ifdef LOCAL_LABEL_PREFIX 3931*e4b17023SJohn Marino fprintf (file, "%s", LOCAL_LABEL_PREFIX); 3932*e4b17023SJohn Marino #endif 3933*e4b17023SJohn Marino break; 3934*e4b17023SJohn Marino 3935*e4b17023SJohn Marino case 'U': 3936*e4b17023SJohn Marino fputs (user_label_prefix, file); 3937*e4b17023SJohn Marino break; 3938*e4b17023SJohn Marino 3939*e4b17023SJohn Marino #ifdef ASM_FPRINTF_EXTENSIONS 3940*e4b17023SJohn Marino /* Uppercase letters are reserved for general use by asm_fprintf 3941*e4b17023SJohn Marino and so are not available to target specific code. In order to 3942*e4b17023SJohn Marino prevent the ASM_FPRINTF_EXTENSIONS macro from using them then, 3943*e4b17023SJohn Marino they are defined here. As they get turned into real extensions 3944*e4b17023SJohn Marino to asm_fprintf they should be removed from this list. */ 3945*e4b17023SJohn Marino case 'A': case 'B': case 'C': case 'D': case 'E': 3946*e4b17023SJohn Marino case 'F': case 'G': case 'H': case 'J': case 'K': 3947*e4b17023SJohn Marino case 'M': case 'N': case 'P': case 'Q': case 'S': 3948*e4b17023SJohn Marino case 'T': case 'V': case 'W': case 'Y': case 'Z': 3949*e4b17023SJohn Marino break; 3950*e4b17023SJohn Marino 3951*e4b17023SJohn Marino ASM_FPRINTF_EXTENSIONS (file, argptr, p) 3952*e4b17023SJohn Marino #endif 3953*e4b17023SJohn Marino default: 3954*e4b17023SJohn Marino gcc_unreachable (); 3955*e4b17023SJohn Marino } 3956*e4b17023SJohn Marino break; 3957*e4b17023SJohn Marino 3958*e4b17023SJohn Marino default: 3959*e4b17023SJohn Marino putc (c, file); 3960*e4b17023SJohn Marino } 3961*e4b17023SJohn Marino va_end (argptr); 3962*e4b17023SJohn Marino } 3963*e4b17023SJohn Marino 3964*e4b17023SJohn Marino /* Split up a CONST_DOUBLE or integer constant rtx 3965*e4b17023SJohn Marino into two rtx's for single words, 3966*e4b17023SJohn Marino storing in *FIRST the word that comes first in memory in the target 3967*e4b17023SJohn Marino and in *SECOND the other. */ 3968*e4b17023SJohn Marino 3969*e4b17023SJohn Marino void 3970*e4b17023SJohn Marino split_double (rtx value, rtx *first, rtx *second) 3971*e4b17023SJohn Marino { 3972*e4b17023SJohn Marino if (CONST_INT_P (value)) 3973*e4b17023SJohn Marino { 3974*e4b17023SJohn Marino if (HOST_BITS_PER_WIDE_INT >= (2 * BITS_PER_WORD)) 3975*e4b17023SJohn Marino { 3976*e4b17023SJohn Marino /* In this case the CONST_INT holds both target words. 3977*e4b17023SJohn Marino Extract the bits from it into two word-sized pieces. 3978*e4b17023SJohn Marino Sign extend each half to HOST_WIDE_INT. */ 3979*e4b17023SJohn Marino unsigned HOST_WIDE_INT low, high; 3980*e4b17023SJohn Marino unsigned HOST_WIDE_INT mask, sign_bit, sign_extend; 3981*e4b17023SJohn Marino unsigned bits_per_word = BITS_PER_WORD; 3982*e4b17023SJohn Marino 3983*e4b17023SJohn Marino /* Set sign_bit to the most significant bit of a word. */ 3984*e4b17023SJohn Marino sign_bit = 1; 3985*e4b17023SJohn Marino sign_bit <<= bits_per_word - 1; 3986*e4b17023SJohn Marino 3987*e4b17023SJohn Marino /* Set mask so that all bits of the word are set. We could 3988*e4b17023SJohn Marino have used 1 << BITS_PER_WORD instead of basing the 3989*e4b17023SJohn Marino calculation on sign_bit. However, on machines where 3990*e4b17023SJohn Marino HOST_BITS_PER_WIDE_INT == BITS_PER_WORD, it could cause a 3991*e4b17023SJohn Marino compiler warning, even though the code would never be 3992*e4b17023SJohn Marino executed. */ 3993*e4b17023SJohn Marino mask = sign_bit << 1; 3994*e4b17023SJohn Marino mask--; 3995*e4b17023SJohn Marino 3996*e4b17023SJohn Marino /* Set sign_extend as any remaining bits. */ 3997*e4b17023SJohn Marino sign_extend = ~mask; 3998*e4b17023SJohn Marino 3999*e4b17023SJohn Marino /* Pick the lower word and sign-extend it. */ 4000*e4b17023SJohn Marino low = INTVAL (value); 4001*e4b17023SJohn Marino low &= mask; 4002*e4b17023SJohn Marino if (low & sign_bit) 4003*e4b17023SJohn Marino low |= sign_extend; 4004*e4b17023SJohn Marino 4005*e4b17023SJohn Marino /* Pick the higher word, shifted to the least significant 4006*e4b17023SJohn Marino bits, and sign-extend it. */ 4007*e4b17023SJohn Marino high = INTVAL (value); 4008*e4b17023SJohn Marino high >>= bits_per_word - 1; 4009*e4b17023SJohn Marino high >>= 1; 4010*e4b17023SJohn Marino high &= mask; 4011*e4b17023SJohn Marino if (high & sign_bit) 4012*e4b17023SJohn Marino high |= sign_extend; 4013*e4b17023SJohn Marino 4014*e4b17023SJohn Marino /* Store the words in the target machine order. */ 4015*e4b17023SJohn Marino if (WORDS_BIG_ENDIAN) 4016*e4b17023SJohn Marino { 4017*e4b17023SJohn Marino *first = GEN_INT (high); 4018*e4b17023SJohn Marino *second = GEN_INT (low); 4019*e4b17023SJohn Marino } 4020*e4b17023SJohn Marino else 4021*e4b17023SJohn Marino { 4022*e4b17023SJohn Marino *first = GEN_INT (low); 4023*e4b17023SJohn Marino *second = GEN_INT (high); 4024*e4b17023SJohn Marino } 4025*e4b17023SJohn Marino } 4026*e4b17023SJohn Marino else 4027*e4b17023SJohn Marino { 4028*e4b17023SJohn Marino /* The rule for using CONST_INT for a wider mode 4029*e4b17023SJohn Marino is that we regard the value as signed. 4030*e4b17023SJohn Marino So sign-extend it. */ 4031*e4b17023SJohn Marino rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx); 4032*e4b17023SJohn Marino if (WORDS_BIG_ENDIAN) 4033*e4b17023SJohn Marino { 4034*e4b17023SJohn Marino *first = high; 4035*e4b17023SJohn Marino *second = value; 4036*e4b17023SJohn Marino } 4037*e4b17023SJohn Marino else 4038*e4b17023SJohn Marino { 4039*e4b17023SJohn Marino *first = value; 4040*e4b17023SJohn Marino *second = high; 4041*e4b17023SJohn Marino } 4042*e4b17023SJohn Marino } 4043*e4b17023SJohn Marino } 4044*e4b17023SJohn Marino else if (GET_CODE (value) != CONST_DOUBLE) 4045*e4b17023SJohn Marino { 4046*e4b17023SJohn Marino if (WORDS_BIG_ENDIAN) 4047*e4b17023SJohn Marino { 4048*e4b17023SJohn Marino *first = const0_rtx; 4049*e4b17023SJohn Marino *second = value; 4050*e4b17023SJohn Marino } 4051*e4b17023SJohn Marino else 4052*e4b17023SJohn Marino { 4053*e4b17023SJohn Marino *first = value; 4054*e4b17023SJohn Marino *second = const0_rtx; 4055*e4b17023SJohn Marino } 4056*e4b17023SJohn Marino } 4057*e4b17023SJohn Marino else if (GET_MODE (value) == VOIDmode 4058*e4b17023SJohn Marino /* This is the old way we did CONST_DOUBLE integers. */ 4059*e4b17023SJohn Marino || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT) 4060*e4b17023SJohn Marino { 4061*e4b17023SJohn Marino /* In an integer, the words are defined as most and least significant. 4062*e4b17023SJohn Marino So order them by the target's convention. */ 4063*e4b17023SJohn Marino if (WORDS_BIG_ENDIAN) 4064*e4b17023SJohn Marino { 4065*e4b17023SJohn Marino *first = GEN_INT (CONST_DOUBLE_HIGH (value)); 4066*e4b17023SJohn Marino *second = GEN_INT (CONST_DOUBLE_LOW (value)); 4067*e4b17023SJohn Marino } 4068*e4b17023SJohn Marino else 4069*e4b17023SJohn Marino { 4070*e4b17023SJohn Marino *first = GEN_INT (CONST_DOUBLE_LOW (value)); 4071*e4b17023SJohn Marino *second = GEN_INT (CONST_DOUBLE_HIGH (value)); 4072*e4b17023SJohn Marino } 4073*e4b17023SJohn Marino } 4074*e4b17023SJohn Marino else 4075*e4b17023SJohn Marino { 4076*e4b17023SJohn Marino REAL_VALUE_TYPE r; 4077*e4b17023SJohn Marino long l[2]; 4078*e4b17023SJohn Marino REAL_VALUE_FROM_CONST_DOUBLE (r, value); 4079*e4b17023SJohn Marino 4080*e4b17023SJohn Marino /* Note, this converts the REAL_VALUE_TYPE to the target's 4081*e4b17023SJohn Marino format, splits up the floating point double and outputs 4082*e4b17023SJohn Marino exactly 32 bits of it into each of l[0] and l[1] -- 4083*e4b17023SJohn Marino not necessarily BITS_PER_WORD bits. */ 4084*e4b17023SJohn Marino REAL_VALUE_TO_TARGET_DOUBLE (r, l); 4085*e4b17023SJohn Marino 4086*e4b17023SJohn Marino /* If 32 bits is an entire word for the target, but not for the host, 4087*e4b17023SJohn Marino then sign-extend on the host so that the number will look the same 4088*e4b17023SJohn Marino way on the host that it would on the target. See for instance 4089*e4b17023SJohn Marino simplify_unary_operation. The #if is needed to avoid compiler 4090*e4b17023SJohn Marino warnings. */ 4091*e4b17023SJohn Marino 4092*e4b17023SJohn Marino #if HOST_BITS_PER_LONG > 32 4093*e4b17023SJohn Marino if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32) 4094*e4b17023SJohn Marino { 4095*e4b17023SJohn Marino if (l[0] & ((long) 1 << 31)) 4096*e4b17023SJohn Marino l[0] |= ((long) (-1) << 32); 4097*e4b17023SJohn Marino if (l[1] & ((long) 1 << 31)) 4098*e4b17023SJohn Marino l[1] |= ((long) (-1) << 32); 4099*e4b17023SJohn Marino } 4100*e4b17023SJohn Marino #endif 4101*e4b17023SJohn Marino 4102*e4b17023SJohn Marino *first = GEN_INT (l[0]); 4103*e4b17023SJohn Marino *second = GEN_INT (l[1]); 4104*e4b17023SJohn Marino } 4105*e4b17023SJohn Marino } 4106*e4b17023SJohn Marino 4107*e4b17023SJohn Marino /* Return nonzero if this function has no function calls. */ 4108*e4b17023SJohn Marino 4109*e4b17023SJohn Marino int 4110*e4b17023SJohn Marino leaf_function_p (void) 4111*e4b17023SJohn Marino { 4112*e4b17023SJohn Marino rtx insn; 4113*e4b17023SJohn Marino rtx link; 4114*e4b17023SJohn Marino 4115*e4b17023SJohn Marino if (crtl->profile || profile_arc_flag) 4116*e4b17023SJohn Marino return 0; 4117*e4b17023SJohn Marino 4118*e4b17023SJohn Marino for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 4119*e4b17023SJohn Marino { 4120*e4b17023SJohn Marino if (CALL_P (insn) 4121*e4b17023SJohn Marino && ! SIBLING_CALL_P (insn)) 4122*e4b17023SJohn Marino return 0; 4123*e4b17023SJohn Marino if (NONJUMP_INSN_P (insn) 4124*e4b17023SJohn Marino && GET_CODE (PATTERN (insn)) == SEQUENCE 4125*e4b17023SJohn Marino && CALL_P (XVECEXP (PATTERN (insn), 0, 0)) 4126*e4b17023SJohn Marino && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0))) 4127*e4b17023SJohn Marino return 0; 4128*e4b17023SJohn Marino } 4129*e4b17023SJohn Marino for (link = crtl->epilogue_delay_list; 4130*e4b17023SJohn Marino link; 4131*e4b17023SJohn Marino link = XEXP (link, 1)) 4132*e4b17023SJohn Marino { 4133*e4b17023SJohn Marino insn = XEXP (link, 0); 4134*e4b17023SJohn Marino 4135*e4b17023SJohn Marino if (CALL_P (insn) 4136*e4b17023SJohn Marino && ! SIBLING_CALL_P (insn)) 4137*e4b17023SJohn Marino return 0; 4138*e4b17023SJohn Marino if (NONJUMP_INSN_P (insn) 4139*e4b17023SJohn Marino && GET_CODE (PATTERN (insn)) == SEQUENCE 4140*e4b17023SJohn Marino && CALL_P (XVECEXP (PATTERN (insn), 0, 0)) 4141*e4b17023SJohn Marino && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0))) 4142*e4b17023SJohn Marino return 0; 4143*e4b17023SJohn Marino } 4144*e4b17023SJohn Marino 4145*e4b17023SJohn Marino return 1; 4146*e4b17023SJohn Marino } 4147*e4b17023SJohn Marino 4148*e4b17023SJohn Marino /* Return 1 if branch is a forward branch. 4149*e4b17023SJohn Marino Uses insn_shuid array, so it works only in the final pass. May be used by 4150*e4b17023SJohn Marino output templates to customary add branch prediction hints. 4151*e4b17023SJohn Marino */ 4152*e4b17023SJohn Marino int 4153*e4b17023SJohn Marino final_forward_branch_p (rtx insn) 4154*e4b17023SJohn Marino { 4155*e4b17023SJohn Marino int insn_id, label_id; 4156*e4b17023SJohn Marino 4157*e4b17023SJohn Marino gcc_assert (uid_shuid); 4158*e4b17023SJohn Marino insn_id = INSN_SHUID (insn); 4159*e4b17023SJohn Marino label_id = INSN_SHUID (JUMP_LABEL (insn)); 4160*e4b17023SJohn Marino /* We've hit some insns that does not have id information available. */ 4161*e4b17023SJohn Marino gcc_assert (insn_id && label_id); 4162*e4b17023SJohn Marino return insn_id < label_id; 4163*e4b17023SJohn Marino } 4164*e4b17023SJohn Marino 4165*e4b17023SJohn Marino /* On some machines, a function with no call insns 4166*e4b17023SJohn Marino can run faster if it doesn't create its own register window. 4167*e4b17023SJohn Marino When output, the leaf function should use only the "output" 4168*e4b17023SJohn Marino registers. Ordinarily, the function would be compiled to use 4169*e4b17023SJohn Marino the "input" registers to find its arguments; it is a candidate 4170*e4b17023SJohn Marino for leaf treatment if it uses only the "input" registers. 4171*e4b17023SJohn Marino Leaf function treatment means renumbering so the function 4172*e4b17023SJohn Marino uses the "output" registers instead. */ 4173*e4b17023SJohn Marino 4174*e4b17023SJohn Marino #ifdef LEAF_REGISTERS 4175*e4b17023SJohn Marino 4176*e4b17023SJohn Marino /* Return 1 if this function uses only the registers that can be 4177*e4b17023SJohn Marino safely renumbered. */ 4178*e4b17023SJohn Marino 4179*e4b17023SJohn Marino int 4180*e4b17023SJohn Marino only_leaf_regs_used (void) 4181*e4b17023SJohn Marino { 4182*e4b17023SJohn Marino int i; 4183*e4b17023SJohn Marino const char *const permitted_reg_in_leaf_functions = LEAF_REGISTERS; 4184*e4b17023SJohn Marino 4185*e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 4186*e4b17023SJohn Marino if ((df_regs_ever_live_p (i) || global_regs[i]) 4187*e4b17023SJohn Marino && ! permitted_reg_in_leaf_functions[i]) 4188*e4b17023SJohn Marino return 0; 4189*e4b17023SJohn Marino 4190*e4b17023SJohn Marino if (crtl->uses_pic_offset_table 4191*e4b17023SJohn Marino && pic_offset_table_rtx != 0 4192*e4b17023SJohn Marino && REG_P (pic_offset_table_rtx) 4193*e4b17023SJohn Marino && ! permitted_reg_in_leaf_functions[REGNO (pic_offset_table_rtx)]) 4194*e4b17023SJohn Marino return 0; 4195*e4b17023SJohn Marino 4196*e4b17023SJohn Marino return 1; 4197*e4b17023SJohn Marino } 4198*e4b17023SJohn Marino 4199*e4b17023SJohn Marino /* Scan all instructions and renumber all registers into those 4200*e4b17023SJohn Marino available in leaf functions. */ 4201*e4b17023SJohn Marino 4202*e4b17023SJohn Marino static void 4203*e4b17023SJohn Marino leaf_renumber_regs (rtx first) 4204*e4b17023SJohn Marino { 4205*e4b17023SJohn Marino rtx insn; 4206*e4b17023SJohn Marino 4207*e4b17023SJohn Marino /* Renumber only the actual patterns. 4208*e4b17023SJohn Marino The reg-notes can contain frame pointer refs, 4209*e4b17023SJohn Marino and renumbering them could crash, and should not be needed. */ 4210*e4b17023SJohn Marino for (insn = first; insn; insn = NEXT_INSN (insn)) 4211*e4b17023SJohn Marino if (INSN_P (insn)) 4212*e4b17023SJohn Marino leaf_renumber_regs_insn (PATTERN (insn)); 4213*e4b17023SJohn Marino for (insn = crtl->epilogue_delay_list; 4214*e4b17023SJohn Marino insn; 4215*e4b17023SJohn Marino insn = XEXP (insn, 1)) 4216*e4b17023SJohn Marino if (INSN_P (XEXP (insn, 0))) 4217*e4b17023SJohn Marino leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0))); 4218*e4b17023SJohn Marino } 4219*e4b17023SJohn Marino 4220*e4b17023SJohn Marino /* Scan IN_RTX and its subexpressions, and renumber all regs into those 4221*e4b17023SJohn Marino available in leaf functions. */ 4222*e4b17023SJohn Marino 4223*e4b17023SJohn Marino void 4224*e4b17023SJohn Marino leaf_renumber_regs_insn (rtx in_rtx) 4225*e4b17023SJohn Marino { 4226*e4b17023SJohn Marino int i, j; 4227*e4b17023SJohn Marino const char *format_ptr; 4228*e4b17023SJohn Marino 4229*e4b17023SJohn Marino if (in_rtx == 0) 4230*e4b17023SJohn Marino return; 4231*e4b17023SJohn Marino 4232*e4b17023SJohn Marino /* Renumber all input-registers into output-registers. 4233*e4b17023SJohn Marino renumbered_regs would be 1 for an output-register; 4234*e4b17023SJohn Marino they */ 4235*e4b17023SJohn Marino 4236*e4b17023SJohn Marino if (REG_P (in_rtx)) 4237*e4b17023SJohn Marino { 4238*e4b17023SJohn Marino int newreg; 4239*e4b17023SJohn Marino 4240*e4b17023SJohn Marino /* Don't renumber the same reg twice. */ 4241*e4b17023SJohn Marino if (in_rtx->used) 4242*e4b17023SJohn Marino return; 4243*e4b17023SJohn Marino 4244*e4b17023SJohn Marino newreg = REGNO (in_rtx); 4245*e4b17023SJohn Marino /* Don't try to renumber pseudo regs. It is possible for a pseudo reg 4246*e4b17023SJohn Marino to reach here as part of a REG_NOTE. */ 4247*e4b17023SJohn Marino if (newreg >= FIRST_PSEUDO_REGISTER) 4248*e4b17023SJohn Marino { 4249*e4b17023SJohn Marino in_rtx->used = 1; 4250*e4b17023SJohn Marino return; 4251*e4b17023SJohn Marino } 4252*e4b17023SJohn Marino newreg = LEAF_REG_REMAP (newreg); 4253*e4b17023SJohn Marino gcc_assert (newreg >= 0); 4254*e4b17023SJohn Marino df_set_regs_ever_live (REGNO (in_rtx), false); 4255*e4b17023SJohn Marino df_set_regs_ever_live (newreg, true); 4256*e4b17023SJohn Marino SET_REGNO (in_rtx, newreg); 4257*e4b17023SJohn Marino in_rtx->used = 1; 4258*e4b17023SJohn Marino } 4259*e4b17023SJohn Marino 4260*e4b17023SJohn Marino if (INSN_P (in_rtx)) 4261*e4b17023SJohn Marino { 4262*e4b17023SJohn Marino /* Inside a SEQUENCE, we find insns. 4263*e4b17023SJohn Marino Renumber just the patterns of these insns, 4264*e4b17023SJohn Marino just as we do for the top-level insns. */ 4265*e4b17023SJohn Marino leaf_renumber_regs_insn (PATTERN (in_rtx)); 4266*e4b17023SJohn Marino return; 4267*e4b17023SJohn Marino } 4268*e4b17023SJohn Marino 4269*e4b17023SJohn Marino format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); 4270*e4b17023SJohn Marino 4271*e4b17023SJohn Marino for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) 4272*e4b17023SJohn Marino switch (*format_ptr++) 4273*e4b17023SJohn Marino { 4274*e4b17023SJohn Marino case 'e': 4275*e4b17023SJohn Marino leaf_renumber_regs_insn (XEXP (in_rtx, i)); 4276*e4b17023SJohn Marino break; 4277*e4b17023SJohn Marino 4278*e4b17023SJohn Marino case 'E': 4279*e4b17023SJohn Marino if (NULL != XVEC (in_rtx, i)) 4280*e4b17023SJohn Marino { 4281*e4b17023SJohn Marino for (j = 0; j < XVECLEN (in_rtx, i); j++) 4282*e4b17023SJohn Marino leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j)); 4283*e4b17023SJohn Marino } 4284*e4b17023SJohn Marino break; 4285*e4b17023SJohn Marino 4286*e4b17023SJohn Marino case 'S': 4287*e4b17023SJohn Marino case 's': 4288*e4b17023SJohn Marino case '0': 4289*e4b17023SJohn Marino case 'i': 4290*e4b17023SJohn Marino case 'w': 4291*e4b17023SJohn Marino case 'n': 4292*e4b17023SJohn Marino case 'u': 4293*e4b17023SJohn Marino break; 4294*e4b17023SJohn Marino 4295*e4b17023SJohn Marino default: 4296*e4b17023SJohn Marino gcc_unreachable (); 4297*e4b17023SJohn Marino } 4298*e4b17023SJohn Marino } 4299*e4b17023SJohn Marino #endif 4300*e4b17023SJohn Marino 4301*e4b17023SJohn Marino /* Turn the RTL into assembly. */ 4302*e4b17023SJohn Marino static unsigned int 4303*e4b17023SJohn Marino rest_of_handle_final (void) 4304*e4b17023SJohn Marino { 4305*e4b17023SJohn Marino rtx x; 4306*e4b17023SJohn Marino const char *fnname; 4307*e4b17023SJohn Marino 4308*e4b17023SJohn Marino /* Get the function's name, as described by its RTL. This may be 4309*e4b17023SJohn Marino different from the DECL_NAME name used in the source file. */ 4310*e4b17023SJohn Marino 4311*e4b17023SJohn Marino x = DECL_RTL (current_function_decl); 4312*e4b17023SJohn Marino gcc_assert (MEM_P (x)); 4313*e4b17023SJohn Marino x = XEXP (x, 0); 4314*e4b17023SJohn Marino gcc_assert (GET_CODE (x) == SYMBOL_REF); 4315*e4b17023SJohn Marino fnname = XSTR (x, 0); 4316*e4b17023SJohn Marino 4317*e4b17023SJohn Marino assemble_start_function (current_function_decl, fnname); 4318*e4b17023SJohn Marino final_start_function (get_insns (), asm_out_file, optimize); 4319*e4b17023SJohn Marino final (get_insns (), asm_out_file, optimize); 4320*e4b17023SJohn Marino final_end_function (); 4321*e4b17023SJohn Marino 4322*e4b17023SJohn Marino /* The IA-64 ".handlerdata" directive must be issued before the ".endp" 4323*e4b17023SJohn Marino directive that closes the procedure descriptor. Similarly, for x64 SEH. 4324*e4b17023SJohn Marino Otherwise it's not strictly necessary, but it doesn't hurt either. */ 4325*e4b17023SJohn Marino output_function_exception_table (fnname); 4326*e4b17023SJohn Marino 4327*e4b17023SJohn Marino assemble_end_function (current_function_decl, fnname); 4328*e4b17023SJohn Marino 4329*e4b17023SJohn Marino user_defined_section_attribute = false; 4330*e4b17023SJohn Marino 4331*e4b17023SJohn Marino /* Free up reg info memory. */ 4332*e4b17023SJohn Marino free_reg_info (); 4333*e4b17023SJohn Marino 4334*e4b17023SJohn Marino if (! quiet_flag) 4335*e4b17023SJohn Marino fflush (asm_out_file); 4336*e4b17023SJohn Marino 4337*e4b17023SJohn Marino /* Write DBX symbols if requested. */ 4338*e4b17023SJohn Marino 4339*e4b17023SJohn Marino /* Note that for those inline functions where we don't initially 4340*e4b17023SJohn Marino know for certain that we will be generating an out-of-line copy, 4341*e4b17023SJohn Marino the first invocation of this routine (rest_of_compilation) will 4342*e4b17023SJohn Marino skip over this code by doing a `goto exit_rest_of_compilation;'. 4343*e4b17023SJohn Marino Later on, wrapup_global_declarations will (indirectly) call 4344*e4b17023SJohn Marino rest_of_compilation again for those inline functions that need 4345*e4b17023SJohn Marino to have out-of-line copies generated. During that call, we 4346*e4b17023SJohn Marino *will* be routed past here. */ 4347*e4b17023SJohn Marino 4348*e4b17023SJohn Marino timevar_push (TV_SYMOUT); 4349*e4b17023SJohn Marino if (!DECL_IGNORED_P (current_function_decl)) 4350*e4b17023SJohn Marino debug_hooks->function_decl (current_function_decl); 4351*e4b17023SJohn Marino timevar_pop (TV_SYMOUT); 4352*e4b17023SJohn Marino 4353*e4b17023SJohn Marino /* Release the blocks that are linked to DECL_INITIAL() to free the memory. */ 4354*e4b17023SJohn Marino DECL_INITIAL (current_function_decl) = error_mark_node; 4355*e4b17023SJohn Marino 4356*e4b17023SJohn Marino if (DECL_STATIC_CONSTRUCTOR (current_function_decl) 4357*e4b17023SJohn Marino && targetm.have_ctors_dtors) 4358*e4b17023SJohn Marino targetm.asm_out.constructor (XEXP (DECL_RTL (current_function_decl), 0), 4359*e4b17023SJohn Marino decl_init_priority_lookup 4360*e4b17023SJohn Marino (current_function_decl)); 4361*e4b17023SJohn Marino if (DECL_STATIC_DESTRUCTOR (current_function_decl) 4362*e4b17023SJohn Marino && targetm.have_ctors_dtors) 4363*e4b17023SJohn Marino targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0), 4364*e4b17023SJohn Marino decl_fini_priority_lookup 4365*e4b17023SJohn Marino (current_function_decl)); 4366*e4b17023SJohn Marino return 0; 4367*e4b17023SJohn Marino } 4368*e4b17023SJohn Marino 4369*e4b17023SJohn Marino struct rtl_opt_pass pass_final = 4370*e4b17023SJohn Marino { 4371*e4b17023SJohn Marino { 4372*e4b17023SJohn Marino RTL_PASS, 4373*e4b17023SJohn Marino "final", /* name */ 4374*e4b17023SJohn Marino NULL, /* gate */ 4375*e4b17023SJohn Marino rest_of_handle_final, /* execute */ 4376*e4b17023SJohn Marino NULL, /* sub */ 4377*e4b17023SJohn Marino NULL, /* next */ 4378*e4b17023SJohn Marino 0, /* static_pass_number */ 4379*e4b17023SJohn Marino TV_FINAL, /* tv_id */ 4380*e4b17023SJohn Marino 0, /* properties_required */ 4381*e4b17023SJohn Marino 0, /* properties_provided */ 4382*e4b17023SJohn Marino 0, /* properties_destroyed */ 4383*e4b17023SJohn Marino 0, /* todo_flags_start */ 4384*e4b17023SJohn Marino TODO_ggc_collect /* todo_flags_finish */ 4385*e4b17023SJohn Marino } 4386*e4b17023SJohn Marino }; 4387*e4b17023SJohn Marino 4388*e4b17023SJohn Marino 4389*e4b17023SJohn Marino static unsigned int 4390*e4b17023SJohn Marino rest_of_handle_shorten_branches (void) 4391*e4b17023SJohn Marino { 4392*e4b17023SJohn Marino /* Shorten branches. */ 4393*e4b17023SJohn Marino shorten_branches (get_insns ()); 4394*e4b17023SJohn Marino return 0; 4395*e4b17023SJohn Marino } 4396*e4b17023SJohn Marino 4397*e4b17023SJohn Marino struct rtl_opt_pass pass_shorten_branches = 4398*e4b17023SJohn Marino { 4399*e4b17023SJohn Marino { 4400*e4b17023SJohn Marino RTL_PASS, 4401*e4b17023SJohn Marino "shorten", /* name */ 4402*e4b17023SJohn Marino NULL, /* gate */ 4403*e4b17023SJohn Marino rest_of_handle_shorten_branches, /* execute */ 4404*e4b17023SJohn Marino NULL, /* sub */ 4405*e4b17023SJohn Marino NULL, /* next */ 4406*e4b17023SJohn Marino 0, /* static_pass_number */ 4407*e4b17023SJohn Marino TV_FINAL, /* tv_id */ 4408*e4b17023SJohn Marino 0, /* properties_required */ 4409*e4b17023SJohn Marino 0, /* properties_provided */ 4410*e4b17023SJohn Marino 0, /* properties_destroyed */ 4411*e4b17023SJohn Marino 0, /* todo_flags_start */ 4412*e4b17023SJohn Marino 0 /* todo_flags_finish */ 4413*e4b17023SJohn Marino } 4414*e4b17023SJohn Marino }; 4415*e4b17023SJohn Marino 4416*e4b17023SJohn Marino 4417*e4b17023SJohn Marino static unsigned int 4418*e4b17023SJohn Marino rest_of_clean_state (void) 4419*e4b17023SJohn Marino { 4420*e4b17023SJohn Marino rtx insn, next; 4421*e4b17023SJohn Marino FILE *final_output = NULL; 4422*e4b17023SJohn Marino int save_unnumbered = flag_dump_unnumbered; 4423*e4b17023SJohn Marino int save_noaddr = flag_dump_noaddr; 4424*e4b17023SJohn Marino 4425*e4b17023SJohn Marino if (flag_dump_final_insns) 4426*e4b17023SJohn Marino { 4427*e4b17023SJohn Marino final_output = fopen (flag_dump_final_insns, "a"); 4428*e4b17023SJohn Marino if (!final_output) 4429*e4b17023SJohn Marino { 4430*e4b17023SJohn Marino error ("could not open final insn dump file %qs: %m", 4431*e4b17023SJohn Marino flag_dump_final_insns); 4432*e4b17023SJohn Marino flag_dump_final_insns = NULL; 4433*e4b17023SJohn Marino } 4434*e4b17023SJohn Marino else 4435*e4b17023SJohn Marino { 4436*e4b17023SJohn Marino flag_dump_noaddr = flag_dump_unnumbered = 1; 4437*e4b17023SJohn Marino if (flag_compare_debug_opt || flag_compare_debug) 4438*e4b17023SJohn Marino dump_flags |= TDF_NOUID; 4439*e4b17023SJohn Marino dump_function_header (final_output, current_function_decl, 4440*e4b17023SJohn Marino dump_flags); 4441*e4b17023SJohn Marino final_insns_dump_p = true; 4442*e4b17023SJohn Marino 4443*e4b17023SJohn Marino for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 4444*e4b17023SJohn Marino if (LABEL_P (insn)) 4445*e4b17023SJohn Marino INSN_UID (insn) = CODE_LABEL_NUMBER (insn); 4446*e4b17023SJohn Marino else 4447*e4b17023SJohn Marino { 4448*e4b17023SJohn Marino if (NOTE_P (insn)) 4449*e4b17023SJohn Marino set_block_for_insn (insn, NULL); 4450*e4b17023SJohn Marino INSN_UID (insn) = 0; 4451*e4b17023SJohn Marino } 4452*e4b17023SJohn Marino } 4453*e4b17023SJohn Marino } 4454*e4b17023SJohn Marino 4455*e4b17023SJohn Marino /* It is very important to decompose the RTL instruction chain here: 4456*e4b17023SJohn Marino debug information keeps pointing into CODE_LABEL insns inside the function 4457*e4b17023SJohn Marino body. If these remain pointing to the other insns, we end up preserving 4458*e4b17023SJohn Marino whole RTL chain and attached detailed debug info in memory. */ 4459*e4b17023SJohn Marino for (insn = get_insns (); insn; insn = next) 4460*e4b17023SJohn Marino { 4461*e4b17023SJohn Marino next = NEXT_INSN (insn); 4462*e4b17023SJohn Marino NEXT_INSN (insn) = NULL; 4463*e4b17023SJohn Marino PREV_INSN (insn) = NULL; 4464*e4b17023SJohn Marino 4465*e4b17023SJohn Marino if (final_output 4466*e4b17023SJohn Marino && (!NOTE_P (insn) || 4467*e4b17023SJohn Marino (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION 4468*e4b17023SJohn Marino && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION 4469*e4b17023SJohn Marino && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG 4470*e4b17023SJohn Marino && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END 4471*e4b17023SJohn Marino && NOTE_KIND (insn) != NOTE_INSN_DELETED_DEBUG_LABEL))) 4472*e4b17023SJohn Marino print_rtl_single (final_output, insn); 4473*e4b17023SJohn Marino } 4474*e4b17023SJohn Marino 4475*e4b17023SJohn Marino if (final_output) 4476*e4b17023SJohn Marino { 4477*e4b17023SJohn Marino flag_dump_noaddr = save_noaddr; 4478*e4b17023SJohn Marino flag_dump_unnumbered = save_unnumbered; 4479*e4b17023SJohn Marino final_insns_dump_p = false; 4480*e4b17023SJohn Marino 4481*e4b17023SJohn Marino if (fclose (final_output)) 4482*e4b17023SJohn Marino { 4483*e4b17023SJohn Marino error ("could not close final insn dump file %qs: %m", 4484*e4b17023SJohn Marino flag_dump_final_insns); 4485*e4b17023SJohn Marino flag_dump_final_insns = NULL; 4486*e4b17023SJohn Marino } 4487*e4b17023SJohn Marino } 4488*e4b17023SJohn Marino 4489*e4b17023SJohn Marino /* In case the function was not output, 4490*e4b17023SJohn Marino don't leave any temporary anonymous types 4491*e4b17023SJohn Marino queued up for sdb output. */ 4492*e4b17023SJohn Marino #ifdef SDB_DEBUGGING_INFO 4493*e4b17023SJohn Marino if (write_symbols == SDB_DEBUG) 4494*e4b17023SJohn Marino sdbout_types (NULL_TREE); 4495*e4b17023SJohn Marino #endif 4496*e4b17023SJohn Marino 4497*e4b17023SJohn Marino flag_rerun_cse_after_global_opts = 0; 4498*e4b17023SJohn Marino reload_completed = 0; 4499*e4b17023SJohn Marino epilogue_completed = 0; 4500*e4b17023SJohn Marino #ifdef STACK_REGS 4501*e4b17023SJohn Marino regstack_completed = 0; 4502*e4b17023SJohn Marino #endif 4503*e4b17023SJohn Marino 4504*e4b17023SJohn Marino /* Clear out the insn_length contents now that they are no 4505*e4b17023SJohn Marino longer valid. */ 4506*e4b17023SJohn Marino init_insn_lengths (); 4507*e4b17023SJohn Marino 4508*e4b17023SJohn Marino /* Show no temporary slots allocated. */ 4509*e4b17023SJohn Marino init_temp_slots (); 4510*e4b17023SJohn Marino 4511*e4b17023SJohn Marino free_bb_for_insn (); 4512*e4b17023SJohn Marino 4513*e4b17023SJohn Marino delete_tree_ssa (); 4514*e4b17023SJohn Marino 4515*e4b17023SJohn Marino /* We can reduce stack alignment on call site only when we are sure that 4516*e4b17023SJohn Marino the function body just produced will be actually used in the final 4517*e4b17023SJohn Marino executable. */ 4518*e4b17023SJohn Marino if (decl_binds_to_current_def_p (current_function_decl)) 4519*e4b17023SJohn Marino { 4520*e4b17023SJohn Marino unsigned int pref = crtl->preferred_stack_boundary; 4521*e4b17023SJohn Marino if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary) 4522*e4b17023SJohn Marino pref = crtl->stack_alignment_needed; 4523*e4b17023SJohn Marino cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary 4524*e4b17023SJohn Marino = pref; 4525*e4b17023SJohn Marino } 4526*e4b17023SJohn Marino 4527*e4b17023SJohn Marino /* Make sure volatile mem refs aren't considered valid operands for 4528*e4b17023SJohn Marino arithmetic insns. We must call this here if this is a nested inline 4529*e4b17023SJohn Marino function, since the above code leaves us in the init_recog state, 4530*e4b17023SJohn Marino and the function context push/pop code does not save/restore volatile_ok. 4531*e4b17023SJohn Marino 4532*e4b17023SJohn Marino ??? Maybe it isn't necessary for expand_start_function to call this 4533*e4b17023SJohn Marino anymore if we do it here? */ 4534*e4b17023SJohn Marino 4535*e4b17023SJohn Marino init_recog_no_volatile (); 4536*e4b17023SJohn Marino 4537*e4b17023SJohn Marino /* We're done with this function. Free up memory if we can. */ 4538*e4b17023SJohn Marino free_after_parsing (cfun); 4539*e4b17023SJohn Marino free_after_compilation (cfun); 4540*e4b17023SJohn Marino return 0; 4541*e4b17023SJohn Marino } 4542*e4b17023SJohn Marino 4543*e4b17023SJohn Marino struct rtl_opt_pass pass_clean_state = 4544*e4b17023SJohn Marino { 4545*e4b17023SJohn Marino { 4546*e4b17023SJohn Marino RTL_PASS, 4547*e4b17023SJohn Marino "*clean_state", /* name */ 4548*e4b17023SJohn Marino NULL, /* gate */ 4549*e4b17023SJohn Marino rest_of_clean_state, /* execute */ 4550*e4b17023SJohn Marino NULL, /* sub */ 4551*e4b17023SJohn Marino NULL, /* next */ 4552*e4b17023SJohn Marino 0, /* static_pass_number */ 4553*e4b17023SJohn Marino TV_FINAL, /* tv_id */ 4554*e4b17023SJohn Marino 0, /* properties_required */ 4555*e4b17023SJohn Marino 0, /* properties_provided */ 4556*e4b17023SJohn Marino PROP_rtl, /* properties_destroyed */ 4557*e4b17023SJohn Marino 0, /* todo_flags_start */ 4558*e4b17023SJohn Marino 0 /* todo_flags_finish */ 4559*e4b17023SJohn Marino } 4560*e4b17023SJohn Marino }; 4561