OSDN Git Service

PR debug/43516
[pf3gnuchains/gcc-fork.git] / gcc / gensupport.c
index dbf0aab..74b1d25 100644 (file)
@@ -1,12 +1,12 @@
 /* Support routines for the various generation passes.
 /* Support routines for the various generation passes.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, Free Software Foundation, Inc.
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GCC is distributed in the hope that it will be useful, but WITHOUT
    any later version.
 
    GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -15,9 +15,8 @@
    License for more details.
 
    You should have received a copy of the GNU General Public License
    License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 #include "bconfig.h"
 #include "system.h"
 
 #include "bconfig.h"
 #include "system.h"
@@ -118,6 +117,7 @@ static void process_define_cond_exec (void);
 static void process_include (rtx, int);
 static char *save_string (const char *, int);
 static void init_predicate_table (void);
 static void process_include (rtx, int);
 static char *save_string (const char *, int);
 static void init_predicate_table (void);
+static void record_insn_name (int, const char *);
 \f
 void
 message_with_line (int lineno, const char *msg, ...)
 \f
 void
 message_with_line (int lineno, const char *msg, ...)
@@ -286,6 +286,10 @@ process_rtx (rtx desc, int lineno)
 
     case DEFINE_PREDICATE:
     case DEFINE_SPECIAL_PREDICATE:
 
     case DEFINE_PREDICATE:
     case DEFINE_SPECIAL_PREDICATE:
+    case DEFINE_CONSTRAINT:
+    case DEFINE_REGISTER_CONSTRAINT:
+    case DEFINE_MEMORY_CONSTRAINT:
+    case DEFINE_ADDRESS_CONSTRAINT:
       queue_pattern (desc, &define_pred_tail, read_rtx_filename, lineno);
       break;
 
       queue_pattern (desc, &define_pred_tail, read_rtx_filename, lineno);
       break;
 
@@ -332,7 +336,7 @@ process_rtx (rtx desc, int lineno)
 
        /* Queue them.  */
        insn_elem
 
        /* Queue them.  */
        insn_elem
-         = queue_pattern (desc, &define_insn_tail, read_rtx_filename, 
+         = queue_pattern (desc, &define_insn_tail, read_rtx_filename,
                           lineno);
        split_elem
          = queue_pattern (split, &other_tail, read_rtx_filename, lineno);
                           lineno);
        split_elem
          = queue_pattern (split, &other_tail, read_rtx_filename, lineno);
@@ -463,6 +467,8 @@ identify_predicable_attribute (void)
       message_with_line (elem->lineno,
                         "attribute `predicable' is not a boolean");
       errors = 1;
       message_with_line (elem->lineno,
                         "attribute `predicable' is not a boolean");
       errors = 1;
+      if (p_false)
+        free (p_false);
       return;
     }
   p_true[-1] = '\0';
       return;
     }
   p_true[-1] = '\0';
@@ -480,12 +486,16 @@ identify_predicable_attribute (void)
       message_with_line (elem->lineno,
                         "attribute `predicable' cannot be const");
       errors = 1;
       message_with_line (elem->lineno,
                         "attribute `predicable' cannot be const");
       errors = 1;
+      if (p_false)
+       free (p_false);
       return;
 
     default:
       message_with_line (elem->lineno,
                         "attribute `predicable' must have a constant default");
       errors = 1;
       return;
 
     default:
       message_with_line (elem->lineno,
                         "attribute `predicable' must have a constant default");
       errors = 1;
+      if (p_false)
+       free (p_false);
       return;
     }
 
       return;
     }
 
@@ -499,6 +509,8 @@ identify_predicable_attribute (void)
                         "unknown value `%s' for `predicable' attribute",
                         value);
       errors = 1;
                         "unknown value `%s' for `predicable' attribute",
                         value);
       errors = 1;
+      if (p_false)
+       free (p_false);
     }
 }
 
     }
 }
 
