X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ffinal.c;h=b59a222001130f3a7d331329f445184f9a1a7509;hp=b25876af6190c3637b4b7bfbfb3faab1df8aba59;hb=f2852046a2c3bac1d4455e33876fc9991e9fc713;hpb=f9567f01d5da105421eb3e672fbf0ae7e28d9d72 diff --git a/gcc/final.c b/gcc/final.c index b25876af619..b59a2220011 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1,13 +1,13 @@ /* Convert RTL to assembler code and output it, for GNU compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* This is the final pass of the compiler. It looks at the rtl code for a function and outputs assembler code. @@ -76,6 +75,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "timevar.h" #include "cgraph.h" #include "coverage.h" +#include "df.h" +#include "vecprim.h" +#include "ggc.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data @@ -107,7 +109,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA /* Is the given character a logical line separator for the assembler? */ #ifndef IS_ASM_LOGICAL_LINE_SEPARATOR -#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == ';') +#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == ';') #endif #ifndef JUMP_TABLES_IN_TEXT_SECTION @@ -135,10 +137,14 @@ static int high_function_linenum; /* Filename of last NOTE. */ static const char *last_filename; +/* Override filename and line number. */ +static const char *override_filename; +static int override_linenum; + /* Whether to force emission of a line note before the next insn. */ static bool force_source_line = false; - -extern int length_unit_log; /* This is defined in insn-attrtab.c. */ + +extern const int length_unit_log; /* This is defined in insn-attrtab.c. */ /* Nonzero while outputting an `asm' with operands. This means that inconsistencies are the user's fault, so don't die. @@ -170,23 +176,6 @@ CC_STATUS cc_status; CC_STATUS cc_prev_status; #endif -/* Indexed by hardware reg number, is 1 if that register is ever - used in the current function. - - In life_analysis, or in stupid_life_analysis, this is set - up to record the hard regs used explicitly. Reload adds - in the hard regs used for holding pseudo regs. Final uses - it to generate the code in the function prologue and epilogue - to save and restore registers as needed. */ - -char regs_ever_live[FIRST_PSEUDO_REGISTER]; - -/* Like regs_ever_live, but 1 if a reg is set or clobbered from an asm. - Unlike regs_ever_live, elements of this array corresponding to - eliminable regs like the frame pointer are set if an asm sets them. */ - -char regs_asm_clobbered[FIRST_PSEUDO_REGISTER]; - /* Nonzero means current function must be given a frame pointer. Initialized in function.c to 0. Set only in reload1.c as per the needs of the function. */ @@ -223,7 +212,7 @@ static int asm_insn_count (rtx); static void profile_function (FILE *); static void profile_after_prologue (FILE *); static bool notice_source_line (rtx); -static rtx walk_alter_subreg (rtx *); +static rtx walk_alter_subreg (rtx *, bool *); static void output_asm_name (void); static void output_alternate_entry_point (FILE *, rtx); static tree get_mem_expr_from_op (rtx, int *); @@ -320,7 +309,7 @@ dbr_sequence_length (void) static int *insn_lengths; -varray_type insn_addresses_; +VEC(int,heap) *insn_addresses_; /* Max uid for which the above arrays are valid. */ static int insn_lengths_max_uid; @@ -380,7 +369,7 @@ init_insn_lengths (void) } /* Obtain the current length of an insn. If branch shortening has been done, - get its actual length. Otherwise, use FALLBACK_FN to calcualte the + get its actual length. Otherwise, use FALLBACK_FN to calculate the length. */ static inline int get_attr_length_1 (rtx insn ATTRIBUTE_UNUSED, @@ -679,7 +668,7 @@ insn_current_reference_address (rtx branch) /* Compute branch alignments based on frequency information in the CFG. */ -static void +static unsigned int compute_alignments (void) { int log, max_skip, max_log; @@ -693,12 +682,11 @@ compute_alignments (void) max_labelno = max_label_num (); min_labelno = get_first_label_num (); - label_align = xcalloc (max_labelno - min_labelno + 1, - sizeof (struct label_alignment)); + label_align = XCNEWVEC (struct label_alignment, max_labelno - min_labelno + 1); /* If not optimizing or optimizing for size, don't assign any alignments. */ if (! optimize || optimize_size) - return; + return 0; FOR_EACH_BB (bb) { @@ -761,6 +749,7 @@ compute_alignments (void) LABEL_TO_ALIGNMENT (label) = max_log; LABEL_TO_MAX_SKIP (label) = max_skip; } + return 0; } struct tree_opt_pass pass_compute_alignments = @@ -816,8 +805,8 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) /* Free uid_shuid before reallocating it. */ free (uid_shuid); - - uid_shuid = xmalloc (max_uid * sizeof *uid_shuid); + + uid_shuid = XNEWVEC (int, max_uid); if (max_labelno != max_label_num ()) { @@ -856,14 +845,9 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) INSN_SHUID (insn) = i++; if (INSN_P (insn)) - { - /* reorg might make the first insn of a loop being run once only, - and delete the label in front of it. Then we want to apply - the loop alignment to the new label created by reorg, which - is separated by the former loop start insn from the - NOTE_INSN_LOOP_BEG. */ - } - else if (LABEL_P (insn)) + continue; + + if (LABEL_P (insn)) { rtx next; @@ -926,20 +910,20 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) #ifdef HAVE_ATTR_length /* Allocate the rest of the arrays. */ - insn_lengths = xmalloc (max_uid * sizeof (*insn_lengths)); + insn_lengths = XNEWVEC (int, max_uid); insn_lengths_max_uid = max_uid; /* Syntax errors can lead to labels being outside of the main insn stream. Initialize insn_addresses, so that we get reproducible results. */ INSN_ADDRESSES_ALLOC (max_uid); - varying_length = xcalloc (max_uid, sizeof (char)); + varying_length = XCNEWVEC (char, max_uid); /* Initialize uid_align. We scan instructions from end to start, and keep in align_tab[n] the last seen insn that does an alignment of at least n+1, i.e. the successor in the alignment chain for an insn that does / has a known alignment of n. */ - uid_align = xcalloc (max_uid, sizeof *uid_align); + uid_align = XCNEWVEC (rtx, max_uid); for (i = MAX_CODE_ALIGN; --i >= 0;) align_tab[i] = NULL_RTX; @@ -1361,16 +1345,83 @@ asm_insn_count (rtx body) if (GET_CODE (body) == ASM_INPUT) template = XSTR (body, 0); else - template = decode_asm_operands (body, NULL, NULL, NULL, NULL); + template = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL); for (; *template; template++) - if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n') + if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template, template) + || *template == '\n') count++; return count; } #endif +/* ??? This is probably the wrong place for these. */ +/* Structure recording the mapping from source file and directory + names at compile time to those to be embedded in debug + information. */ +typedef struct debug_prefix_map +{ + const char *old_prefix; + const char *new_prefix; + size_t old_len; + size_t new_len; + struct debug_prefix_map *next; +} debug_prefix_map; + +/* Linked list of such structures. */ +debug_prefix_map *debug_prefix_maps; + + +/* Record a debug file prefix mapping. ARG is the argument to + -fdebug-prefix-map and must be of the form OLD=NEW. */ + +void +add_debug_prefix_map (const char *arg) +{ + debug_prefix_map *map; + const char *p; + + p = strchr (arg, '='); + if (!p) + { + error ("invalid argument %qs to -fdebug-prefix-map", arg); + return; + } + map = XNEW (debug_prefix_map); + map->old_prefix = ggc_alloc_string (arg, p - arg); + map->old_len = p - arg; + p++; + map->new_prefix = ggc_strdup (p); + map->new_len = strlen (p); + map->next = debug_prefix_maps; + debug_prefix_maps = map; +} + +/* Perform user-specified mapping of debug filename prefixes. Return + the new name corresponding to FILENAME. */ + +const char * +remap_debug_filename (const char *filename) +{ + debug_prefix_map *map; + char *s; + const char *name; + size_t name_len; + + for (map = debug_prefix_maps; map; map = map->next) + if (strncmp (filename, map->old_prefix, map->old_len) == 0) + break; + if (!map) + return filename; + name = filename + map->old_len; + name_len = strlen (name) + 1; + s = (char *) alloca (name_len + map->new_len); + memcpy (s, map->new_prefix, map->new_len); + memcpy (s + map->new_len, name, name_len); + return ggc_strdup (s); +} + /* Output assembler code for the start of a function, and initialize some of the variables in this file for the new function. The label for the function and associated @@ -1422,7 +1473,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, function. */ if (write_symbols) { - remove_unnecessary_notes (); reemit_insn_block_notes (); number_blocks (current_function_decl); /* We never actually put out begin/end notes for the top-level @@ -1478,7 +1528,9 @@ profile_function (FILE *file ATTRIBUTE_UNUSED) #if defined(ASM_OUTPUT_REG_PUSH) if (sval && svrtx != NULL_RTX && REG_P (svrtx)) - ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx)); + { + ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx)); + } #endif #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) @@ -1509,7 +1561,9 @@ profile_function (FILE *file ATTRIBUTE_UNUSED) #if defined(ASM_OUTPUT_REG_PUSH) if (sval && svrtx != NULL_RTX && REG_P (svrtx)) - ASM_OUTPUT_REG_POP (file, REGNO (svrtx)); + { + ASM_OUTPUT_REG_POP (file, REGNO (svrtx)); + } #endif } @@ -1550,33 +1604,6 @@ final (rtx first, FILE *file, int optimize) last_ignored_compare = 0; -#ifdef SDB_DEBUGGING_INFO - /* When producing SDB debugging info, delete troublesome line number - notes from inlined functions in other files as well as duplicate - line number notes. */ - if (write_symbols == SDB_DEBUG) - { - rtx last = 0; - for (insn = first; insn; insn = NEXT_INSN (insn)) - if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0) - { - if (last != 0 -#ifdef USE_MAPPED_LOCATION - && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last) -#else - && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last) - && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last) -#endif - ) - { - delete_insn (insn); /* Use delete_note. */ - continue; - } - last = insn; - } - } -#endif - for (insn = first; insn; insn = NEXT_INSN (insn)) { if (INSN_UID (insn) > max_uid) /* Find largest UID. */ @@ -1600,7 +1627,7 @@ final (rtx first, FILE *file, int optimize) CC_STATUS_INIT; /* Output the insns. */ - for (insn = NEXT_INSN (first); insn;) + for (insn = first; insn;) { #ifdef HAVE_ATTR_length if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ()) @@ -1700,14 +1727,9 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, switch (GET_CODE (insn)) { case NOTE: - switch (NOTE_LINE_NUMBER (insn)) + switch (NOTE_KIND (insn)) { case NOTE_INSN_DELETED: - case NOTE_INSN_LOOP_BEG: - case NOTE_INSN_LOOP_END: - case NOTE_INSN_FUNCTION_END: - case NOTE_INSN_REPEATED_LINE_NUMBER: - case NOTE_INSN_EXPECTED_VALUE: break; case NOTE_INSN_SWITCH_TEXT_SECTIONS: @@ -1715,9 +1737,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, (*debug_hooks->switch_text_section) (); switch_to_section (current_function_section ()); break; - + case NOTE_INSN_BASIC_BLOCK: - #ifdef TARGET_UNWIND_INFO targetm.asm_out.unwind_emit (asm_out_file, insn); #endif @@ -1797,6 +1818,18 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, /* Mark this block as output. */ TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1; } + if (write_symbols == DBX_DEBUG + || write_symbols == SDB_DEBUG) + { + location_t *locus_ptr + = block_nonartificial_location (NOTE_BLOCK (insn)); + + if (locus_ptr != NULL) + { + override_filename = LOCATION_FILE (*locus_ptr); + override_linenum = LOCATION_LINE (*locus_ptr); + } + } break; case NOTE_INSN_BLOCK_END: @@ -1816,6 +1849,24 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, (*debug_hooks->end_block) (high_block_linenum, n); } + if (write_symbols == DBX_DEBUG + || write_symbols == SDB_DEBUG) + { + tree outer_block = BLOCK_SUPERCONTEXT (NOTE_BLOCK (insn)); + location_t *locus_ptr + = block_nonartificial_location (outer_block); + + if (locus_ptr != NULL) + { + override_filename = LOCATION_FILE (*locus_ptr); + override_linenum = LOCATION_LINE (*locus_ptr); + } + else + { + override_filename = NULL; + override_linenum = 0; + } + } break; case NOTE_INSN_DELETED_LABEL: @@ -1829,11 +1880,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, (*debug_hooks->var_location) (insn); break; - case 0: - break; - default: - gcc_assert (NOTE_LINE_NUMBER (insn) > 0); + gcc_unreachable (); break; } break; @@ -1961,6 +2009,10 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, int insn_code_number; const char *template; +#ifdef HAVE_conditional_execution + /* Reset this early so it is correct for ASM statements. */ + current_insn_predicate = NULL_RTX; +#endif /* An INSN, JUMP_INSN or CALL_INSN. First check for special kinds that recog doesn't recognize. */ @@ -2075,12 +2127,27 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, if (string[0]) { + expanded_location loc; + if (! app_on) { fputs (ASM_APP_ON, file); app_on = 1; } +#ifdef USE_MAPPED_LOCATION + loc = expand_location (ASM_INPUT_SOURCE_LOCATION (body)); +#else + loc.file = ASM_INPUT_SOURCE_FILE (body); + loc.line = ASM_INPUT_SOURCE_LINE (body); +#endif + if (*loc.file && loc.line) + fprintf (asm_out_file, "%s %i \"%s\" 1\n", + ASM_COMMENT_START, loc.line, loc.file); fprintf (asm_out_file, "\t%s\n", string); +#if HAVE_AS_LINE_ZERO + if (*loc.file && loc.line) + fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START); +#endif } break; } @@ -2091,15 +2158,18 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, unsigned int noperands = asm_noperands (body); rtx *ops = alloca (noperands * sizeof (rtx)); const char *string; + location_t loc; + expanded_location expanded; /* There's no telling what that did to the condition codes. */ CC_STATUS_INIT; /* Get out the operand values. */ - string = decode_asm_operands (body, ops, NULL, NULL, NULL); + string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc); /* Inhibit dieing on what would otherwise be compiler bugs. */ insn_noperands = noperands; this_is_asm_operands = insn; + expanded = expand_location (loc); #ifdef FINAL_PRESCAN_INSN FINAL_PRESCAN_INSN (insn, ops, insn_noperands); @@ -2113,7 +2183,14 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, fputs (ASM_APP_ON, file); app_on = 1; } + if (expanded.file && expanded.line) + fprintf (asm_out_file, "%s %i \"%s\" 1\n", + ASM_COMMENT_START, expanded.line, expanded.file); output_asm_insn (string, ops); +#if HAVE_AS_LINE_ZERO + if (expanded.file && expanded.line) + fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START); +#endif } this_is_asm_operands = 0; @@ -2275,6 +2352,41 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, INSN_CODE (insn) = -1; } + /* If this is a conditional trap, maybe modify it if the cc's + are in a nonstandard state so that it accomplishes the same + thing that it would do straightforwardly if the cc's were + set up normally. */ + if (cc_status.flags != 0 + && NONJUMP_INSN_P (insn) + && GET_CODE (body) == TRAP_IF + && COMPARISON_P (TRAP_CONDITION (body)) + && XEXP (TRAP_CONDITION (body), 0) == cc0_rtx) + { + /* This function may alter the contents of its argument + and clear some of the cc_status.flags bits. + It may also return 1 meaning condition now always true + or -1 meaning condition now always false + or 2 meaning condition nontrivial but altered. */ + int result = alter_cond (TRAP_CONDITION (body)); + + /* If TRAP_CONDITION has become always false, delete the + instruction. */ + if (result == -1) + { + delete_insn (insn); + break; + } + + /* If TRAP_CONDITION has become always true, replace + TRAP_CONDITION with const_true_rtx. */ + if (result == 1) + TRAP_CONDITION (body) = const_true_rtx; + + /* Rerecognize the instruction if it has changed. */ + if (result != 0) + INSN_CODE (insn) = -1; + } + /* Make same adjustments to instructions that examine the condition codes without jumping and instructions that handle conditional moves (if this machine has either one). */ @@ -2396,8 +2508,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, #ifdef HAVE_conditional_execution if (GET_CODE (PATTERN (insn)) == COND_EXEC) current_insn_predicate = COND_EXEC_TEST (PATTERN (insn)); - else - current_insn_predicate = NULL_RTX; #endif #ifdef HAVE_cc0 @@ -2498,8 +2608,19 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, static bool notice_source_line (rtx insn) { - const char *filename = insn_file (insn); - int linenum = insn_line (insn); + const char *filename; + int linenum; + + if (override_filename) + { + filename = override_filename; + linenum = override_linenum; + } + else + { + filename = insn_file (insn); + linenum = insn_line (insn); + } if (filename && (force_source_line @@ -2523,6 +2644,7 @@ void cleanup_subreg_operands (rtx insn) { int i; + bool changed = false; extract_insn_cached (insn); for (i = 0; i < recog_data.n_operands; i++) { @@ -2532,22 +2654,30 @@ cleanup_subreg_operands (rtx insn) matches the else clause. Instead we test the underlying expression directly. */ if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG) - recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]); + { + recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]); + changed = true; + } else if (GET_CODE (recog_data.operand[i]) == PLUS || GET_CODE (recog_data.operand[i]) == MULT || MEM_P (recog_data.operand[i])) - recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i]); + recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i], &changed); } for (i = 0; i < recog_data.n_dups; i++) { if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG) - *recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]); + { + *recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]); + changed = true; + } else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS || GET_CODE (*recog_data.dup_loc[i]) == MULT || MEM_P (*recog_data.dup_loc[i])) - *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i]); + *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i], &changed); } + if (changed) + df_insn_rescan (insn); } /* If X is a SUBREG, replace it with a REG or a MEM, @@ -2601,7 +2731,7 @@ alter_subreg (rtx *xp) /* Do alter_subreg on all the SUBREGs contained in X. */ static rtx -walk_alter_subreg (rtx *xp) +walk_alter_subreg (rtx *xp, bool *changed) { rtx x = *xp; switch (GET_CODE (x)) @@ -2609,16 +2739,17 @@ walk_alter_subreg (rtx *xp) case PLUS: case MULT: case AND: - XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0)); - XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1)); + XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed); + XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1), changed); break; case MEM: case ZERO_EXTEND: - XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0)); + XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed); break; case SUBREG: + *changed = true; return alter_subreg (xp); default: @@ -3057,7 +3188,7 @@ output_asm_insn (const char *template, rtx *operands) int letter = *p++; unsigned long opnum; char *endptr; - + opnum = strtoul (p, &endptr, 10); if (endptr == p) @@ -3102,7 +3233,7 @@ output_asm_insn (const char *template, rtx *operands) { unsigned long opnum; char *endptr; - + opnum = strtoul (p, &endptr, 10); if (this_is_asm_operands && opnum >= insn_noperands) output_operand_lossage ("operand number out of range"); @@ -3151,7 +3282,7 @@ output_asm_label (rtx x) x = XEXP (x, 0); if (LABEL_P (x) || (NOTE_P (x) - && NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL)) + && NOTE_KIND (x) == NOTE_INSN_DELETED_LABEL)) ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); else output_operand_lossage ("'%%l' operand isn't a label"); @@ -3188,7 +3319,8 @@ output_operand (rtx x, int code ATTRIBUTE_UNUSED) void output_address (rtx x) { - walk_alter_subreg (&x); + bool changed = false; + walk_alter_subreg (&x, &changed); PRINT_OPERAND_ADDRESS (asm_out_file, x); } @@ -3258,6 +3390,10 @@ output_addr_const (FILE *file, rtx x) output_operand_lossage ("floating constant misused"); break; + case CONST_FIXED: + fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_FIXED_VALUE_LOW (x)); + break; + case PLUS: /* Some assemblers need integer constants to appear last (eg masm). */ if (GET_CODE (XEXP (x, 0)) == CONST_INT) @@ -3676,7 +3812,7 @@ int final_forward_branch_p (rtx insn) { int insn_id, label_id; - + gcc_assert (uid_shuid); insn_id = INSN_SHUID (insn); label_id = INSN_SHUID (JUMP_LABEL (insn)); @@ -3706,7 +3842,7 @@ only_leaf_regs_used (void) const char *const permitted_reg_in_leaf_functions = LEAF_REGISTERS; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if ((regs_ever_live[i] || global_regs[i]) + if ((df_regs_ever_live_p (i) || global_regs[i]) && ! permitted_reg_in_leaf_functions[i]) return 0; @@ -3774,9 +3910,9 @@ leaf_renumber_regs_insn (rtx in_rtx) } newreg = LEAF_REG_REMAP (newreg); gcc_assert (newreg >= 0); - regs_ever_live[REGNO (in_rtx)] = 0; - regs_ever_live[newreg] = 1; - REGNO (in_rtx) = newreg; + df_set_regs_ever_live (REGNO (in_rtx), false); + df_set_regs_ever_live (newreg, true); + SET_REGNO (in_rtx, newreg); in_rtx->used = 1; } @@ -3852,7 +3988,7 @@ debug_flush_symbol_queue (void) for (i = 0; i < symbol_queue_index; ++i) { - /* If we pushed queued symbols then such symbols are must be + /* If we pushed queued symbols then such symbols must be output no matter what anyone else says. Specifically, we need to make sure dbxout_symbol() thinks the symbol was used and also we need to override TYPE_DECL_SUPPRESS_DEBUG @@ -3904,7 +4040,7 @@ debug_free_queue (void) } /* Turn the RTL into assembly. */ -static void +static unsigned int rest_of_handle_final (void) { rtx x; @@ -3927,24 +4063,24 @@ rest_of_handle_final (void) #ifdef TARGET_UNWIND_INFO /* ??? The IA-64 ".handlerdata" directive must be issued before the ".endp" directive that closes the procedure descriptor. */ - output_function_exception_table (); + output_function_exception_table (fnname); #endif assemble_end_function (current_function_decl, fnname); #ifndef TARGET_UNWIND_INFO /* Otherwise, it feels unclean to switch sections in the middle. */ - output_function_exception_table (); + output_function_exception_table (fnname); #endif user_defined_section_attribute = false; + /* Free up reg info memory. */ + free_reg_info (); + if (! quiet_flag) fflush (asm_out_file); - /* Release all memory allocated by flow. */ - free_basic_block_vars (); - /* Write DBX symbols if requested. */ /* Note that for those inline functions where we don't initially @@ -3959,6 +4095,17 @@ rest_of_handle_final (void) timevar_push (TV_SYMOUT); (*debug_hooks->function_decl) (current_function_decl); timevar_pop (TV_SYMOUT); + if (DECL_STATIC_CONSTRUCTOR (current_function_decl) + && targetm.have_ctors_dtors) + targetm.asm_out.constructor (XEXP (DECL_RTL (current_function_decl), 0), + decl_init_priority_lookup + (current_function_decl)); + if (DECL_STATIC_DESTRUCTOR (current_function_decl) + && targetm.have_ctors_dtors) + targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0), + decl_fini_priority_lookup + (current_function_decl)); + return 0; } struct tree_opt_pass pass_final = @@ -3979,13 +4126,14 @@ struct tree_opt_pass pass_final = }; -static void +static unsigned int rest_of_handle_shorten_branches (void) { /* Shorten branches. */ shorten_branches (get_insns ()); + return 0; } - + struct tree_opt_pass pass_shorten_branches = { "shorten", /* name */ @@ -4004,7 +4152,7 @@ struct tree_opt_pass pass_shorten_branches = }; -static void +static unsigned int rest_of_clean_state (void) { rtx insn, next; @@ -4030,8 +4178,9 @@ rest_of_clean_state (void) reload_completed = 0; epilogue_completed = 0; - flow2_completed = 0; - no_new_pseudos = 0; +#ifdef STACK_REGS + regstack_completed = 0; +#endif /* Clear out the insn_length contents now that they are no longer valid. */ @@ -4040,10 +4189,8 @@ rest_of_clean_state (void) /* Show no temporary slots allocated. */ init_temp_slots (); - free_basic_block_vars (); free_bb_for_insn (); - if (targetm.binds_local_p (current_function_decl)) { int pref = cfun->preferred_stack_boundary; @@ -4066,6 +4213,7 @@ rest_of_clean_state (void) /* We're done with this function. Free up memory if we can. */ free_after_parsing (cfun); free_after_compilation (cfun); + return 0; } struct tree_opt_pass pass_clean_state =