Mercurial > hg > CbC > CbC_gcc
diff gcc/final.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/final.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/final.c Tue Mar 22 17:18:12 2011 +0900 @@ -62,11 +62,13 @@ #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 +88,7 @@ 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 +98,8 @@ #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 +220,6 @@ 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 +256,13 @@ { } +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 +505,41 @@ #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 +722,8 @@ { 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 +747,7 @@ 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 +791,7 @@ 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 +808,15 @@ 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 +938,7 @@ 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 +951,7 @@ 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 +971,7 @@ 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 +1492,7 @@ 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 +1525,12 @@ 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 +1545,8 @@ 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,12 +1555,10 @@ /* 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); #endif @@ -1591,10 +1598,8 @@ 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,18 +1666,16 @@ 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 } /* 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; @@ -1687,7 +1690,7 @@ #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) @@ -1717,7 +1720,7 @@ insn_current_address = INSN_ADDRESSES (INSN_UID (insn)); #endif /* HAVE_ATTR_length */ - insn = final_scan_insn (insn, file, optimize, 0, &seen); + insn = final_scan_insn (insn, file, optimize_p, 0, &seen); } } @@ -1813,7 +1816,7 @@ 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,21 +1841,21 @@ 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 (targetm.asm_out.unwind_emit) + targetm.asm_out.unwind_emit (asm_out_file, insn); if (flag_debug_asm) fprintf (asm_out_file, "\t%s basic block %d\n", @@ -1895,17 +1898,16 @@ 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: @@ -2014,10 +2016,8 @@ break; case BARRIER: -#if defined (DWARF2_UNWIND_INFO) if (dwarf2out_do_frame ()) dwarf2out_frame_debug (insn, false); -#endif break; case CODE_LABEL: @@ -2043,9 +2043,7 @@ #endif } } -#ifdef HAVE_cc0 CC_STATUS_INIT; -#endif if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn)) debug_hooks->label (insn); @@ -2287,11 +2285,9 @@ /* 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 +2343,7 @@ 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 +2528,7 @@ #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 +2539,7 @@ 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 +2602,8 @@ 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 +2652,12 @@ 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)) { @@ -2711,14 +2705,16 @@ /* 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 +3325,7 @@ 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 +3391,10 @@ 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 +3466,15 @@ } /* 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. */ - -static void + by TARGET_PRINT_OPERAND. */ + +void output_operand (rtx x, int code ATTRIBUTE_UNUSED) { if (x && GET_CODE (x) == SUBREG) @@ -3490,7 +3483,7 @@ /* 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 +3491,15 @@ 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 +3623,39 @@ break; default: -#ifdef OUTPUT_ADDR_CONST_EXTRA - OUTPUT_ADDR_CONST_EXTRA (file, x, fail); - break; - - fail: -#endif + if (targetm.asm_out.output_addr_const_extra (file, x)) + break; + 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 +3843,11 @@ 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 +3870,7 @@ /* 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) @@ -4249,19 +4265,13 @@ 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,8 +4373,8 @@ 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 @@ -4392,7 +4402,11 @@ 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; + } } } @@ -4413,7 +4427,6 @@ && 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 +4437,8 @@ 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 +4469,10 @@ 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)