@@ -768,6 +780,7 @@ process_one_cond_exec (struct queue_elem *ce_elem)
     {
       int alternatives, max_operand;
       rtx pred, insn, pattern, split;
     {
       int alternatives, max_operand;
       rtx pred, insn, pattern, split;
+      char *new_name;
       int i;
 
       if (! is_predicable (insn_elem))
       int i;
 
       if (! is_predicable (insn_elem))
@@ -794,7 +807,9 @@ process_one_cond_exec (struct queue_elem *ce_elem)
 
       /* Construct a new pattern for the new insn.  */
       insn = copy_rtx (insn_elem->data);
 
       /* Construct a new pattern for the new insn.  */
       insn = copy_rtx (insn_elem->data);
-      XSTR (insn, 0) = "";
+      new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4);
+      sprintf (new_name, "*p %s", XSTR (insn_elem->data, 0));
+      XSTR (insn, 0) = new_name;
       pattern = rtx_alloc (COND_EXEC);
       XEXP (pattern, 0) = pred;
       if (XVECLEN (insn, 1) == 1)
       pattern = rtx_alloc (COND_EXEC);
       XEXP (pattern, 0) = pred;
       if (XVECLEN (insn, 1) == 1)
@@ -863,7 +878,7 @@ process_one_cond_exec (struct queue_elem *ce_elem)
          XVECEXP (split, 2, i) = pattern;
        }
       /* Add the new split to the queue.  */
          XVECEXP (split, 2, i) = pattern;
        }
       /* Add the new split to the queue.  */
-      queue_pattern (split, &other_tail, read_rtx_filename, 
+      queue_pattern (split, &other_tail, read_rtx_filename,
                     insn_elem->split->lineno);
     }
 }
                     insn_elem->split->lineno);
     }
 }
@@ -901,90 +916,148 @@ int
 init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *))
 {
   FILE *input_file;
 init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *))
 {
   FILE *input_file;
-  int i, lineno;
-  size_t ix;
+  int c, i, lineno;
   char *lastsl;
   rtx desc;
   char *lastsl;
   rtx desc;
+  bool no_more_options;
+  bool already_read_stdin;
 
 
+  /* Unlock the stdio streams.  */
+  unlock_std_streams ();
+
+  /* First we loop over all the options.  */
   for (i = 1; i < argc; i++)
     {
       if (argv[i][0] != '-')
   for (i = 1; i < argc; i++)
     {
       if (argv[i][0] != '-')
-       {
-         if (in_fname)
-           fatal ("too many input files");
+       continue;
 
 
-         in_fname = argv[i];
-       }
-      else
+      c = argv[i][1];
+      switch (c)
        {
        {
-         int c = argv[i][1];
-         switch (c)
-           {
-           case 'I':           /* Add directory to path for includes.  */
-             {
-               struct file_name_list *dirtmp;
-
-               dirtmp = XNEW (struct file_name_list);
-               dirtmp->next = 0;       /* New one goes on the end */
-               if (first_dir_md_include == 0)
-                 first_dir_md_include = dirtmp;
-               else
-                 last_dir_md_include->next = dirtmp;
-               last_dir_md_include = dirtmp;   /* Tail follows the last one */
-               if (argv[i][1] == 'I' && argv[i][2] != 0)
-                 dirtmp->fname = argv[i] + 2;
-               else if (i + 1 == argc)
-                 fatal ("directory name missing after -I option");
-               else
-                 dirtmp->fname = argv[++i];
-               if (strlen (dirtmp->fname) > max_include_len)
-                 max_include_len = strlen (dirtmp->fname);
-             }
-             break;
-           default:
-             /* The program may have provided a callback so it can
-                accept its own options.  */
-             if (parse_opt && parse_opt (argv[i]))
-               break;
-
-             fatal ("invalid option `%s'", argv[i]);
-           }
-       }
-    }
+       case 'I':               /* Add directory to path for includes.  */
+         {
+           struct file_name_list *dirtmp;
+
+           dirtmp = XNEW (struct file_name_list);
+           dirtmp->next = 0;   /* New one goes on the end */
+           if (first_dir_md_include == 0)
+             first_dir_md_include = dirtmp;
+           else
+             last_dir_md_include->next = dirtmp;
+           last_dir_md_include = dirtmp;       /* Tail follows the last one */
+           if (argv[i][1] == 'I' && argv[i][2] != 0)
+             dirtmp->fname = argv[i] + 2;
+           else if (i + 1 == argc)
+             fatal ("directory name missing after -I option");
+           else
+             dirtmp->fname = argv[++i];
+           if (strlen (dirtmp->fname) > max_include_len)
+             max_include_len = strlen (dirtmp->fname);
+         }
+         break;
 
 
-  if (!in_fname)
-    fatal ("no input file name");
+       case '\0':
+         /* An argument consisting of exactly one dash is a request to
+            read stdin.  This will be handled in the second loop.  */
+         continue;
 
 
-  lastsl = strrchr (in_fname, '/');
-  if (lastsl != NULL)
-    base_dir = save_string (in_fname, lastsl - in_fname + 1 );
+       case '-':
+         /* An argument consisting of just two dashes causes option
+            parsing to cease.  */
+         if (argv[i][2] == '\0')
+           goto stop_parsing_options;
 
 
-  read_rtx_filename = in_fname;
-  input_file = fopen (in_fname, "r");
-  if (input_file == 0)
-    {
-      perror (in_fname);
-      return FATAL_EXIT_CODE;
-    }
+       default:
+         /* The program may have provided a callback so it can
+            accept its own options.  */
+         if (parse_opt && parse_opt (argv[i]))
+           break;
 
 
-  /* Initialize the table of insn conditions.  */
-  condition_table = htab_create (n_insn_conditions,
-                                hash_c_test, cmp_c_test, NULL);
+         fatal ("invalid option `%s'", argv[i]);
+       }
+    }
 
 
-  for (ix = 0; ix < n_insn_conditions; ix++)
-    *(htab_find_slot (condition_table, &insn_conditions[ix], INSERT))
-      = (void *) &insn_conditions[ix];
+ stop_parsing_options:
 
 
+  /* Prepare to read input.  */
+  condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
   init_predicate_table ();
   init_predicate_table ();
-
   obstack_init (rtl_obstack);
   errors = 0;
   sequence_num = 0;
   obstack_init (rtl_obstack);
   errors = 0;
   sequence_num = 0;
+  no_more_options = false;
+  already_read_stdin = false;
 
 
-  /* Read the entire file.  */
-  while (read_rtx (input_file, &desc, &lineno))
-    process_rtx (desc, lineno);
-  fclose (input_file);
+
+  /* Now loop over all input files.  */
+  for (i = 1; i < argc; i++)
+    {
+      if (argv[i][0] == '-')
+       {
+         if (argv[i][1] == '\0')
+           {
+             /* Read stdin.  */
+             if (already_read_stdin)
+               fatal ("cannot read standard input twice");
+
+             base_dir = NULL;
+             read_rtx_filename = in_fname = "<stdin>";
+             read_rtx_lineno = 1;
+             input_file = stdin;
+             already_read_stdin = true;
+
+             while (read_rtx (input_file, &desc, &lineno))
+               process_rtx (desc, lineno);
+             fclose (input_file);
+             continue;
+           }
+         else if (argv[i][1] == '-' && argv[i][2] == '\0')
+           {
+             /* No further arguments are to be treated as options.  */
+             no_more_options = true;
+             continue;
+           }
+         else if (!no_more_options)
+           continue;
+       }
+
+      /* If we get here we are looking at a non-option argument, i.e.
+        a file to be processed.  */
+
+      in_fname = argv[i];
+      lastsl = strrchr (in_fname, '/');
+      if (lastsl != NULL)
+       base_dir = save_string (in_fname, lastsl - in_fname + 1 );
+      else
+       base_dir = NULL;
+
+      read_rtx_filename = in_fname;
+      read_rtx_lineno = 1;
+      input_file = fopen (in_fname, "r");
+      if (input_file == 0)
+       {
+         perror (in_fname);
+         return FATAL_EXIT_CODE;
+       }
+
+      while (read_rtx (input_file, &desc, &lineno))
+       process_rtx (desc, lineno);
+      fclose (input_file);
+    }
+
+  /* If we get to this point without having seen any files to process,
+     read standard input now.  */
+  if (!in_fname)
+    {
+      base_dir = NULL;
+      read_rtx_filename = in_fname = "<stdin>";
+      read_rtx_lineno = 1;
+      input_file = stdin;
+
+      while (read_rtx (input_file, &desc, &lineno))
+       process_rtx (desc, lineno);
+      fclose (input_file);
+    }
 
   /* Process define_cond_exec patterns.  */
   if (define_cond_exec_queue != NULL)
 
   /* Process define_cond_exec patterns.  */
   if (define_cond_exec_queue != NULL)
@@ -1046,6 +1119,10 @@ read_md_rtx (int *lineno, int *seqnr)
        sequence_num++;
       else if (insn_elision)
        goto discard;
        sequence_num++;
       else if (insn_elision)
        goto discard;
+
+      /* *seqnr is used here so the name table will match caller's
+        idea of insn numbering, whether or not elision is active.  */
+      record_insn_name (*seqnr, XSTR (desc, 0));
       break;
 
     case DEFINE_SPLIT:
       break;
 
     case DEFINE_SPLIT:
@@ -1116,16 +1193,41 @@ maybe_eval_c_test (const char *expr)
   if (expr[0] == 0)
     return 1;
 
   if (expr[0] == 0)
     return 1;
 
-  if (insn_elision_unavailable)
-    return -1;
-
   dummy.expr = expr;
   test = (const struct c_test *)htab_find (condition_table, &dummy);
   dummy.expr = expr;
   test = (const struct c_test *)htab_find (condition_table, &dummy);
-  gcc_assert (test);
-
+  if (!test)
+    return -1;
   return test->value;
 }
 
   return test->value;
 }
 
