OSDN Git Service

Delete !REGISTER_CONSTRAINTS code
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index 4695590..5ef12ef 100644 (file)
@@ -49,6 +49,7 @@ Boston, MA 02111-1307, USA.  */
 
 #include "tree.h"
 #include "rtl.h"
+#include "tm_p.h"
 #include "regs.h"
 #include "insn-config.h"
 #include "insn-flags.h"
@@ -62,6 +63,7 @@ Boston, MA 02111-1307, USA.  */
 #include "defaults.h"
 #include "output.h"
 #include "except.h"
+#include "function.h"
 #include "toplev.h"
 #include "reload.h"
 #include "intl.h"
@@ -283,7 +285,9 @@ struct bb_str {
   int length;                  /* string length */
 };
 
+#ifdef HAVE_peephole
 extern rtx peephole            PROTO((rtx));
+#endif
 
 static struct bb_str *sbb_head = 0;            /* Head of string list.  */
 static struct bb_str **sbb_tail        = &sbb_head;    /* Ptr to store next bb str */
@@ -306,14 +310,12 @@ static void leaf_renumber_regs    PROTO((rtx));
 #ifdef HAVE_cc0
 static int alter_cond          PROTO((rtx));
 #endif
-
-extern char *getpwd ();
 \f
 /* Initialize data in final at the beginning of a compilation.  */
 
 void
 init_final (filename)
-     char *filename;
+     const char *filename ATTRIBUTE_UNUSED;
 {
   next_block_index = 2;
   app_on = 0;
@@ -424,9 +426,11 @@ end_final (filename)
       if (write_symbols != NO_DEBUG && profile_block_flag)
        {
          ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 5);
-         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, 1);
+         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
+                           pointer_bytes, 1);
          ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 6);
