#include "dwarf2asm.h"
#include "integrate.h"
#include "debug.h"
-
-#ifdef DWARF_DEBUGGING_INFO
-#include "dwarfout.h"
-#endif
+#include "target.h"
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
#include "dwarf2out.h"
#endif
#ifdef XCOFF_DEBUGGING_INFO
-#include "xcoffout.h"
+#include "xcoffout.h" /* Needed for external data
+ declarations for e.g. AIX 4.x. */
#endif
\f
#ifdef VMS
static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
static void crash_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
+static void set_float_handler PARAMS ((jmp_buf));
static void compile_file PARAMS ((const char *));
static void display_help PARAMS ((void));
static void display_target_options PARAMS ((void));
/* Specify where to longjmp to when a floating arithmetic error happens.
If HANDLER is 0, it means don't handle the errors any more. */
-void
+static void
set_float_handler (handler)
jmp_buf handler;
{
warning_with_decl (decl, "`%s' defined but not used");
timevar_push (TV_SYMOUT);
-#ifdef SDB_DEBUGGING_INFO
- /* The COFF linker can move initialized global vars to the end.
- And that can screw up the symbol ordering.
- By putting the symbols in that order to begin with,
- we avoid a problem. mcsun!unido!fauern!tumuc!pes@uunet.uu.net. */
- if (write_symbols == SDB_DEBUG && TREE_CODE (decl) == VAR_DECL
- && TREE_PUBLIC (decl) && DECL_INITIAL (decl)
- && ! DECL_EXTERNAL (decl)
- && DECL_RTL (decl) != 0)
- sdbout_symbol (decl, 0);
-
- /* Output COFF information for non-global
- file-scope initialized variables. */
- if (write_symbols == SDB_DEBUG
- && TREE_CODE (decl) == VAR_DECL
- && DECL_INITIAL (decl)
- && ! DECL_EXTERNAL (decl)
- && DECL_RTL (decl) != 0
- && GET_CODE (DECL_RTL (decl)) == MEM)
- sdbout_toplevel_data (decl);
-#endif /* SDB_DEBUGGING_INFO */
-#ifdef DWARF_DEBUGGING_INFO
- /* Output DWARF information for file-scope tentative data object
- declarations, file-scope (extern) function declarations (which
- had no corresponding body) and file-scope tagged type declarations
- and definitions which have not yet been forced out. */
-
- if (write_symbols == DWARF_DEBUG
- && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- dwarfout_file_scope_decl (decl, 1);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- /* Output DWARF2 information for file-scope tentative data object
- declarations, file-scope (extern) function declarations (which
- had no corresponding body) and file-scope tagged type declarations
- and definitions which have not yet been forced out. */
-
- if (write_symbols == DWARF2_DEBUG
- && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- dwarf2out_decl (decl);
-#endif
+ (*debug_hooks->global_decl) (decl);
timevar_pop (TV_SYMOUT);
}
}
debug_hooks = &dwarf2_debug_hooks;
#endif
-#ifndef ASM_OUTPUT_SECTION_NAME
- if (flag_function_sections)
+ if (! targetm.have_named_sections)
{
- warning ("-ffunction-sections not supported for this target.");
- flag_function_sections = 0;
- }
- if (flag_data_sections)
- {
- warning ("-fdata-sections not supported for this target.");
- flag_data_sections = 0;
+ if (flag_function_sections)
+ {
+ warning ("-ffunction-sections not supported for this target.");
+ flag_function_sections = 0;
+ }
+ if (flag_data_sections)
+ {
+ warning ("-fdata-sections not supported for this target.");
+ flag_data_sections = 0;
+ }
}
-#endif
if (flag_function_sections
&& (profile_flag || profile_block_flag))
timevar_pop (TV_SYMOUT);
}
-/* DECL is an inline function, whose body is present, but which is not
- being output at this point. (We're putting that off until we need
- to do it.) If there are any actions that need to take place,
- including the emission of debugging information for the function,
- this is where they should go. This function may be called by
- language-dependent code for front-ends that do not even generate
- RTL for functions that don't need to be put out. */
-
-void
-note_deferral_of_defined_inline_function (decl)
- tree decl ATTRIBUTE_UNUSED;
-{
-#ifdef DWARF_DEBUGGING_INFO
- /* Generate the DWARF info for the "abstract" instance of a function
- which we may later generate inlined and/or out-of-line instances
- of. */
- if (write_symbols == DWARF_DEBUG
- && (DECL_INLINE (decl) || DECL_ABSTRACT (decl))
- && ! DECL_ABSTRACT_ORIGIN (decl))
- {
- /* The front-end may not have set CURRENT_FUNCTION_DECL, but the
- DWARF code expects it to be set in this case. Intuitively,
- DECL is the function we just finished defining, so setting
- CURRENT_FUNCTION_DECL is sensible. */
- tree saved_cfd = current_function_decl;
- int was_abstract = DECL_ABSTRACT (decl);
- current_function_decl = decl;
-
- /* Let the DWARF code do its work. */
- set_decl_abstract_flags (decl, 1);
- dwarfout_file_scope_decl (decl, 0);
- if (! was_abstract)
- set_decl_abstract_flags (decl, 0);
-
- /* Reset CURRENT_FUNCTION_DECL. */
- current_function_decl = saved_cfd;
- }
-#endif
-}
-
-/* FNDECL is an inline function which is about to be emitted out of line.
- Do any preparation, such as emitting abstract debug info for the inline
- before it gets mangled by optimization. */
-
-void
-note_outlining_of_inline_function (fndecl)
- tree fndecl ATTRIBUTE_UNUSED;
-{
-#ifdef DWARF2_DEBUGGING_INFO
- /* The DWARF 2 backend tries to reduce debugging bloat by not emitting
- the abstract description of inline functions until something tries to
- reference them. Force it out now, before optimizations mangle the
- block tree. */
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_abstract_function (fndecl);
-#endif
-}
-
/* This is called from finish_function (within yyparse)
after each top-level definition is parsed.
It is supposed to compile that function or variable
declared inline but not inlined, and those inlined even
though they weren't declared inline. Conveniently, that's
what DECL_INLINE means at this point. */
- note_deferral_of_defined_inline_function (decl);
+ (*debug_hooks->deferred_inline_function) (decl);
if (DECL_DEFER_OUTPUT (decl))
{
/* If -Wreturn-type, we have to do a bit of compilation. We just
- want to call jump_optimize to figure out whether or not we can
+ want to call cleanup the cfg to figure out whether or not we can
fall off the end of the function; we do the minimum amount of
- work necessary to make that safe. And, we set optimize to zero
- to keep jump_optimize from working too hard. */
+ work necessary to make that safe. */
if (warn_return_type)
{
int saved_optimize = optimize;
optimize = 0;
+ rebuild_jump_labels (insns);
find_exception_handler_labels ();
- jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
optimize = saved_optimize;
}
purge_hard_subreg_sets (get_insns ());
emit_initial_value_sets ();
- /* Don't return yet if -Wreturn-type; we need to do jump_optimize. */
+ /* Don't return yet if -Wreturn-type; we need to do cleanup_cfg. */
if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
goto exit_rest_of_compilation;
expected_value_to_br_prob ();
reg_scan (insns, max_reg_num (), 0);
- jump_optimize (insns, !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
+ rebuild_jump_labels (insns);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP);
+ copy_loop_headers (insns);
+ purge_line_number_notes (insns);
timevar_pop (TV_JUMP);
open_dump_file (DFI_ssa, decl);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
convert_to_ssa ();
close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
if (optimize > 0)
{
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
/* ??? Run if-conversion before delete_null_pointer_checks,
since the later does not preserve the CFG. This should
if (tem || optimize > 1)
{
timevar_push (TV_JUMP);
- jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ rebuild_jump_labels (insns);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
timevar_pop (TV_JUMP);
}
/* Run this after jump optmizations remove all the unreachable code
so that unreachable code will not keep values live. */
- delete_trivially_dead_insns (insns, max_reg_num ());
+ delete_trivially_dead_insns (insns, max_reg_num (), 0);
/* Try to identify useless null pointer tests and delete them. */
if (flag_delete_null_pointer_checks)
timevar_push (TV_JUMP);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
delete_null_pointer_checks (insns);
timevar_pop (TV_JUMP);
open_dump_file (DFI_gcse, decl);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
tem = gcse_main (insns, rtl_dump_file);
save_csb = flag_cse_skip_blocks;
{
tem = tem2 = 0;
timevar_push (TV_JUMP);
- jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ rebuild_jump_labels (insns);
+ delete_trivially_dead_insns (insns, max_reg_num (), 0);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
timevar_pop (TV_JUMP);
if (flag_expensive_optimizations)
if (flag_rerun_loop_opt)
{
+ cleanup_barriers ();
+
/* We only want to perform unrolling once. */
loop_optimize (insns, rtl_dump_file, 0);
trivially dead. We delete those instructions now in the
hope that doing so will make the heuristics in loop work
better and possibly speed up compilation. */
- delete_trivially_dead_insns (insns, max_reg_num ());
+ delete_trivially_dead_insns (insns, max_reg_num (), 0);
/* The regscan pass is currently necessary as the alias
analysis code depends on this information. */
reg_scan (insns, max_reg_num (), 1);
}
+ cleanup_barriers ();
loop_optimize (insns, rtl_dump_file,
(flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT);
trivially dead. We delete those instructions now in the
hope that doing so will make the heuristics in jump work
better and possibly speed up compilation. */
- delete_trivially_dead_insns (insns, max_reg_num ());
+ delete_trivially_dead_insns (insns, max_reg_num (), 0);
reg_scan (insns, max_reg_num (), 0);
- jump_optimize (insns, !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
timevar_push (TV_IFCVT);
if (tem)
{
timevar_push (TV_JUMP);
- jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+ rebuild_jump_labels (insns);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (CLEANUP_EXPENSIVE);
timevar_pop (TV_JUMP);
}
}
life_analysis (insns, rtl_dump_file, PROP_FINAL);
timevar_pop (TV_FLOW);
- register_life_up_to_date = 1;
no_new_pseudos = 1;
if (warn_uninitialized || extra_warnings)
rebuild_jump_labels_after_combine
= combine_instructions (insns, max_reg_num ());
+ /* Always purge dead edges, as we may eliminate an insn throwing
+ exception. */
+ rebuild_jump_labels_after_combine |= purge_all_dead_edges ();
+
/* Combining insns may have turned an indirect jump into a
direct jump. Rebuid the JUMP_LABEL fields of jumping
instructions. */
timevar_pop (TV_JUMP);
timevar_push (TV_FLOW);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
cleanup_cfg (CLEANUP_EXPENSIVE);
/* Blimey. We've got to have the CFG up to date for the call to
without updating life info can wind up with Wierd Stuff in
global_live_at_end. We then run sched1, which updates things
properly, discovers the wierdness and aborts. */
+ allocate_bb_life_data ();
update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
| PROP_SCAN_DEAD_CODE);
ggc_collect ();
}
+ /* Do unconditional splitting before register allocation to allow machine
+ description to add extra information not needed previously. */
+ split_all_insns (1);
+
/* Any of the several passes since flow1 will have munged register
lifetime data a bit. */
- if (optimize > 0)
- register_life_up_to_date = 0;
+ register_life_up_to_date = 0;
#ifdef OPTIMIZE_MODE_SWITCHING
timevar_push (TV_GCSE);
+ no_new_pseudos = 0;
if (optimize_mode_switching (NULL))
{
/* We did work, and so had to regenerate global life information.
information below. */
register_life_up_to_date = 1;
}
+ no_new_pseudos = 1;
timevar_pop (TV_GCSE);
#endif
timevar_push (TV_SCHED);
- split_all_insns (1);
-
#ifdef INSN_SCHEDULING
/* Print function header into sched dump now
timevar_pop (TV_RELOAD_CSE_REGS);
}
- /* If optimizing, then go ahead and split insns now since we are about
- to recompute flow information anyway. */
- if (optimize > 0)
- {
- int old_labelnum = max_label_num ();
-
- split_all_insns (0);
- rebuild_label_notes_after_reload |= old_labelnum != max_label_num ();
- }
-
/* Register allocation and reloading may have turned an indirect jump into
a direct jump. If so, we must rebuild the JUMP_LABEL fields of
jumping instructions. */
timevar_push (TV_FLOW2);
open_dump_file (DFI_flow2, decl);
- jump_optimize (insns, JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
+
+ compute_bb_for_insn (get_max_uid ());
+
+ /* If optimizing, then go ahead and split insns now. */
+ if (optimize > 0)
+ split_all_insns (0);
+
+ cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
/* On some machines, the prologue and epilogue code, or parts thereof,
can be represented as RTL. Doing so lets us schedule insns between
ggc_collect ();
#endif
- if (optimize > 0 && flag_reorder_blocks)
+ if (optimize > 0)
{
timevar_push (TV_REORDER_BLOCKS);
open_dump_file (DFI_bbro, decl);
- reorder_basic_blocks ();
+ /* Last attempt to optimize CFG, as life analyzis possibly removed
+ some instructions. */
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
+ | CLEANUP_CROSSJUMP);
+ if (flag_reorder_blocks)
+ {
+ reorder_basic_blocks ();
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
+ }
close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
timevar_pop (TV_REORDER_BLOCKS);
}
/* CFG no longer kept up to date. */
+ purge_line_number_notes (insns);
+ cleanup_barriers ();
+
/* If a scheduling pass for delayed branches is to be done,
call the scheduling code. */
#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
timevar_push (TV_SHORTEN_BRANCH);
- split_all_insns (0);
+ split_all_insns_noflow ();
timevar_pop (TV_SHORTEN_BRANCH);
#endif
generated. During that call, we *will* be routed past here. */
timevar_push (TV_SYMOUT);
-#ifdef DBX_DEBUGGING_INFO
- if (write_symbols == DBX_DEBUG)
- dbxout_function (decl);
-#endif
-
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- dwarfout_file_scope_decl (decl, 0);
-#endif
-
-#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_decl (decl);
-#endif
+ (*debug_hooks->function_decl) (decl);
timevar_pop (TV_SYMOUT);
exit_rest_of_compilation:
fprintf (file, "%s", term);
}
-
-/* Returns nonzero if it is appropriate not to emit any debugging
- information for BLOCK, because it doesn't contain any instructions.
- This may not be the case for blocks containing nested functions, since
- we may actually call such a function even though the BLOCK information
- is messed up. */
-
-int
-debug_ignore_block (block)
- tree block ATTRIBUTE_UNUSED;
-{
- /* Never delete the BLOCK for the outermost scope
- of the function; we can refer to names from
- that scope even if the block notes are messed up. */
- if (is_body_block (block))
- return 0;
-
-#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- return dwarf2out_ignore_block (block);
-#endif
-
- return 1;
-}