+/* Record the C test expression EXPR in the condition_table, with
+   value VAL.  Duplicates clobber previous entries.  */
+
+void
+add_c_test (const char *expr, int value)
+{
+  struct c_test *test;
+
+  if (expr[0] == 0)
+    return;
+
+  test = XNEW (struct c_test);
+  test->expr = expr;
+  test->value = value;
+
+  *(htab_find_slot (condition_table, test, INSERT)) = test;
+}
+
+/* For every C test, call CALLBACK with two arguments: a pointer to
+   the condition structure and INFO.  Stops when CALLBACK returns zero.  */
+void
+traverse_c_tests (htab_trav callback, void *info)
+{
+  if (condition_table)
+    htab_traverse (condition_table, callback, info);
+}
+
+
 /* Given a string, return the number of comma-separated elements in it.
    Return 0 for the null string.  */
 int
 /* Given a string, return the number of comma-separated elements in it.
    Return 0 for the null string.  */
 int
@@ -1197,7 +1299,35 @@ lookup_predicate (const char *name)
 {
   struct pred_data key;
   key.name = name;
 {
   struct pred_data key;
   key.name = name;
-  return htab_find (predicate_table, &key);
+  return (struct pred_data *) htab_find (predicate_table, &key);
+}
+
+/* Record that predicate PRED can accept CODE.  */
+
+void
+add_predicate_code (struct pred_data *pred, enum rtx_code code)
+{
+  if (!pred->codes[code])
+    {
+      pred->num_codes++;
+      pred->codes[code] = true;
+
+      if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
+       pred->allows_non_const = true;
+
+      if (code != REG
+         && code != SUBREG
+         && code != MEM
+         && code != CONCAT
+         && code != PARALLEL
+         && code != STRICT_LOW_PART)
+       pred->allows_non_lvalue = true;
+
+      if (pred->num_codes == 1)
+       pred->singleton = code;
+      else if (pred->num_codes == 2)
+       pred->singleton = UNKNOWN;
+    }
 }
 
 void
 }
 
 void