-         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, 1);
+         assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
+                           pointer_bytes, 1);
        }
       else
        {
@@ -796,27 +800,27 @@ get_attr_length (insn)
    address mod X to one mod Y, which is Y - X.  */
 
 #ifndef LABEL_ALIGN
-#define LABEL_ALIGN(LABEL) 0
+#define LABEL_ALIGN(LABEL) align_labels_log
 #endif
 
 #ifndef LABEL_ALIGN_MAX_SKIP
-#define LABEL_ALIGN_MAX_SKIP 0
+#define LABEL_ALIGN_MAX_SKIP (align_labels-1)
 #endif
 
 #ifndef LOOP_ALIGN
-#define LOOP_ALIGN(LABEL) 0
+#define LOOP_ALIGN(LABEL) align_loops_log
 #endif
 
 #ifndef LOOP_ALIGN_MAX_SKIP
-#define LOOP_ALIGN_MAX_SKIP 0
+#define LOOP_ALIGN_MAX_SKIP (align_loops-1)
 #endif
 
 #ifndef LABEL_ALIGN_AFTER_BARRIER
-#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
+#define LABEL_ALIGN_AFTER_BARRIER(LABEL) align_jumps_log
 #endif
 
 #ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
-#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0
+#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP (align_jumps-1)
 #endif
 
 #ifndef ADDR_VEC_ALIGN
@@ -999,7 +1003,9 @@ shorten_branches (first)
     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
       {
        rtx old = insn;
-       insn = try_split (PATTERN (old), old, 1);
+       /* Don't split the insn if it has been deleted.  */
+       if (! INSN_DELETED_P (old))
+         insn = try_split (PATTERN (old), old, 1);
        /* When not optimizing, the old insn will be still left around
           with only the 'deleted' bit set.  Transform it into a note
           to avoid confusion of subsequent processing.  */
@@ -1022,10 +1028,8 @@ shorten_branches (first)
 
   max_labelno = max_label_num ();
   min_labelno = get_first_label_num ();
-  label_align = (struct label_alignment *) xmalloc (
-    (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
-  bzero ((char *) label_align,
-    (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
+  label_align = (struct label_alignment *)
+    xcalloc ((max_labelno - min_labelno + 1), sizeof (struct label_alignment));
 
   uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
 
@@ -1111,18 +1115,32 @@ shorten_branches (first)
               && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
        {
          rtx label;
+         int nest = 0;
 
+         /* Search for the label that starts the loop.
+            Don't skip past the end of the loop, since that could
+            lead to putting an alignment where it does not belong.
+            However, a label after a nested (non-)loop would be OK.  */
          for (label = insn; label; label = NEXT_INSN (label))
-           if (GET_CODE (label) == CODE_LABEL)
-             {
-               log = LOOP_ALIGN (insn);
-               if (max_log < log)
-                 {
-                   max_log = log;
-                   max_skip = LOOP_ALIGN_MAX_SKIP;
-                 }
+           {
+             if (GET_CODE (label) == NOTE
+                 && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_BEG)
+               nest++;
+             else if (GET_CODE (label) == NOTE
+                      && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_END
+                      && --nest == 0)
                break;
-             }
+             else if (GET_CODE (label) == CODE_LABEL)
+               {
+                 log = LOOP_ALIGN (insn);
+                 if (max_log < log)
+                   {
+                     max_log = log;
+                     max_skip = LOOP_ALIGN_MAX_SKIP;
+                   }
+                 break;
+               }
+           }
        }
       else
        continue;
@@ -1131,24 +1149,19 @@ shorten_branches (first)
 
   /* Allocate the rest of the arrays.  */
   insn_lengths = (short *) xmalloc (max_uid * sizeof (short));
-  insn_addresses = (int *) xmalloc (max_uid * sizeof (int));
   insn_lengths_max_uid = max_uid;
   /* Syntax errors can lead to labels being outside of the main insn stream.
      Initialize insn_addresses, so that we get reproducible results.  */
-  bzero ((char *)insn_addresses, max_uid * sizeof *insn_addresses);
-  uid_align = (rtx *) xmalloc (max_uid * sizeof *uid_align);
+  insn_addresses = (int *) xcalloc (max_uid, sizeof (int));
 
-  varying_length = (char *) xmalloc (max_uid * sizeof (char));
-
-  bzero (varying_length, max_uid);
+  varying_length = (char *) xcalloc (max_uid, sizeof (char));
 
   /* Initialize uid_align.  We scan instructions
      from end to start, and keep in align_tab[n] the last seen insn
      that does an alignment of at least n+1, i.e. the successor
      in the alignment chain for an insn that does / has a known
      alignment of n.  */
-
-  bzero ((char *) uid_align, max_uid * sizeof *uid_align);
+  uid_align = (rtx *) xcalloc (max_uid, sizeof *uid_align);
 
   for (i = MAX_CODE_ALIGN; --i >= 0; )
     align_tab[i] = NULL_RTX;
@@ -1581,7 +1594,7 @@ void
 final_start_function (first, file, optimize)
      rtx first;
      FILE *file;
-     int optimize;
+     int optimize ATTRIBUTE_UNUSED;
 {
   block_depth = 0;
 
@@ -1773,9 +1786,9 @@ profile_function (file)
 
 void
 final_end_function (first, file, optimize)
-     rtx first;
+     rtx first ATTRIBUTE_UNUSED;
      FILE *file;
-     int optimize;
+     int optimize ATTRIBUTE_UNUSED;
 {
   if (app_on)
     {
@@ -2022,6 +2035,27 @@ final (first, file, optimize, prescan)
   free_insn_eh_region ();
 }
 \f
+const char *
+get_insn_template (code, insn)
+     int code;
+     rtx insn;
+{
+  const void *output = insn_data[code].output;
+  switch (insn_data[code].output_format)
+    {
+    case INSN_OUTPUT_FORMAT_SINGLE:
+      return (const char *) output;
+    case INSN_OUTPUT_FORMAT_MULTI:
+      return ((const char * const *) output)[which_alternative];
+    case INSN_OUTPUT_FORMAT_FUNCTION:
+      if (insn == NULL)
+       abort ();
+      return (* (insn_output_fn) output) (recog_data.operand, insn);
+
+    default:
+      abort ();
+    }
+}
 /* The final scan for one insn, INSN.
    Args are same as in `final', except that INSN
    is the insn being scanned.
@@ -2066,11 +2100,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
          && ! exceptions_via_longjmp)
        {
-         ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_BLOCK_NUMBER (insn));
+         ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_EH_HANDLER (insn));
           if (! flag_new_exceptions)
-            add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
+            add_eh_table_entry (NOTE_EH_HANDLER (insn));
 #ifdef ASM_OUTPUT_EH_REGION_BEG
-         ASM_OUTPUT_EH_REGION_BEG (file, NOTE_BLOCK_NUMBER (insn));
+         ASM_OUTPUT_EH_REGION_BEG (file, NOTE_EH_HANDLER (insn));
 #endif
          break;
        }
@@ -2078,11 +2112,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
          && ! exceptions_via_longjmp)
        {
-         ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_BLOCK_NUMBER (insn));
+         ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_EH_HANDLER (insn));
           if (flag_new_exceptions)
-            add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
+            add_eh_table_entry (NOTE_EH_HANDLER (insn));
 #ifdef ASM_OUTPUT_EH_REGION_END
-         ASM_OUTPUT_EH_REGION_END (file, NOTE_BLOCK_NUMBER (insn));
+         ASM_OUTPUT_EH_REGION_END (file, NOTE_EH_HANDLER (insn));
 #endif
          break;
        }
@@ -2810,6 +2844,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
 #endif
 
+#ifdef HAVE_peephole
        /* Do machine-specific peephole optimizations if desired.  */
 
        if (optimize && !flag_no_peephole && !nopeepholes)
@@ -2840,6 +2875,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
            /* PEEPHOLE might have changed this.  */
            body = PATTERN (insn);
          }
+#endif
 
        /* Try to recognize the instruction.
           If successful, verify that the operands satisfy the
@@ -2850,16 +2886,14 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        extract_insn (insn);
        cleanup_subreg_operands (insn);
 
-#ifdef REGISTER_CONSTRAINTS
        if (! constrain_operands (1))
          fatal_insn_not_found (insn);
-#endif
 
        /* Some target machines need to prescan each insn before
           it is output.  */
 
 #ifdef FINAL_PRESCAN_INSN
-       FINAL_PRESCAN_INSN (insn, recog_operand, recog_n_operands);
+       FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands);
 #endif
 
 #ifdef HAVE_cc0
@@ -2881,24 +2915,18 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          dwarf2out_frame_debug (insn);
 #endif
 
-       /* If the proper template needs to be chosen by some C code,
-          run that code and get the real template.  */
+       /* Find the proper template for this insn.  */
+       template = get_insn_template (insn_code_number, insn);
 
-       template = insn_template[insn_code_number];
+       /* If the C code returns 0, it means that it is a jump insn
+          which follows a deleted test insn, and that test insn
+          needs to be reinserted.  */
        if (template == 0)
          {
-           template = (*insn_outfun[insn_code_number]) (recog_operand, insn);
-
-           /* If the C code returns 0, it means that it is a jump insn
-              which follows a deleted test insn, and that test insn
-              needs to be reinserted.  */
-           if (template == 0)
-             {
-               if (prev_nonnote_insn (insn) != last_ignored_compare)
-                 abort ();
-               new_block = 0;
-               return prev_nonnote_insn (insn);
-             }
+           if (prev_nonnote_insn (insn) != last_ignored_compare)
+             abort ();
+           new_block = 0;
+           return prev_nonnote_insn (insn);
          }
 
        /* If the template is the string "#", it means that this insn must
@@ -2927,7 +2955,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
        /* Output assembler code from the template.  */
 
-       output_asm_insn (template, recog_operand);
+       output_asm_insn (template, recog_data.operand);
 
 #if defined (DWARF2_UNWIND_INFO)
 #if !defined (ACCUMULATE_OUTGOING_ARGS)
@@ -2965,7 +2993,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
 static void
 output_source_line (file, insn)
-     FILE *file;
+     FILE *file ATTRIBUTE_UNUSED;
      rtx insn;
 {
   register char *filename = NOTE_SOURCE_FILE (insn);
@@ -3036,22 +3064,22 @@ cleanup_subreg_operands (insn)
   int i;
 
   extract_insn (insn);
-  for (i = 0; i < recog_n_operands; i++)
+  for (i = 0; i < recog_data.n_operands; i++)
     {
-      if (GET_CODE (recog_operand[i]) == SUBREG)
-        recog_operand[i] = alter_subreg (recog_operand[i]);
-      else if (GET_CODE (recog_operand[i]) == PLUS
-               || GET_CODE (recog_operand[i]) == MULT)
-       recog_operand[i] = walk_alter_subreg (recog_operand[i]);
+      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)
+       recog_data.operand[i] = walk_alter_subreg (recog_data.operand[i]);
     }
 
-  for (i = 0; i < recog_n_dups; i++)
+  for (i = 0; i < recog_data.n_dups; i++)
     {
-      if (GET_CODE (*recog_dup_loc[i]) == SUBREG)
-        *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]);
-      else if (GET_CODE (*recog_dup_loc[i]) == PLUS
-               || GET_CODE (*recog_dup_loc[i]) == MULT)
-        *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]);
+      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)
+        *recog_data.dup_loc[i] = walk_alter_subreg (*recog_data.dup_loc[i]);
     }
 }
 
