OSDN Git Service

* update_web_docs, doc_exclude: Check out files that may be in the
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index c83f722..7b36b1b 100644 (file)
@@ -1,6 +1,6 @@
 /* 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 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -52,15 +52,12 @@ Boston, MA 02111-1307, USA.  */
 #include "tm_p.h"
 #include "regs.h"
 #include "insn-config.h"
-#include "insn-flags.h"
 #include "insn-attr.h"
-#include "insn-codes.h"
 #include "recog.h"
 #include "conditions.h"
 #include "flags.h"
 #include "real.h"
 #include "hard-reg-set.h"
-#include "defaults.h"
 #include "output.h"
 #include "except.h"
 #include "function.h"
@@ -69,21 +66,10 @@ Boston, MA 02111-1307, USA.  */
 #include "intl.h"
 #include "basic-block.h"
 
-/* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist.  */
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
 #include "dbxout.h"
-#if defined (USG) || !defined (HAVE_STAB_H)
-#include "gstab.h"  /* If doing DBX on sysV, use our own stab.h.  */
-#else
-#include <stab.h>
-#endif
-
 #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
 
-#ifndef ACCUMULATE_OUTGOING_ARGS
-#define ACCUMULATE_OUTGOING_ARGS 0
-#endif
-
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"
 #endif
@@ -100,16 +86,6 @@ Boston, MA 02111-1307, USA.  */
 #include "sdbout.h"
 #endif
 
-/* .stabd code for line number.  */
-#ifndef N_SLINE
-#define        N_SLINE 0x44
-#endif
-
-/* .stabs code for included file name.  */
-#ifndef N_SOL
-#define        N_SOL 0x84
-#endif
-
 /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist.  So define a
    null default for it to save conditionalization later.  */
 #ifndef CC_STATUS_INIT
@@ -806,11 +782,11 @@ static int
 final_addr_vec_align (addr_vec)
      rtx addr_vec;
 {
-  int align = exact_log2 (GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec))));
+  int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
 
   if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
     align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
-  return align;
+  return exact_log2 (align);
 
 }
 
@@ -1556,8 +1532,7 @@ asm_insn_count (body)
   if (GET_CODE (body) == ASM_INPUT)
     template = XSTR (body, 0);
   else
-    template = decode_asm_operands (body, NULL_PTR, NULL_PTR,
-                                   NULL_PTR, NULL_PTR);
+    template = decode_asm_operands (body, NULL, NULL, NULL, NULL);
 
   for (; *template; template++)
     if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n')
@@ -1608,12 +1583,9 @@ final_start_function (first, file, optimize)
     last_linenum = high_block_linenum = high_function_linenum
       = NOTE_LINE_NUMBER (first);
 
-#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
-  /* Output DWARF definition of the function.  */
-  if (dwarf2out_do_frame ())
-    dwarf2out_begin_prologue ();
-  else
-    current_function_func_begin_label = 0;
+#if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO) \
+    || defined (DWARF2_DEBUGGING_INFO)
+  dwarf2out_begin_prologue ();
 #endif
 
   /* For SDB and XCOFF, the function beginning must be marked between
@@ -1836,10 +1808,6 @@ final_end_function (first, file, optimize)
 
   bb_func_label_num = -1;      /* not in function, nuke label # */
 
-#ifdef IA64_UNWIND_INFO
-  output_function_exception_table ();
-#endif
-
   /* If FUNCTION_EPILOGUE is not defined, then the function body
      itself contains return instructions wherever needed.  */
 }
@@ -1952,8 +1920,6 @@ final (first, file, optimize, prescan)
   last_ignored_compare = 0;
   new_block = 1;
 
-  check_exception_handler_labels ();
-
   /* Make a map indicating which line numbers appear in this function.
      When producing SDB debugging info, delete troublesome line number
      notes from inlined functions in other files as well as duplicate
@@ -2010,10 +1976,6 @@ final (first, file, optimize, prescan)
 #endif
     }
 
-  /* Initialize insn_eh_region table if eh is being used.  */
-
-  init_insn_eh_region (first, max_uid);
-
   init_recog ();
 
   CC_STATUS_INIT;
@@ -2047,7 +2009,6 @@ final (first, file, optimize, prescan)
   if (profile_block_flag && new_block)
     add_bb (file);
 
-  free_insn_eh_region ();
   free (line_note_exists);
   line_note_exists = NULL;
 }
@@ -2124,33 +2085,22 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          break;
 
        case NOTE_INSN_BASIC_BLOCK:
+#ifdef IA64_UNWIND_INFO
+         IA64_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);
          break;
 
        case NOTE_INSN_EH_REGION_BEG:
-         if (! exceptions_via_longjmp)
-           {
-             ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_EH_HANDLER (insn));
-             if (! flag_new_exceptions)
-               add_eh_table_entry (NOTE_EH_HANDLER (insn));
-#ifdef ASM_OUTPUT_EH_REGION_BEG
-             ASM_OUTPUT_EH_REGION_BEG (file, NOTE_EH_HANDLER (insn));
-#endif
-           }
+         ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB",
+                                 NOTE_EH_HANDLER (insn));
          break;
 
        case NOTE_INSN_EH_REGION_END:
-         if (! exceptions_via_longjmp)
-           {
-             ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_EH_HANDLER (insn));
-             if (flag_new_exceptions)
-               add_eh_table_entry (NOTE_EH_HANDLER (insn));
-#ifdef ASM_OUTPUT_EH_REGION_END
-             ASM_OUTPUT_EH_REGION_END (file, NOTE_EH_HANDLER (insn));
-#endif
-           }
+         ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE",
+                                 NOTE_EH_HANDLER (insn));
          break;
 
        case NOTE_INSN_PROLOGUE_END:
@@ -2325,9 +2275,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
     case BARRIER:
 #if defined (DWARF2_UNWIND_INFO)
-      /* If we push arguments, we need to check all insns for stack
-        adjustments.  */
-      if (!ACCUMULATE_OUTGOING_ARGS && dwarf2out_do_frame ())
+      if (dwarf2out_do_frame ())
        dwarf2out_frame_debug (insn);
 #endif
       break;
@@ -2381,7 +2329,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
       new_block = 1;
 
 #ifdef FINAL_PRESCAN_LABEL
-      FINAL_PRESCAN_INSN (insn, NULL_PTR, 0);
+      FINAL_PRESCAN_INSN (insn, NULL, 0);
 #endif
 
 #ifdef SDB_DEBUGGING_INFO
@@ -2583,8 +2531,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
              }
 
            /* Get out the operand values.  */
-           string = decode_asm_operands (body, ops, NULL_PTR,
-                                         NULL_PTR, NULL_PTR);
+           string = decode_asm_operands (body, ops, NULL, NULL, NULL);
            /* Inhibit aborts on what would otherwise be compiler bugs.  */
            insn_noperands = noperands;
            this_is_asm_operands = insn;
@@ -2937,9 +2884,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        current_output_insn = debug_insn = insn;
 
 #if defined (DWARF2_UNWIND_INFO)
-       /* If we push arguments, we want to know where the calls are.  */
-       if (!ACCUMULATE_OUTGOING_ARGS && GET_CODE (insn) == CALL_INSN
-           && dwarf2out_do_frame ())
+       if (GET_CODE (insn) == CALL_INSN && dwarf2out_do_frame ())
          dwarf2out_frame_debug (insn);
 #endif
 
@@ -3007,22 +2952,15 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        output_asm_insn (template, recog_data.operand);
 
 #if defined (DWARF2_UNWIND_INFO)