@@ -1215,64 +1345,45 @@ add_predicate (struct pred_data *pred)
 }
 
 /* This array gives the initial content of the predicate table.  It
 }
 
 /* This array gives the initial content of the predicate table.  It
-   has entries for all predicates defined in recog.c.  The back end
-   can define PREDICATE_CODES to give additional entries for the
-   table; this is considered an obsolete mechanism (use
-   define_predicate instead).  */
+   has entries for all predicates defined in recog.c.  */
 
 
-struct old_pred_table
+struct std_pred_table
 {
   const char *name;
 {
   const char *name;
+  bool special;
+  bool allows_const_p;
   RTX_CODE codes[NUM_RTX_CODE];
 };
 
   RTX_CODE codes[NUM_RTX_CODE];
 };
 
-static const struct old_pred_table old_preds[] = {
-  {"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                      LABEL_REF, SUBREG, REG, MEM }},
-  {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                      LABEL_REF, SUBREG, REG, MEM,
-                      PLUS, MINUS, MULT}},
-  {"register_operand", {SUBREG, REG}},
-  {"pmode_register_operand", {SUBREG, REG}},
-  {"scratch_operand", {SCRATCH, REG}},
-  {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                        LABEL_REF}},
-  {"const_int_operand", {CONST_INT}},
-  {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
-  {"nonimmediate_operand", {SUBREG, REG, MEM}},
-  {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                        LABEL_REF, SUBREG, REG}},
-  {"push_operand", {MEM}},
-  {"pop_operand", {MEM}},
-  {"memory_operand", {SUBREG, MEM}},
-  {"indirect_operand", {SUBREG, MEM}},
-  {"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU,
-                          UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
-                          UNLT, LTGT}},
-#ifdef PREDICATE_CODES
-  PREDICATE_CODES
-#endif
+static const struct std_pred_table std_preds[] = {
+  {"general_operand", false, true, {SUBREG, REG, MEM}},
+  {"address_operand", true, true, {SUBREG, REG, MEM, PLUS, MINUS, MULT}},
+  {"register_operand", false, false, {SUBREG, REG}},
+  {"pmode_register_operand", true, false, {SUBREG, REG}},
+  {"scratch_operand", false, false, {SCRATCH, REG}},
+  {"immediate_operand", false, true, {UNKNOWN}},
+  {"const_int_operand", false, false, {CONST_INT}},
+  {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}},
+  {"nonimmediate_operand", false, false, {SUBREG, REG, MEM}},
+  {"nonmemory_operand", false, true, {SUBREG, REG}},
+  {"push_operand", false, false, {MEM}},
+  {"pop_operand", false, false, {MEM}},
+  {"memory_operand", false, false, {SUBREG, MEM}},
+  {"indirect_operand", false, false, {SUBREG, MEM}},
+  {"ordered_comparison_operator", false, false, {EQ, NE,
+                                                LE, LT, GE, GT,
+                                                LEU, LTU, GEU, GTU}},
+  {"comparison_operator", false, false, {EQ, NE,
+                                        LE, LT, GE, GT,
+                                        LEU, LTU, GEU, GTU,
+                                        UNORDERED, ORDERED,
+                                        UNEQ, UNGE, UNGT,
+                                        UNLE, UNLT, LTGT}}
 };
 };