@@ -3074,6 +3102,7 @@ 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
@@ -3081,13 +3110,14 @@ alter_subreg (x)
         earlier, or kept _all_ subregs until now and eliminate
         gen_lowpart and friends.  */
 
-      PUT_CODE (x, REG);
 #ifdef ALTER_HARD_SUBREG
-      REGNO (x) = ALTER_HARD_SUBREG(GET_MODE (x), SUBREG_WORD (x),
-                                   GET_MODE (y), REGNO (y));
+      regno = ALTER_HARD_SUBREG(GET_MODE (x), SUBREG_WORD (x),
+                               GET_MODE (y), REGNO (y));
 #else
-      REGNO (x) = REGNO (y) + SUBREG_WORD (x);
+      regno = REGNO (y) + SUBREG_WORD (x);
 #endif
+      PUT_CODE (x, REG);
+      REGNO (x) = regno;
       /* This field has a different meaning for REGs and SUBREGs.  Make sure
         to clear it!  */
       x->used = 0;
@@ -3307,7 +3337,10 @@ output_operand_lossage (msgid)
   if (this_is_asm_operands)
     error_for_asm (this_is_asm_operands, "invalid `asm': %s", _(msgid));
   else
-    fatal ("Internal compiler error, output_operand_lossage `%s'", _(msgid));
+    {
+      error ("output_operand: %s", _(msgid));
+      abort ();
+    }
 }
 \f
 /* Output of assembler code from a template, and its subroutines.  */
