OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index cc7234c..718caf1 100644 (file)
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3.  If not see
 #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
@@ -105,11 +106,6 @@ along with GCC; see the file COPYING3.  If not see
 #define CC_STATUS_INIT
 #endif
 
-/* How to start an assembler comment.  */
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-#endif
-
 /* Is the given character a logical line separator for the assembler?  */
 #ifndef IS_ASM_LOGICAL_LINE_SEPARATOR
 #define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == ';')
@@ -836,7 +832,7 @@ struct rtl_opt_pass pass_compute_alignments =
   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 */
  }
 };
@@ -1559,11 +1555,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
   if (targetm.profile_before_prologue () && crtl->profile)
     profile_function (file);
 
-#if defined (HAVE_prologue)
-  if (dwarf2out_do_frame ())
-    dwarf2out_frame_debug_init ();
-#endif
-
   /* If debugging, assign block numbers to all of the blocks in this
      function.  */
   if (write_symbols)
@@ -1672,16 +1663,70 @@ final_end_function (void)
     dwarf2out_end_epilogue (last_linenum, last_filename);
 }
 \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_p)
 {
-  rtx insn;
+  rtx insn, next;
   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))
@@ -1694,7 +1739,7 @@ final (rtx first, FILE *file, int optimize_p)
       if (optimize_p && JUMP_P (insn))
        {
          rtx lab = JUMP_LABEL (insn);
-         if (lab && LABEL_NUSES (lab) == 1)
+         if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1)
            {
              LABEL_REFS (lab) = insn;
            }
@@ -1706,6 +1751,21 @@ final (rtx first, FILE *file, int optimize_p)
 
   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;)
     {
@@ -1721,8 +1781,26 @@ final (rtx first, FILE *file, int optimize_p)
        insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
 #endif /* HAVE_ATTR_length */
 
+      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);
+    }
+
+  /* Remove CFI notes, to avoid compare-debug failures.  */
+  for (insn = first; insn; insn = next)
+    {
+      next = NEXT_INSN (insn);
+      if (NOTE_P (insn)
+         && (NOTE_KIND (insn) == NOTE_INSN_CFI
+             || NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL))
+       delete_insn (insn);
+    }
 }
 \f
 const char *
@@ -1858,10 +1936,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
          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",
-                    ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);
-
          if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB)
            {
              *seen |= SEEN_EMITTED;
@@ -1899,16 +1973,18 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
          break;
 
        case NOTE_INSN_EPILOGUE_BEG:
-#if defined (HAVE_epilogue)
-         if (dwarf2out_do_frame ())
-           dwarf2out_cfi_begin_epilogue (insn);
-#endif
-         (*debug_hooks->begin_epilogue) (last_linenum, last_filename);
+          if (!DECL_IGNORED_P (current_function_decl))
+            (*debug_hooks->begin_epilogue) (last_linenum, last_filename);
          targetm.asm_out.function_begin_epilogue (file);
          break;
 
-       case NOTE_INSN_CFA_RESTORE_STATE:
-         dwarf2out_frame_debug_restore_state ();
+       case NOTE_INSN_CFI:
+         dwarf2out_emit_cfi (NOTE_CFI (insn));
+         break;
+
+       case NOTE_INSN_CFI_LABEL:
+         ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI",
+                                 NOTE_LABEL_NUMBER (insn));
          break;
 
        case NOTE_INSN_FUNCTION_BEG:
@@ -2005,6 +2081,12 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
          ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
          break;
 
+       case NOTE_INSN_DELETED_DEBUG_LABEL:
+         /* Similarly, but need to use different namespace for it.  */
+         if (CODE_LABEL_NUMBER (insn) != -1)
+           ASM_OUTPUT_DEBUG_LABEL (file, "LDL", CODE_LABEL_NUMBER (insn));
+         break;
+
        case NOTE_INSN_VAR_LOCATION:
        case NOTE_INSN_CALL_ARG_LOCATION:
          if (!DECL_IGNORED_P (current_function_decl))
@@ -2018,8 +2100,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
       break;
 
     case BARRIER:
-      if (dwarf2out_do_frame ())
-       dwarf2out_frame_debug (insn, false);
       break;
 
     case CODE_LABEL:
@@ -2285,12 +2365,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 
            final_sequence = body;
 
-           /* Record the delay slots' frame information before the branch.
-              This is needed for delayed calls: see execute_cfa_program().  */
-           if (dwarf2out_do_frame ())
-             for (i = 1; i < XVECLEN (body, 0); i++)
-               dwarf2out_frame_debug (XVECEXP (body, 0, i), false);
-
            /* The first insn in this SEQUENCE might be a JUMP_INSN that will
               force the restoration of a comparison that was previously
               thought unnecessary.  If that happens, cancel this sequence
@@ -2425,7 +2499,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
                delete_insn (insn);
                break;
              }
-           else if (GET_CODE (SET_SRC (body)) == RETURN)
+           else if (ANY_RETURN_P (SET_SRC (body)))
              /* Replace (set (pc) (return)) with (return).  */
              PATTERN (insn) = body = SET_SRC (body);
 
@@ -2604,9 +2678,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 
        current_output_insn = debug_insn = insn;
 
-       if (CALL_P (insn) && dwarf2out_do_frame ())
-         dwarf2out_frame_debug (insn, false);
-
        /* Find the proper template for this insn.  */
        templ = get_insn_template (insn_code_number, insn);
 
@@ -2686,16 +2757,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
          targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand,
                                               recog_data.n_operands);
 
-       /* 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 (final_sequence == 0
-#if !defined (HAVE_prologue)
-           && !ACCUMULATE_OUTGOING_ARGS
-#endif
-           && dwarf2out_do_frame ())
-         dwarf2out_frame_debug (insn, true);
-
        if (!targetm.asm_out.unwind_emit_before_insn
            && targetm.asm_out.unwind_emit)
          targetm.asm_out.unwind_emit (asm_out_file, insn);
@@ -3555,8 +3616,7 @@ output_addr_const (FILE *file, rtx x)
       break;
 
     case CONST_FIXED:
-      fprintf (file, HOST_WIDE_INT_PRINT_HEX,
-              (unsigned HOST_WIDE_INT) CONST_FIXED_VALUE_LOW (x));
+      fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_FIXED_VALUE_LOW (x));
       break;
 
     case PLUS:
@@ -3640,6 +3700,97 @@ output_quoted_string (FILE *asm_file, const char *string)
 #endif
 }
 \f
+/* Write a HOST_WIDE_INT number in hex form 0x1234, fast. */
+
+void
+fprint_whex (FILE *f, unsigned HOST_WIDE_INT value)
+{
+  char buf[2 + CHAR_BIT * sizeof (value) / 4];
+  if (value == 0)
+    putc ('0', f);
+  else
+    {
+      char *p = buf + sizeof (buf);
+      do
+        *--p = "0123456789abcdef"[value % 16];
+      while ((value /= 16) != 0);
+      *--p = 'x';
+      *--p = '0';
+      fwrite (p, 1, buf + sizeof (buf) - p, f);
+    }
+}
+
+/* Internal function that prints an unsigned long in decimal in reverse.
+   The output string IS NOT null-terminated. */
+
+static int
+sprint_ul_rev (char *s, unsigned long value)
+{
+  int i = 0;
+  do
+    {
+      s[i] = "0123456789"[value % 10];
+      value /= 10;
+      i++;
+      /* alternate version, without modulo */
+      /* oldval = value; */
+      /* value /= 10; */
+      /* s[i] = "0123456789" [oldval - 10*value]; */
+      /* i++ */
+    }
+  while (value != 0);
+  return i;
+}
+
+/* Write an unsigned long as decimal to a file, fast. */
+
+void
+fprint_ul (FILE *f, unsigned long value)
+{
+  /* python says: len(str(2**64)) == 20 */
+  char s[20];
+  int i;
+
+  i = sprint_ul_rev (s, value);
+
+  /* It's probably too small to bother with string reversal and fputs. */
+  do
+    {
+      i--;
+      putc (s[i], f);
+    }
+  while (i != 0);
+}
+
+/* Write an unsigned long as decimal to a string, fast.
+   s must be wide enough to not overflow, at least 21 chars.
+   Returns the length of the string (without terminating '\0'). */
+
+int
+sprint_ul (char *s, unsigned long value)
+{
+  int len;
+  char tmp_c;
+  int i;
+  int j;
+
+  len = sprint_ul_rev (s, value);
+  s[len] = '\0';
+
+  /* Reverse the string. */
+  i = 0;
+  j = len - 1;
+  while (i < j)
+    {
+      tmp_c = s[i];
+      s[i] = s[j];
+      s[j] = tmp_c;
+      i++; j--;
+    }
+
+  return len;
+}
+
 /* 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.
@@ -4146,87 +4297,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
@@ -4339,7 +4409,7 @@ struct rtl_opt_pass pass_shorten_branches =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func                        /* todo_flags_finish */
+  0                                     /* todo_flags_finish */
  }
 };
 
@@ -4363,23 +4433,11 @@ rest_of_clean_state (void)
        }
       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))
@@ -4410,7 +4468,7 @@ rest_of_clean_state (void)
               && 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)))
+              && NOTE_KIND (insn) != NOTE_INSN_DELETED_DEBUG_LABEL)))
        print_rtl_single (final_output, insn);
     }