OSDN Git Service

PR 49214 fd_gets should return NULL if nothing was read
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index 93c2970..7e1ae90 100644 (file)
@@ -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
 }
 \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))
@@ -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);
     }
 }
 \f
@@ -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);
 }
 \f
 /* 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");
     }
 }
 \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.
@@ -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;
-    }
-}
 \f
 /* 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)