@@ -3339,11 +3372,13 @@ output_asm_name ()
        {
          register int num = INSN_CODE (debug_insn);
          fprintf (asm_out_file, "\t%s %d\t%s", 
-                  ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]);
-         if (insn_n_alternatives[num] > 1)
+                  ASM_COMMENT_START, INSN_UID (debug_insn),
+                  insn_data[num].name);
+         if (insn_data[num].n_alternatives > 1)
            fprintf (asm_out_file, "/%d", which_alternative + 1);
 #ifdef HAVE_ATTR_length
-         fprintf (asm_out_file, "\t[length = %d]", get_attr_length (debug_insn));
+         fprintf (asm_out_file, "\t[length = %d]",
+                  get_attr_length (debug_insn));
 #endif
          /* Clear this so only the first assembler insn
             of any rtl insn will get the special comment for -dp.  */
@@ -3397,9 +3432,10 @@ output_asm_insn (template, operands)
             DIALECT_NUMBER of strings ending with '|'.  */
          for (i = 0; i < dialect_number; i++)
            {
-             while (*p && *p++ != '|')
+             while (*p && *p != '}' && *p++ != '|')
                ;
-
+             if (*p == '}')
+               break;
              if (*p == '|')
                p++;
            }
@@ -3653,9 +3689,9 @@ output_addr_const (file, x)
       if (GET_CODE (XEXP (x, 1)) == CONST_INT
          && INTVAL (XEXP (x, 1)) < 0)
        {
-         fprintf (file, ASM_OPEN_PAREN);
+         fprintf (file, "%s", ASM_OPEN_PAREN);
          output_addr_const (file, XEXP (x, 1));
-         fprintf (file, ASM_CLOSE_PAREN);
+         fprintf (file, "%s", ASM_CLOSE_PAREN);
        }
       else
        output_addr_const (file, XEXP (x, 1));
@@ -3823,6 +3859,20 @@ asm_fprintf VPROTO((FILE *file, const char *p, ...))
            fputs (user_label_prefix, file);
            break;
 
+#ifdef ASM_FPRINTF_EXTENSIONS
+           /* Upper case letters are reserved for general use by asm_fprintf
+              and so are not available to target specific code.  In order to
+              prevent the ASM_FPRINTF_EXTENSIONS macro from using them then,
+              they are defined here.  As they get turned into real extensions
+              to asm_fprintf they should be removed from this list.  */
+         case 'A': case 'B': case 'C': case 'D': case 'E':
+         case 'F': case 'G': case 'H': case 'J': case 'K':
+         case 'M': case 'N': case 'P': case 'Q': case 'S':
+         case 'T': case 'V': case 'W': case 'Y': case 'Z':
+           break;
+           
+         ASM_FPRINTF_EXTENSIONS (file, argptr, p)
+#endif
          default:
            abort ();
          }
@@ -3831,6 +3881,7 @@ asm_fprintf VPROTO((FILE *file, const char *p, ...))
       default:
        fputc (c, file);
       }
+  va_end (argptr);
 }
 \f
 /* Split up a CONST_DOUBLE or integer constant rtx
@@ -4071,7 +4122,7 @@ leaf_renumber_regs_insn (in_rtx)
      register rtx in_rtx;
 {
   register int i, j;
-  register char *format_ptr;
+  register const char *format_ptr;
 
   if (in_rtx == 0)
     return;