X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ffinal.c;h=7e1ae902477ef312a5447b3d89c63ef3420d6e45;hb=467fa2ada0cbc1b7b81db7567540e8e46dbca920;hp=93c2970b32023a52ada629c062d2552c06268c89;hpb=a7a4626828090600459358ca745c4482cf9551a1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/final.c b/gcc/final.c index 93c2970b320..7e1ae902477 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1,6 +1,7 @@ /* 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, 2006, 2007, 2008, 2009, 2010 + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -62,11 +63,13 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "except.h" #include "function.h" -#include "toplev.h" +#include "rtl-error.h" +#include "toplev.h" /* exact_log2, floor_log2 */ #include "reload.h" #include "intl.h" #include "basic-block.h" #include "target.h" +#include "targhooks.h" #include "debug.h" #include "expr.h" #include "cfglayout.h" @@ -86,9 +89,7 @@ along with GCC; see the file COPYING3. If not see declarations for e.g. AIX 4.x. */ #endif -#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) #include "dwarf2out.h" -#endif #ifdef DBX_DEBUGGING_INFO #include "dbxout.h" @@ -98,8 +99,8 @@ along with GCC; see the file COPYING3. If not see #include "sdbout.h" #endif -/* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a - null default for it to save conditionalization later. */ +/* Most ports that aren't using cc0 don't need to define CC_STATUS_INIT. + So define a null default for it to save conditionalization later. */ #ifndef CC_STATUS_INIT #define CC_STATUS_INIT #endif @@ -220,7 +221,6 @@ static void output_asm_name (void); static void output_alternate_entry_point (FILE *, rtx); static tree get_mem_expr_from_op (rtx, int *); static void output_asm_operand_names (rtx *, int *, int); -static void output_operand (rtx, int); #ifdef LEAF_REGISTERS static void leaf_renumber_regs (rtx); #endif @@ -257,6 +257,13 @@ default_function_pro_epilogue (FILE *file ATTRIBUTE_UNUSED, { } +void +default_function_switched_text_sections (FILE *file ATTRIBUTE_UNUSED, + tree decl ATTRIBUTE_UNUSED, + bool new_is_cold ATTRIBUTE_UNUSED) +{ +} + /* Default target hook that outputs nothing to a stream. */ void no_asm_to_stream (FILE *file ATTRIBUTE_UNUSED) @@ -499,33 +506,41 @@ get_attr_min_length (rtx insn) #define LABEL_ALIGN(LABEL) align_labels_log #endif -#ifndef LABEL_ALIGN_MAX_SKIP -#define LABEL_ALIGN_MAX_SKIP align_labels_max_skip -#endif - #ifndef LOOP_ALIGN #define LOOP_ALIGN(LABEL) align_loops_log #endif -#ifndef LOOP_ALIGN_MAX_SKIP -#define LOOP_ALIGN_MAX_SKIP align_loops_max_skip -#endif - #ifndef LABEL_ALIGN_AFTER_BARRIER #define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0 #endif -#ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP -#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0 -#endif - #ifndef JUMP_ALIGN #define JUMP_ALIGN(LABEL) align_jumps_log #endif -#ifndef JUMP_ALIGN_MAX_SKIP -#define JUMP_ALIGN_MAX_SKIP align_jumps_max_skip -#endif +int +default_label_align_after_barrier_max_skip (rtx insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +int +default_loop_align_max_skip (rtx insn ATTRIBUTE_UNUSED) +{ + return align_loops_max_skip; +} + +int +default_label_align_max_skip (rtx insn ATTRIBUTE_UNUSED) +{ + return align_labels_max_skip; +} + +int +default_jump_align_max_skip (rtx insn ATTRIBUTE_UNUSED) +{ + return align_jumps_max_skip; +} #ifndef ADDR_VEC_ALIGN static int @@ -708,8 +723,8 @@ compute_alignments (void) { dump_flow_info (dump_file, TDF_DETAILS); flow_loops_dump (dump_file, NULL, 1); - loop_optimizer_init (AVOID_CFG_MODIFICATIONS); } + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); FOR_EACH_BB (bb) if (bb->frequency > freq_max) freq_max = bb->frequency; @@ -733,7 +748,7 @@ compute_alignments (void) continue; } max_log = LABEL_ALIGN (label); - max_skip = LABEL_ALIGN_MAX_SKIP; + max_skip = targetm.asm_out.label_align_max_skip (label); FOR_EACH_EDGE (e, ei, bb->preds) { @@ -777,7 +792,7 @@ compute_alignments (void) if (max_log < log) { max_log = log; - max_skip = JUMP_ALIGN_MAX_SKIP; + max_skip = targetm.asm_out.jump_align_max_skip (label); } } /* In case block is frequent and reached mostly by non-fallthru edge, @@ -794,18 +809,15 @@ compute_alignments (void) if (max_log < log) { max_log = log; - max_skip = LOOP_ALIGN_MAX_SKIP; + max_skip = targetm.asm_out.loop_align_max_skip (label); } } LABEL_TO_ALIGNMENT (label) = max_log; LABEL_TO_MAX_SKIP (label) = max_skip; } - if (dump_file) - { - loop_optimizer_finalize (); - free_dominance_info (CDI_DOMINATORS); - } + loop_optimizer_finalize (); + free_dominance_info (CDI_DOMINATORS); return 0; } @@ -927,7 +939,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) if (max_log < log) { max_log = log; - max_skip = LABEL_ALIGN_MAX_SKIP; + max_skip = targetm.asm_out.label_align_max_skip (insn); } } /* ADDR_VECs only take room if read-only data goes into the text @@ -940,7 +952,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) if (max_log < log) { max_log = log; - max_skip = LABEL_ALIGN_MAX_SKIP; + max_skip = targetm.asm_out.label_align_max_skip (insn); } } LABEL_TO_ALIGNMENT (insn) = max_log; @@ -960,7 +972,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) if (max_log < log) { max_log = log; - max_skip = LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP; + max_skip = targetm.asm_out.label_align_after_barrier_max_skip (label); } break; } @@ -1481,7 +1493,7 @@ remap_debug_filename (const char *filename) size_t name_len; for (map = debug_prefix_maps; map; map = map->next) - if (strncmp (filename, map->old_prefix, map->old_len) == 0) + if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0) break; if (!map) return filename; @@ -1514,12 +1526,12 @@ dwarf2_debug_info_emitted_p (tree decl) FIRST is the first insn of the rtl for the function being compiled. FILE is the file to write assembler code to. - OPTIMIZE is nonzero if we should eliminate redundant + OPTIMIZE_P is nonzero if we should eliminate redundant test and compare insns. */ void final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, - int optimize ATTRIBUTE_UNUSED) + int optimize_p ATTRIBUTE_UNUSED) { block_depth = 0; @@ -1534,10 +1546,8 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->begin_prologue (last_linenum, last_filename); -#if defined (DWARF2_UNWIND_INFO) || defined (TARGET_UNWIND_INFO) if (!dwarf2_debug_info_emitted_p (current_function_decl)) dwarf2out_begin_prologue (0, NULL); -#endif #ifdef LEAF_REG_REMAP if (current_function_uses_only_leaf_regs) @@ -1546,14 +1556,12 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, /* The Sun386i and perhaps other machines don't work right if the profiling code comes after the prologue. */ -#ifdef PROFILE_BEFORE_PROLOGUE - if (crtl->profile) + if (targetm.profile_before_prologue () && crtl->profile) profile_function (file); -#endif /* PROFILE_BEFORE_PROLOGUE */ -#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue) +#if defined (HAVE_prologue) if (dwarf2out_do_frame ()) - dwarf2out_frame_debug (NULL_RTX, false); + dwarf2out_frame_debug_init (); #endif /* If debugging, assign block numbers to all of the blocks in this @@ -1591,10 +1599,8 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, static void profile_after_prologue (FILE *file ATTRIBUTE_UNUSED) { -#ifndef PROFILE_BEFORE_PROLOGUE - if (crtl->profile) + if (!targetm.profile_before_prologue () && crtl->profile) profile_function (file); -#endif /* not PROFILE_BEFORE_PROLOGUE */ } static void @@ -1661,23 +1667,75 @@ final_end_function (void) if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->end_epilogue (last_linenum, last_filename); -#if defined (DWARF2_UNWIND_INFO) if (!dwarf2_debug_info_emitted_p (current_function_decl) && dwarf2out_do_frame ()) dwarf2out_end_epilogue (last_linenum, last_filename); -#endif } + +/* Dumper helper for basic block information. FILE is the assembly + output file, and INSN is the instruction being emitted. */ + +static void +dump_basic_block_info (FILE *file, rtx insn, basic_block *start_to_bb, + basic_block *end_to_bb, int bb_map_size, int *bb_seqn) +{ + basic_block bb; + + if (!flag_debug_asm) + return; + + if (INSN_UID (insn) < bb_map_size + && (bb = start_to_bb[INSN_UID (insn)]) != NULL) + { + edge e; + edge_iterator ei; + + fprintf (file, "%s BLOCK %d", ASM_COMMENT_START, bb->index); + if (bb->frequency) + fprintf (file, " freq:%d", bb->frequency); + if (bb->count) + fprintf (file, " count:" HOST_WIDEST_INT_PRINT_DEC, + bb->count); + fprintf (file, " seq:%d", (*bb_seqn)++); + fprintf (file, "\n%s PRED:", ASM_COMMENT_START); + FOR_EACH_EDGE (e, ei, bb->preds) + { + dump_edge_info (file, e, 0); + } + fprintf (file, "\n"); + } + if (INSN_UID (insn) < bb_map_size + && (bb = end_to_bb[INSN_UID (insn)]) != NULL) + { + edge e; + edge_iterator ei; + + fprintf (asm_out_file, "%s SUCC:", ASM_COMMENT_START); + FOR_EACH_EDGE (e, ei, bb->succs) + { + dump_edge_info (asm_out_file, e, 1); + } + fprintf (file, "\n"); + } +} + /* Output assembler code for some insns: all or part of a function. For description of args, see `final_start_function', above. */ void -final (rtx first, FILE *file, int optimize) +final (rtx first, FILE *file, int optimize_p) { rtx insn; int max_uid = 0; int seen = 0; + /* Used for -dA dump. */ + basic_block *start_to_bb = NULL; + basic_block *end_to_bb = NULL; + int bb_map_size = 0; + int bb_seqn = 0; + last_ignored_compare = 0; for (insn = first; insn; insn = NEXT_INSN (insn)) @@ -1687,7 +1745,7 @@ final (rtx first, FILE *file, int optimize) #ifdef HAVE_cc0 /* If CC tracking across branches is enabled, record the insn which jumps to each branch only reached from one place. */ - if (optimize && JUMP_P (insn)) + if (optimize_p && JUMP_P (insn)) { rtx lab = JUMP_LABEL (insn); if (lab && LABEL_NUSES (lab) == 1) @@ -1702,6 +1760,21 @@ final (rtx first, FILE *file, int optimize) CC_STATUS_INIT; + if (flag_debug_asm) + { + basic_block bb; + + bb_map_size = get_max_uid () + 1; + start_to_bb = XCNEWVEC (basic_block, bb_map_size); + end_to_bb = XCNEWVEC (basic_block, bb_map_size); + + FOR_EACH_BB_REVERSE (bb) + { + start_to_bb[INSN_UID (BB_HEAD (bb))] = bb; + end_to_bb[INSN_UID (BB_END (bb))] = bb; + } + } + /* Output the insns. */ for (insn = first; insn;) { @@ -1717,7 +1790,15 @@ final (rtx first, FILE *file, int optimize) insn_current_address = INSN_ADDRESSES (INSN_UID (insn)); #endif /* HAVE_ATTR_length */ - insn = final_scan_insn (insn, file, optimize, 0, &seen); + dump_basic_block_info (file, insn, start_to_bb, end_to_bb, + bb_map_size, &bb_seqn); + insn = final_scan_insn (insn, file, optimize_p, 0, &seen); + } + + if (flag_debug_asm) + { + free (start_to_bb); + free (end_to_bb); } } @@ -1813,7 +1894,7 @@ call_from_call_insn (rtx insn) first. */ rtx -final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, +final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, int nopeepholes ATTRIBUTE_UNUSED, int *seen) { #ifdef HAVE_cc0 @@ -1838,25 +1919,21 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, case NOTE_INSN_SWITCH_TEXT_SECTIONS: in_cold_section_p = !in_cold_section_p; -#ifdef DWARF2_UNWIND_INFO + if (dwarf2out_do_frame ()) dwarf2out_switch_text_section (); - else -#endif - if (!DECL_IGNORED_P (current_function_decl)) + else if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->switch_text_section (); switch_to_section (current_function_section ()); + targetm.asm_out.function_switched_text_sections (asm_out_file, + current_function_decl, + in_cold_section_p); break; case NOTE_INSN_BASIC_BLOCK: -#ifdef TARGET_UNWIND_INFO - targetm.asm_out.unwind_emit (asm_out_file, insn); -#endif - - if (flag_debug_asm) - fprintf (asm_out_file, "\t%s basic block %d\n", - ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index); + if (targetm.asm_out.unwind_emit) + targetm.asm_out.unwind_emit (asm_out_file, insn); if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB) { @@ -1895,17 +1972,16 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, break; case NOTE_INSN_EPILOGUE_BEG: -#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_epilogue) +#if defined (HAVE_epilogue) if (dwarf2out_do_frame ()) - dwarf2out_begin_epilogue (insn); + dwarf2out_cfi_begin_epilogue (insn); #endif + (*debug_hooks->begin_epilogue) (last_linenum, last_filename); targetm.asm_out.function_begin_epilogue (file); break; case NOTE_INSN_CFA_RESTORE_STATE: -#if defined (DWARF2_UNWIND_INFO) dwarf2out_frame_debug_restore_state (); -#endif break; case NOTE_INSN_FUNCTION_BEG: @@ -2003,6 +2079,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, break; case NOTE_INSN_VAR_LOCATION: + case NOTE_INSN_CALL_ARG_LOCATION: if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->var_location (insn); break; @@ -2014,10 +2091,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, break; case BARRIER: -#if defined (DWARF2_UNWIND_INFO) if (dwarf2out_do_frame ()) dwarf2out_frame_debug (insn, false); -#endif break; case CODE_LABEL: @@ -2043,9 +2118,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, #endif } } -#ifdef HAVE_cc0 CC_STATUS_INIT; -#endif if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn)) debug_hooks->label (insn); @@ -2240,6 +2313,11 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, location_t loc; expanded_location expanded; + /* Make sure we flush any queued register saves in case this + clobbers affected registers. */ + if (dwarf2out_do_frame ()) + dwarf2out_frame_debug (insn, false); + /* There's no telling what that did to the condition codes. */ CC_STATUS_INIT; @@ -2287,11 +2365,9 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, /* Record the delay slots' frame information before the branch. This is needed for delayed calls: see execute_cfa_program(). */ -#if defined (DWARF2_UNWIND_INFO) if (dwarf2out_do_frame ()) for (i = 1; i < XVECLEN (body, 0); i++) dwarf2out_frame_debug (XVECEXP (body, 0, i), false); -#endif /* The first insn in this SEQUENCE might be a JUMP_INSN that will force the restoration of a comparison that was previously @@ -2347,7 +2423,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, and the next statement should reexamine the variable to compute the condition codes. */ - if (optimize) + if (optimize_p) { if (set && GET_CODE (SET_DEST (set)) == CC0 @@ -2532,7 +2608,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, #ifdef HAVE_peephole /* Do machine-specific peephole optimizations if desired. */ - if (optimize && !flag_no_peephole && !nopeepholes) + if (optimize_p && !flag_no_peephole && !nopeepholes) { rtx next = peephole (insn); /* When peepholing, if there were notes within the peephole, @@ -2543,7 +2619,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, for (note = NEXT_INSN (insn); note != next; note = NEXT_INSN (note)) - final_scan_insn (note, file, optimize, nopeepholes, seen); + final_scan_insn (note, file, optimize_p, nopeepholes, seen); /* Put the notes in the proper position for a later rescan. For example, the SH target can do this @@ -2606,10 +2682,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, current_output_insn = debug_insn = insn; -#if defined (DWARF2_UNWIND_INFO) if (CALL_P (insn) && dwarf2out_do_frame ()) dwarf2out_frame_debug (insn, false); -#endif /* Find the proper template for this insn. */ templ = get_insn_template (insn_code_number, insn); @@ -2658,12 +2732,12 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, return new_rtx; } -#ifdef TARGET_UNWIND_INFO /* ??? This will put the directives in the wrong place if get_insn_template outputs assembly directly. However calling it before get_insn_template breaks if the insns is split. */ - targetm.asm_out.unwind_emit (asm_out_file, insn); -#endif + if (targetm.asm_out.unwind_emit_before_insn + && targetm.asm_out.unwind_emit) + targetm.asm_out.unwind_emit (asm_out_file, insn); if (CALL_P (insn)) { @@ -2677,31 +2751,13 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, if (t) assemble_external (t); } + if (!DECL_IGNORED_P (current_function_decl)) + debug_hooks->var_location (insn); } /* Output assembler code from the template. */ output_asm_insn (templ, recog_data.operand); - /* Record point-of-call information for ICF debugging. */ - if (flag_enable_icf_debug && CALL_P (insn)) - { - rtx x = call_from_call_insn (insn); - x = XEXP (x, 0); - if (x && MEM_P (x)) - { - if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF) - { - tree t; - x = XEXP (x, 0); - t = SYMBOL_REF_DECL (x); - if (t) - (*debug_hooks->direct_call) (t); - } - else - (*debug_hooks->virtual_call) (INSN_UID (insn)); - } - } - /* Some target machines need to postscan each insn after it is output. */ if (targetm.asm_out.final_postscan_insn) @@ -2711,14 +2767,16 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, /* If necessary, report the effect that the instruction has on the unwind info. We've already done this for delay slots and call instructions. */ -#if defined (DWARF2_UNWIND_INFO) if (final_sequence == 0 #if !defined (HAVE_prologue) && !ACCUMULATE_OUTGOING_ARGS #endif && dwarf2out_do_frame ()) dwarf2out_frame_debug (insn, true); -#endif + + if (!targetm.asm_out.unwind_emit_before_insn + && targetm.asm_out.unwind_emit) + targetm.asm_out.unwind_emit (asm_out_file, insn); current_output_insn = debug_insn = 0; } @@ -3329,7 +3387,7 @@ output_asm_insn (const char *templ, rtx *operands) outputs an operand in a special way depending on the letter. Letters `acln' are implemented directly. Other letters are passed to `output_operand' so that - the PRINT_OPERAND macro can define them. */ + the TARGET_PRINT_OPERAND hook can define them. */ else if (ISALPHA (*p)) { int letter = *p++; @@ -3395,12 +3453,10 @@ output_asm_insn (const char *templ, rtx *operands) c = *p; } /* % followed by punctuation: output something for that - punctuation character alone, with no operand. - The PRINT_OPERAND macro decides what is actually done. */ -#ifdef PRINT_OPERAND_PUNCT_VALID_P - else if (PRINT_OPERAND_PUNCT_VALID_P ((unsigned char) *p)) + punctuation character alone, with no operand. The + TARGET_PRINT_OPERAND hook decides what is actually done. */ + else if (targetm.asm_out.print_operand_punct_valid_p ((unsigned char) *p)) output_operand (NULL_RTX, *p++); -#endif else output_operand_lossage ("invalid %%-code"); break; @@ -3472,16 +3528,15 @@ mark_symbol_refs_as_used (rtx x) } /* Print operand X using machine-dependent assembler syntax. - The macro PRINT_OPERAND is defined just to control this function. CODE is a non-digit that preceded the operand-number in the % spec, such as 'z' if the spec was `%z3'. CODE is 0 if there was no char between the % and the digits. When CODE is a non-letter, X is 0. The meanings of the letters are machine-dependent and controlled - by PRINT_OPERAND. */ + by TARGET_PRINT_OPERAND. */ -static void +void output_operand (rtx x, int code ATTRIBUTE_UNUSED) { if (x && GET_CODE (x) == SUBREG) @@ -3490,7 +3545,7 @@ output_operand (rtx x, int code ATTRIBUTE_UNUSED) /* X must not be a pseudo reg. */ gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER); - PRINT_OPERAND (asm_out_file, x, code); + targetm.asm_out.print_operand (asm_out_file, x, code); if (x == NULL_RTX) return; @@ -3498,16 +3553,15 @@ output_operand (rtx x, int code ATTRIBUTE_UNUSED) for_each_rtx (&x, mark_symbol_ref_as_used, NULL); } -/* Print a memory reference operand for address X - using machine-dependent assembler syntax. - The macro PRINT_OPERAND_ADDRESS exists just to control this function. */ +/* Print a memory reference operand for address X using + machine-dependent assembler syntax. */ void output_address (rtx x) { bool changed = false; walk_alter_subreg (&x, &changed); - PRINT_OPERAND_ADDRESS (asm_out_file, x); + targetm.asm_out.print_operand_address (asm_out_file, x); } /* Print an integer constant expression in assembler syntax. @@ -3631,16 +3685,39 @@ output_addr_const (FILE *file, rtx x) break; default: -#ifdef OUTPUT_ADDR_CONST_EXTRA - OUTPUT_ADDR_CONST_EXTRA (file, x, fail); - break; + if (targetm.asm_out.output_addr_const_extra (file, x)) + break; - fail: -#endif output_operand_lossage ("invalid expression as operand"); } } +/* Output a quoted string. */ + +void +output_quoted_string (FILE *asm_file, const char *string) +{ +#ifdef OUTPUT_QUOTED_STRING + OUTPUT_QUOTED_STRING (asm_file, string); +#else + char c; + + putc ('\"', asm_file); + while ((c = *string++) != 0) + { + if (ISPRINT (c)) + { + if (c == '\"' || c == '\\') + putc ('\\', asm_file); + putc (c, asm_file); + } + else + fprintf (asm_file, "\\%03o", (unsigned char) c); + } + putc ('\"', asm_file); +#endif +} + /* A poor man's fprintf, with the added features of %I, %R, %L, and %U. %R prints the value of REGISTER_PREFIX. %L prints the value of LOCAL_LABEL_PREFIX. @@ -3828,10 +3905,11 @@ split_double (rtx value, rtx *first, rtx *second) Sign extend each half to HOST_WIDE_INT. */ unsigned HOST_WIDE_INT low, high; unsigned HOST_WIDE_INT mask, sign_bit, sign_extend; + unsigned bits_per_word = BITS_PER_WORD; /* Set sign_bit to the most significant bit of a word. */ sign_bit = 1; - sign_bit <<= BITS_PER_WORD - 1; + sign_bit <<= bits_per_word - 1; /* Set mask so that all bits of the word are set. We could have used 1 << BITS_PER_WORD instead of basing the @@ -3854,7 +3932,7 @@ split_double (rtx value, rtx *first, rtx *second) /* Pick the higher word, shifted to the least significant bits, and sign-extend it. */ high = INTVAL (value); - high >>= BITS_PER_WORD - 1; + high >>= bits_per_word - 1; high >>= 1; high &= mask; if (high & sign_bit) @@ -4146,87 +4224,6 @@ leaf_renumber_regs_insn (rtx in_rtx) } } #endif - - -/* When -gused is used, emit debug info for only used symbols. But in - addition to the standard intercepted debug_hooks there are some direct - calls into this file, i.e., dbxout_symbol, dbxout_parms, and dbxout_reg_params. - Those routines may also be called from a higher level intercepted routine. So - to prevent recording data for an inner call to one of these for an intercept, - we maintain an intercept nesting counter (debug_nesting). We only save the - intercepted arguments if the nesting is 1. */ -int debug_nesting = 0; - -static tree *symbol_queue; -int symbol_queue_index = 0; -static int symbol_queue_size = 0; - -/* Generate the symbols for any queued up type symbols we encountered - while generating the type info for some originally used symbol. - This might generate additional entries in the queue. Only when - the nesting depth goes to 0 is this routine called. */ - -void -debug_flush_symbol_queue (void) -{ - int i; - - /* Make sure that additionally queued items are not flushed - prematurely. */ - - ++debug_nesting; - - for (i = 0; i < symbol_queue_index; ++i) - { - /* 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 - which may be set for outside reasons. */ - int saved_tree_used = TREE_USED (symbol_queue[i]); - int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]); - TREE_USED (symbol_queue[i]) = 1; - TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0; - -#ifdef DBX_DEBUGGING_INFO - dbxout_symbol (symbol_queue[i], 0); -#endif - - TREE_USED (symbol_queue[i]) = saved_tree_used; - TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug; - } - - symbol_queue_index = 0; - --debug_nesting; -} - -/* Queue a type symbol needed as part of the definition of a decl - symbol. These symbols are generated when debug_flush_symbol_queue() - is called. */ - -void -debug_queue_symbol (tree decl) -{ - if (symbol_queue_index >= symbol_queue_size) - { - symbol_queue_size += 10; - symbol_queue = XRESIZEVEC (tree, symbol_queue, symbol_queue_size); - } - - symbol_queue[symbol_queue_index++] = decl; -} - -/* Free symbol queue. */ -void -debug_free_queue (void) -{ - if (symbol_queue) - { - free (symbol_queue); - symbol_queue = NULL; - symbol_queue_size = 0; - } -} /* Turn the RTL into assembly. */ static unsigned int @@ -4249,19 +4246,13 @@ rest_of_handle_final (void) final (get_insns (), asm_out_file, optimize); final_end_function (); -#ifdef TARGET_UNWIND_INFO - /* ??? The IA-64 ".handlerdata" directive must be issued before - the ".endp" directive that closes the procedure descriptor. */ + /* The IA-64 ".handlerdata" directive must be issued before the ".endp" + directive that closes the procedure descriptor. Similarly, for x64 SEH. + Otherwise it's not strictly necessary, but it doesn't hurt either. */ 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 (fnname); -#endif - user_defined_section_attribute = false; /* Free up reg info memory. */ @@ -4363,14 +4354,14 @@ rest_of_clean_state (void) final_output = fopen (flag_dump_final_insns, "a"); if (!final_output) { - error ("could not open final insn dump file %qs: %s", - flag_dump_final_insns, strerror (errno)); + error ("could not open final insn dump file %qs: %m", + flag_dump_final_insns); flag_dump_final_insns = NULL; } else { const char *aname; - struct cgraph_node *node = cgraph_node (current_function_decl); + struct cgraph_node *node = cgraph_get_node (current_function_decl); aname = (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl))); @@ -4392,7 +4383,11 @@ rest_of_clean_state (void) if (LABEL_P (insn)) INSN_UID (insn) = CODE_LABEL_NUMBER (insn); else - INSN_UID (insn) = 0; + { + if (NOTE_P (insn)) + set_block_for_insn (insn, NULL); + INSN_UID (insn) = 0; + } } } @@ -4409,11 +4404,11 @@ rest_of_clean_state (void) if (final_output && (!NOTE_P (insn) || (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION + && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END && NOTE_KIND (insn) != NOTE_INSN_CFA_RESTORE_STATE))) print_rtl_single (final_output, insn); - } if (final_output) @@ -4424,8 +4419,8 @@ rest_of_clean_state (void) if (fclose (final_output)) { - error ("could not close final insn dump file %qs: %s", - flag_dump_final_insns, strerror (errno)); + error ("could not close final insn dump file %qs: %m", + flag_dump_final_insns); flag_dump_final_insns = NULL; } } @@ -4456,7 +4451,10 @@ rest_of_clean_state (void) delete_tree_ssa (); - if (targetm.binds_local_p (current_function_decl)) + /* We can reduce stack alignment on call site only when we are sure that + the function body just produced will be actually used in the final + executable. */ + if (decl_binds_to_current_def_p (current_function_decl)) { unsigned int pref = crtl->preferred_stack_boundary; if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary)