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