-#define NUM_KNOWN_OLD_PREDS ARRAY_SIZE (old_preds)
-
-/* This table gives the initial set of special predicates.  It has
-   entries for all special predicates defined in recog.c.  The back
-   end can define SPECIAL_MODE_PREDICATES to give additional entries
-   for the table; this is considered an obsolete mechanism (use
-   define_special_predicate instead).  */
-static const char *const old_special_pred_table[] = {
-  "address_operand",
-  "pmode_register_operand",
-#ifdef SPECIAL_MODE_PREDICATES
-  SPECIAL_MODE_PREDICATES
-#endif
-};
-
-#define NUM_OLD_SPECIAL_MODE_PREDS ARRAY_SIZE (old_special_pred_table)
+#define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
 
 /* Initialize the table of predicate definitions, starting with
 
 /* Initialize the table of predicate definitions, starting with
-   the information we have on generic predicates, and the old-style
-   PREDICATE_CODES definitions.  */
+   the information we have on generic predicates.  */
 
 static void
 init_predicate_table (void)
 
 static void
 init_predicate_table (void)
@@ -1284,41 +1395,67 @@ init_predicate_table (void)
                                       eq_struct_pred_data, 0,
                                       xcalloc, free);
 
                                       eq_struct_pred_data, 0,
                                       xcalloc, free);
 
-  for (i = 0; i < NUM_KNOWN_OLD_PREDS; i++)
+  for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
     {
     {
-      pred = xcalloc (sizeof (struct pred_data), 1);
-      pred->name = old_preds[i].name;
+      pred = XCNEW (struct pred_data);
+      pred->name = std_preds[i].name;
+      pred->special = std_preds[i].special;
+
+      for (j = 0; std_preds[i].codes[j] != 0; j++)
+       add_predicate_code (pred, std_preds[i].codes[j]);
+
+      if (std_preds[i].allows_const_p)
+       for (j = 0; j < NUM_RTX_CODE; j++)
+         if (GET_RTX_CLASS (j) == RTX_CONST_OBJ)
+           add_predicate_code (pred, (enum rtx_code) j);
 
 
-      for (j = 0; old_preds[i].codes[j] != 0; j++)
-       {
-         enum rtx_code code = old_preds[i].codes[j];
-
-         pred->codes[code] = true;
-         if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
-           pred->allows_non_const = true;
-         if (code != REG
-             && code != SUBREG
-             && code != MEM
-             && code != CONCAT
-             && code != PARALLEL
-             && code != STRICT_LOW_PART)
-           pred->allows_non_lvalue = true;
-       }
-      if (j == 1)
-       pred->singleton = old_preds[i].codes[0];
-      
       add_predicate (pred);
     }
       add_predicate (pred);
     }
+}
+\f
+/* These functions allow linkage with print-rtl.c.  Also, some generators
+   like to annotate their output with insn names.  */
+
+/* Holds an array of names indexed by insn_code_number.  */
+static char **insn_name_ptr = 0;
+static int insn_name_ptr_size = 0;
 
 
-  for (i = 0; i < NUM_OLD_SPECIAL_MODE_PREDS; i++)
+const char *
+get_insn_name (int code)
+{
+  if (code < insn_name_ptr_size)
+    return insn_name_ptr[code];
+  else
+    return NULL;
+}
+
+static void
+record_insn_name (int code, const char *name)
+{
+  static const char *last_real_name = "insn";
+  static int last_real_code = 0;
+  char *new_name;
+
+  if (insn_name_ptr_size <= code)
     {
     {
-      pred = lookup_predicate (old_special_pred_table[i]);
-      if (!pred)
-       {
-         error ("old-style special predicate list refers "
-                "to unknown predicate '%s'", old_special_pred_table[i]);
-         continue;
-       }
-      pred->special = true;
+      int new_size;
+      new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
+      insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
+      memset (insn_name_ptr + insn_name_ptr_size, 0,
+             sizeof(char *) * (new_size - insn_name_ptr_size));
+      insn_name_ptr_size = new_size;
+    }
+
+  if (!name || name[0] == '\0')
+    {
+      new_name = XNEWVAR (char, strlen (last_real_name) + 10);
+      sprintf (new_name, "%s+%d", last_real_name, code - last_real_code);
+    }
+  else
+    {
+      last_real_name = new_name = xstrdup (name);
+      last_real_code = code;
     }
     }
+
+  insn_name_ptr[code] = new_name;
 }
 }