-       /* If we push arguments, we need to check all insns for stack
-          adjustments.  */
-       if (!ACCUMULATE_OUTGOING_ARGS)
-         {
-           if (GET_CODE (insn) == INSN && dwarf2out_do_frame ())
-             dwarf2out_frame_debug (insn);
-         }
-       else
-         {
 #if defined (HAVE_prologue)
-           /* If this insn is part of the prologue, emit DWARF v2
-              call frame info.  */
-           if (RTX_FRAME_RELATED_P (insn) && dwarf2out_do_frame ())
-             dwarf2out_frame_debug (insn);
+       if (GET_CODE (insn) == INSN && dwarf2out_do_frame ())
+         dwarf2out_frame_debug (insn);
+#else
+       if (!ACCUMULATE_OUTGOING_ARGS
+           && GET_CODE (insn) == INSN
+           && dwarf2out_do_frame ())
+         dwarf2out_frame_debug (insn);
 #endif
-         }
 #endif
 
 #if 0
@@ -3120,7 +3058,8 @@ cleanup_subreg_operands (insn)
       if (GET_CODE (recog_data.operand[i]) == SUBREG)
        recog_data.operand[i] = alter_subreg (recog_data.operand[i]);
       else if (GET_CODE (recog_data.operand[i]) == PLUS
-              || GET_CODE (recog_data.operand[i]) == MULT)
+              || GET_CODE (recog_data.operand[i]) == MULT
+              || GET_CODE (recog_data.operand[i]) == MEM)
        recog_data.operand[i] = walk_alter_subreg (recog_data.operand[i]);
     }
 
@@ -3129,7 +3068,8 @@ cleanup_subreg_operands (insn)
       if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG)
        *recog_data.dup_loc[i] = alter_subreg (*recog_data.dup_loc[i]);
       else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
-              || GET_CODE (*recog_data.dup_loc[i]) == MULT)
+              || GET_CODE (*recog_data.dup_loc[i]) == MULT
+              || GET_CODE (*recog_data.dup_loc[i]) == MEM)
        *recog_data.dup_loc[i] = walk_alter_subreg (*recog_data.dup_loc[i]);
     }
 }
@@ -3153,33 +3093,23 @@ alter_subreg (x)
 
   if (GET_CODE (y) == REG)
     {
-      int regno;
-      /* If the word size is larger than the size of this register,
-        adjust the register number to compensate.  */
-      /* ??? Note that this just catches stragglers created by/for
-        integrate.  It would be better if we either caught these
-        earlier, or kept _all_ subregs until now and eliminate
-        gen_lowpart and friends.  */
-
-#ifdef ALTER_HARD_SUBREG
-      regno = ALTER_HARD_SUBREG (GET_MODE (x), SUBREG_WORD (x),
-                                GET_MODE (y), REGNO (y));
-#else
-      regno = REGNO (y) + SUBREG_WORD (x);
-#endif
+      int regno = subreg_hard_regno (x, 1);
+
       PUT_CODE (x, REG);
       REGNO (x) = regno;
+      ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
       /* This field has a different meaning for REGs and SUBREGs.  Make sure
         to clear it!  */
       x->used = 0;
     }
   else if (GET_CODE (y) == MEM)
     {
-      register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+      register int offset = SUBREG_BYTE (x);
+
+      /* Catch these instead of generating incorrect code.  */
+      if ((offset % GET_MODE_SIZE (GET_MODE (x))) != 0)
+       abort ();
 
-      if (BYTES_BIG_ENDIAN)
-       offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
-                  - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
       PUT_CODE (x, MEM);
       MEM_COPY_ATTRIBUTES (x, y);
       XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
@@ -3388,10 +3318,7 @@ output_operand_lossage (msgid)
   if (this_is_asm_operands)
     error_for_asm (this_is_asm_operands, "invalid `asm': %s", _(msgid));
   else
-    {
-      error ("output_operand: %s", _(msgid));
-      abort ();
-    }
+    internal_error ("output_operand: %s", _(msgid));
 }
 \f
 /* Output of assembler code from a template, and its subroutines.  */
@@ -3673,14 +3600,16 @@ output_addr_const (file, x)
       break;
 
     case SYMBOL_REF:
