/* 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.
#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"
#include "ggc.h"
#include "cfgloop.h"
#include "params.h"
+#include "tree-pretty-print.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
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"
#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
{
}
+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)
#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
{
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;
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)
{
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,
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;
}
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func | TODO_verify_rtl_sharing
+ TODO_verify_rtl_sharing
| TODO_ggc_collect /* todo_flags_finish */
}
};
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
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;
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;
}
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;
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;
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)
/* 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
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
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
}
\f
+
+/* 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))
#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)
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;)
{
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);
}
}
\f
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
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)
{
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:
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;
break;
case BARRIER:
-#if defined (DWARF2_UNWIND_INFO)
if (dwarf2out_do_frame ())
dwarf2out_frame_debug (insn, false);
-#endif
break;
case CODE_LABEL:
#endif
}
}
-#ifdef HAVE_cc0
CC_STATUS_INIT;
-#endif
if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn))
debug_hooks->label (insn);
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;
/* 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
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
#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,
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
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);
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))
{
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)
/* 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;
}
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");
}
}
\f
+/* 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
+}
+\f
/* 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.
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
/* 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)
}
}
#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;
- }
-}
\f
/* Turn the RTL into assembly. */
static unsigned int
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. */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func /* todo_flags_finish */
+ 0 /* todo_flags_finish */
}
};
}
else
{
- const char *aname;
- struct cgraph_node *node = cgraph_node (current_function_decl);
-
- aname = (IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (current_function_decl)));
- fprintf (final_output, "\n;; Function (%s) %s\n\n", aname,
- node->frequency == NODE_FREQUENCY_HOT
- ? " (hot)"
- : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
- ? " (unlikely executed)"
- : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
- ? " (executed once)"
- : "");
-
flag_dump_noaddr = flag_dump_unnumbered = 1;
if (flag_compare_debug_opt || flag_compare_debug)
dump_flags |= TDF_NOUID;
+ dump_function_header (final_output, current_function_decl,
+ dump_flags);
final_insns_dump_p = true;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
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;
+ }
}
}
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)
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)