+#ifdef ASM_OUTPUT_SYMBOL_REF
+      ASM_OUTPUT_SYMBOL_REF (file, x);
+#else
       assemble_name (file, XSTR (x, 0));
+#endif
       break;
 
     case LABEL_REF:
-      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
-      assemble_name (file, buf);
-      break;
-
+      x = XEXP (x, 0);
+      /* Fall through.  */
     case CODE_LABEL:
       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
       assemble_name (file, buf);
@@ -3726,7 +3655,8 @@ output_addr_const (file, x)
       else
        {
          output_addr_const (file, XEXP (x, 0));
-         if (INTVAL (XEXP (x, 1)) >= 0)
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT
+             || INTVAL (XEXP (x, 1)) >= 0)
            fprintf (file, "+");
          output_addr_const (file, XEXP (x, 1));
        }
@@ -3741,8 +3671,9 @@ output_addr_const (file, x)
 
       output_addr_const (file, XEXP (x, 0));
       fprintf (file, "-");
-      if (GET_CODE (XEXP (x, 1)) == CONST_INT
-         && INTVAL (XEXP (x, 1)) < 0)
+      if ((GET_CODE (XEXP (x, 1)) == CONST_INT
+          && INTVAL (XEXP (x, 1)) < 0)
+         || GET_CODE (XEXP (x, 1)) != CONST_INT)
        {
          fprintf (file, "%s", ASM_OPEN_PAREN);
          output_addr_const (file, XEXP (x, 1));
@@ -3758,6 +3689,12 @@ output_addr_const (file, x)
       break;
 
     default:
+#ifdef OUTPUT_ADDR_CONST_EXTRA
+      OUTPUT_ADDR_CONST_EXTRA (file, x, fail);
+      break;
+
+    fail:
+#endif
       output_operand_lossage ("invalid expression as operand");
     }
 }
@@ -4114,6 +4051,7 @@ int
 leaf_function_p ()
 {
   rtx insn;
+  rtx link;
 
   if (profile_flag || profile_block_flag || profile_arc_flag)
     return 0;
@@ -4129,23 +4067,44 @@ leaf_function_p ()
          && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
        return 0;
     }
-  for (insn = current_function_epilogue_delay_list;
-       insn;
-       insn = XEXP (insn, 1))
+  for (link = current_function_epilogue_delay_list;
+       link;
+       link = XEXP (link, 1))
     {
-      if (GET_CODE (XEXP (insn, 0)) == CALL_INSN
+      insn = XEXP (link, 0);
+
+      if (GET_CODE (insn) == CALL_INSN
          && ! SIBLING_CALL_P (insn))
        return 0;
-      if (GET_CODE (XEXP (insn, 0)) == INSN
-         && GET_CODE (PATTERN (XEXP (insn, 0))) == SEQUENCE
-         && GET_CODE (XVECEXP (PATTERN (XEXP (insn, 0)), 0, 0)) == CALL_INSN
-         && ! SIBLING_CALL_P (XVECEXP (PATTERN (XEXP (insn, 0)), 0, 0)))
+      if (GET_CODE (insn) == INSN
+         && GET_CODE (PATTERN (insn)) == SEQUENCE
+         && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN
+         && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
        return 0;
     }
 
   return 1;
 }
 
+/* Return 1 if branch is an forward branch.
+   Uses insn_shuid array, so it works only in the final pass.  May be used by
+   output templates to customary add branch prediction hints.
+ */
+int
+final_forward_branch_p (insn)
+     rtx insn;
+{
+  int insn_id, label_id;
+  if (!uid_shuid)
+    abort ();
+  insn_id = INSN_SHUID (insn);
+  label_id = INSN_SHUID (JUMP_LABEL (insn));
+  /* We've hit some insns that does not have id information available.  */
+  if (!insn_id || !label_id)
+    abort ();
+  return insn_id < label_id;
+}
+
 /* On some machines, a function with no call insns
    can run faster if it doesn't create its own register window.
    When output, the leaf function should use only the "output"