This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] insn mnemonic attribute v2


Hi,

here is an updated version of the insn mnemonic attribute patch.

For a detailed explanation please see here:
http://gcc.gnu.org/ml/gcc-patches/2010-09/msg02265.html

This version addresses the comments from RTH in:
http://gcc.gnu.org/ml/gcc-patches/2010-11/msg00554.html

Tested on x86_64 and s390x with and without the
TARGET_WANT_MNEMONIC_ATTR definition.

Ok for mainline?

Bye,

-Andreas-


2010-11-12  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* genattr.c: Include obstack.h and hashtab.h.
	(mnemonic_htab, obstack1, hash_obstack): New global variables.
	(MNEMONIC_HTAB_SIZE): New macro.
	(mnemonic_htab_callback, add_mnemonic_string, make_mnemonic_attr)
	(mnemonic_callback, gen_insn, htab_eq_string): New functions.
	(gen_attr): Record values for existing mnemonic attribute
	definitions.
	(main): Initialize data structures and invoke make_mnemonic_attr.
	* genattrtab.c (add_attr_value): Moved here to avoid forward
	declarations.
	(add_value, mnemonic_callback, make_mnemonic_attr): New functions.
	(main): Invoke make_mnemonic_attr.
	* gensupport.c (find_mnemonics): New function.
	* gensupport.h (mnemonic_callback_t): New type definition.
	(find_mnemonics): Add prototype.
	* defaults.h (TARGET_WANT_MNEMONIC_ATTR): New target macro.
	* doc/tm.texi.in (TARGET_WANT_MNEMONIC_ATTR): Documentation added.
	* doc/tm.texi: Likewise.

Index: gcc/genattr.c
===================================================================
*** gcc/genattr.c.orig
--- gcc/genattr.c
*************** along with GCC; see the file COPYING3.
*** 28,33 ****
--- 28,35 ----
  #include "errors.h"
  #include "read-md.h"
  #include "gensupport.h"
+ #include "obstack.h"
+ #include "hashtab.h"
  
  
  static void write_upcase (const char *);
*************** write_upcase (const char *str)
*** 42,47 ****
--- 44,143 ----
  
  static VEC (rtx, heap) *const_attrs, *reservations;
  
+ static htab_t mnemonic_htab;
+ 
+ static struct obstack obstack1;
+ static struct obstack *hash_obstack = &obstack1;
+ 
+ #define MNEMONIC_HTAB_SIZE 1024
+ 
+ 
+ static int
+ mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
+ {
+   printf (", MNEMONIC_");
+   write_upcase ((char*)*slot);
+   return 1;
+ }
+ 
+ /* Store a permanent (possibly shared) copy of a mnemonic string STR
+    (not assumed to be null terminated) with LEN bytes into
+    mnemonic_htab.  */
+ 
+ static void
+ add_mnemonic_string (const char *str, int len)
+ {
+   char *new_str;
+   void **slot;
+   char *str_zero = (char*)alloca (len + 1);
+ 
+   memcpy (str_zero, str, len);
+   str_zero[len] = '\0';
+ 
+   slot = htab_find_slot (mnemonic_htab, str_zero, INSERT);
+ 
+   if (*slot)
+     return;
+ 
+   /* Not found; create a permanent copy and add it to the hash table.  */
+   new_str = XOBNEWVAR (hash_obstack, char, len + 1);
+   memcpy (new_str, str_zero, len + 1);
+   *slot = new_str;
+ }
+ 
+ /* Generate the enum for the mnemonic attribute.  */
+ 
+ static void
+ make_mnemonic_attr (void)
+ {
+   printf ("#define HAVE_ATTR_mnemonic\n");
+   printf ("enum attr_mnemonic { ");
+ 
+   /* Just here to prevent starting with a , */
+   printf ("MNEMONIC_NULL");
+   add_mnemonic_string ("unknown", strlen ("unknown"));
+   htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
+ 
+   printf (" };\n");
+   printf ("extern enum attr_mnemonic get_attr_mnemonic (rtx);\n");
+ }
+ 
+ /* Called by find_mnemonics and adds a permanent copy of the string in
+    STR into mnemonic_htab.  */
+ 
+ static void
+ mnemonic_callback (const char *str, void *data ATTRIBUTE_UNUSED)
+ {
+   char *new_str;
+   void **slot;
+   int len = strlen (str) + 1;
+ 
+   slot = htab_find_slot (mnemonic_htab, str, INSERT);
+ 
+   if (*slot)
+     return;
+ 
+   /* Not found; create a permanent copy and add it to the hash table.  */
+   new_str = XOBNEWVAR (hash_obstack, char, len);
+   memcpy (new_str, str, len);
+   *slot = new_str;
+ }
+ 
+ static void
+ gen_insn (rtx insn)
+ {
+   int i;
+ 
+   /* Skip if INSN already has a (set_attr "mnemonic" ...).  */
+   if (XVEC (insn, 4))
+     for (i = 0; i < XVECLEN (insn, 4); i++)
+       {
+ 	if (strcmp (XSTR (XVECEXP (insn, 4, i), 0), "mnemonic") == 0)
+ 	  return;
+       }
+ 
+   find_mnemonics (insn, mnemonic_callback, NULL);
+ }
  
  static void
  gen_attr (rtx attr)
*************** gen_attr (rtx attr)
*** 58,63 ****
--- 154,167 ----
    if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
      printf ("extern enum %s get_attr_%s (%s);\n\n",
  	    XSTR (attr, 1), XSTR (attr, 0), (is_const ? "void" : "rtx"));
+   else if (strcmp (XSTR (attr, 0), "mnemonic") == 0)
+     {
+       /* The mnemonic attribute will be laid out later after the
+ 	 md file has been processed completely.  */
+       p = XSTR (attr, 1);
+       while ((tag = scan_comma_elt (&p)) != 0)
+ 	add_mnemonic_string (tag, p - tag);
+     }
    else
      {
        p = XSTR (attr, 1);
*************** find_tune_attr (rtx exp)
*** 159,164 ****
--- 263,273 ----
        return false;
      }
  }
+ static int
+ htab_eq_string (const void *s1, const void *s2)
+ {
+   return strcmp ((const char*)s1, (const char*)s2) == 0;
+ }
  
  int
  main (int argc, char **argv)
*************** main (int argc, char **argv)
*** 175,180 ****
--- 284,302 ----
    if (!init_rtx_reader_args (argc, argv))
      return (FATAL_EXIT_CODE);
  
+   if (TARGET_WANT_MNEMONIC_ATTR)
+     {
+       obstack_init (hash_obstack);
+       mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string,
+ 					 htab_eq_string, 0, xcalloc, free);
+ 
+       if (!mnemonic_htab)
+ 	{
+ 	  error ("Out of memory");
+ 	  return FATAL_EXIT_CODE;
+ 	}
+     }
+ 
    puts ("/* Generated automatically by the program `genattr'");
    puts ("   from the machine description file `md'.  */\n");
    puts ("#ifndef GCC_INSN_ATTR_H");
*************** main (int argc, char **argv)
*** 196,202 ****
        if (desc == NULL)
  	break;
  
!       if (GET_CODE (desc) == DEFINE_ATTR
  	  || GET_CODE (desc) == DEFINE_ENUM_ATTR)
  	gen_attr (desc);
  
--- 318,327 ----
        if (desc == NULL)
  	break;
  
!       if (TARGET_WANT_MNEMONIC_ATTR && GET_CODE (desc) == DEFINE_INSN)
! 	gen_insn (desc);
!       else
! 	if (GET_CODE (desc) == DEFINE_ATTR
  	  || GET_CODE (desc) == DEFINE_ENUM_ATTR)
  	gen_attr (desc);
  
*************** main (int argc, char **argv)
*** 376,381 ****
--- 501,509 ----
    printf("#define ATTR_FLAG_unlikely\t0x10\n");
    printf("#define ATTR_FLAG_very_unlikely\t0x20\n");
  
+   if (TARGET_WANT_MNEMONIC_ATTR)
+     make_mnemonic_attr ();
+ 
    puts("\n#endif /* GCC_INSN_ATTR_H */");
  
    if (ferror (stdout) || fflush (stdout) || fclose (stdout))
Index: gcc/genattrtab.c
===================================================================
*** gcc/genattrtab.c.orig
--- gcc/genattrtab.c
*************** make_length_attrs (void)
*** 1561,1566 ****
--- 1561,1684 ----
      }
  }
  
+ /* Add attribute value NAME to the beginning of ATTR's list.  */
+ 
+ static void
+ add_attr_value (struct attr_desc *attr, const char *name)
+ {
+   struct attr_value *av;
+ 
+   av = oballoc (struct attr_value);
+   av->value = attr_rtx (CONST_STRING, name);
+   av->next = attr->first_value;
+   attr->first_value = av;
+   av->first_insn = NULL;
+   av->num_insns = 0;
+   av->has_asm_insn = 0;
+ }
+ 
+ /* Add STR to the value list of ATTR avoiding duplicate values.  */
+ 
+ static void
+ add_value (struct attr_desc *attr, const char *str, int len)
+ {
+   char *value = attr_string (str, len);
+   struct attr_value *av;
+ 
+   for (av = attr->first_value; av != NULL; av = av->next)
+     if (value == XSTR (av->value, 0))
+       return;
+ 
+   add_attr_value (attr, value);
+ }
+ 
+ /* This callback is invoked for every mnemonic string in the insn
+    definition as detected by find_mnemonics.  STR is the mnemonic
+    string and DATA holds a pointer to the mnemonic attribute
+    description.  */
+ 
+ static void
+ mnemonic_callback (const char *str, void *data)
+ {
+   struct attr_desc *attr = (struct attr_desc*)data;
+   int len = strlen (str);
+ 
+   add_value (attr, str, len);
+   if (obstack_next_free (&string_obstack) != obstack_base (&string_obstack))
+     obstack_1grow (&string_obstack, ',');
+   obstack_grow (&string_obstack, str, len);
+ }
+ 
+ /* Generate attribute definition as well as SET_ATTR expressions for
+    the mnemonic attribute.  */
+ 
+ static void
+ make_mnemonic_attr (void)
+ {
+   struct insn_def *id;
+   const char *attr_name = "mnemonic";
+   struct attr_desc *attr = find_attr (&attr_name, 1);
+ 
+   if (!attr->default_val)
+     {
+       /* The mnemonic attribute didn't exist before.  Define a
+ 	 default value.  */
+       add_attr_value (attr, attr_string ("UNKNOWN", strlen ("UNKNOWN")));
+       attr->default_val = attr->first_value;
+     }
+ 
+   for (id = defs; id; id = id->next)
+     {
+       bool found = false;
+       int i;
+       int num_mnemonics;
+       int len;
+       rtx set_attr;
+       rtvec new_vec;
+ 
+       if (id->insn_code == -1)
+ 	continue;
+ 
+       if (XVEC (id->def, id->vec_idx))
+ 	for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
+ 	  {
+ 	    if (!strcmp_check (XSTR (XVECEXP (id->def, id->vec_idx, i), 0),
+ 			       attr_name))
+ 	      found = true;
+ 	  }
+ 
+       /* Skip if the md file already specifies an "mnemonic"
+ 	 attribute for this insn.  */
+       if (found)
+         continue;
+ 
+       num_mnemonics = find_mnemonics (id->def, mnemonic_callback, attr);
+ 
+       if (num_mnemonics != id->num_alternatives)
+ 	{
+ 	  obstack_free (&string_obstack, obstack_finish (&string_obstack));
+ 	  continue;
+ 	}
+ 
+       obstack_1grow (&string_obstack, '\0');
+ 
+       set_attr = rtx_alloc (SET_ATTR);
+       XSTR (set_attr, 0) = attr_name;
+       XSTR (set_attr, 1) = XOBFINISH (&string_obstack, char *);
+ 
+       if (!XVEC (id->def, id->vec_idx))
+ 	len = 0;
+       else
+ 	len = XVECLEN (id->def, id->vec_idx);
+ 
+       new_vec = rtvec_alloc (len + 1);
+       for (i = 0; i < len; i++)
+ 	RTVEC_ELT (new_vec, i) = XVECEXP (id->def, id->vec_idx, i);
+       RTVEC_ELT (new_vec, len) = set_attr;
+       XVEC (id->def, id->vec_idx) = new_vec;
+     }
+ }
+ 
  /* Utility functions called from above routine.  */
  
  static rtx
*************** clear_struct_flag (rtx x)
*** 2901,2922 ****
      }
  }
  
- /* Add attribute value NAME to the beginning of ATTR's list.  */
- 
- static void
- add_attr_value (struct attr_desc *attr, const char *name)
- {
-   struct attr_value *av;
- 
-   av = oballoc (struct attr_value);
-   av->value = attr_rtx (CONST_STRING, name);
-   av->next = attr->first_value;
-   attr->first_value = av;
-   av->first_insn = NULL;
-   av->num_insns = 0;
-   av->has_asm_insn = 0;
- }
- 
  /* Create table entries for DEFINE_ATTR or DEFINE_ENUM_ATTR.  */
  
  static void
--- 3019,3024 ----
*************** from the machine description file `md'.
*** 4942,4947 ****
--- 5044,5053 ----
    /* Construct extra attributes for automata.  */
    make_automaton_attrs ();
  
+   /* Construct extra attribute for the insn mnemonic.  */
+   if (TARGET_WANT_MNEMONIC_ATTR)
+     make_mnemonic_attr ();
+ 
    /* Prepare to write out attribute subroutines by checking everything stored
       away and building the attribute cases.  */
  
Index: gcc/gensupport.c
===================================================================
*** gcc/gensupport.c.orig
--- gcc/gensupport.c
*************** record_insn_name (int code, const char *
*** 1149,1151 ****
--- 1149,1228 ----
  
    insn_name_ptr[code] = new_name;
  }
+ 
+ /* Invoke CALLBACK for every mnemonic string found in the insn
+    definition INSN.  DATA is passed as parameter to CALLBACK.  The
+    number of the detected mnemonics is returned.
+ 
+    The mnemonics cannot be found if they are emitted using C code.  In
+    that case the function returns 0.
+ 
+    If a mnemonic string contains ';' the string contains more than a
+    single instruction.  CALLBACK then is invoked with 'unknown' as
+    mnemonic.  */
+ 
+ int
+ find_mnemonics (rtx insn, mnemonic_callback_t callback, void *data)
+ {
+   const char *template_code;
+   const char *cp;
+   int i;
+   char str[255];
+ 
+   template_code = XTMPL (insn, 3);
+ 
+   /* Skip patterns which use C code to emit the template.  */
+   if (template_code[0] == '*')
+     return 0;
+ 
+   if (template_code[0] == '@')
+     cp = &template_code[1];
+   else
+     cp = &template_code[0];
+ 
+   for (i = 0; *cp; )
+     {
+       const char *ep, *sp;
+       int size = 0;
+ 
+       while (ISSPACE (*cp))
+ 	cp++;
+ 
+       for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
+ 	if (!ISSPACE (*ep))
+ 	  sp = ep + 1;
+ 
+       while (cp < sp && ((*cp >= '0' && *cp <= '9')
+ 			 || (*cp >= 'a' && *cp <= 'z')))
+ 
+ 	{
+ 	  str[size] = *cp;
+ 	  cp++;
+ 	  size++;
+ 	}
+ 
+       while (cp < sp)
+ 	{
+ 	  /* Don't return a mnemonic if there is more than one in the
+ 	     string.  */
+ 	  if (*cp == ';')
+ 	    {
+ 	      size = 0;
+ 
+ 	      while (cp < sp)
+ 		cp++;
+ 	    }
+ 	  cp++;
+ 	}
+ 
+       if (size == 0)
+ 	strcpy (str, "unknown");
+       else
+ 	str[size] = '\0';
+ 
+       callback (str, data);
+       i++;
+     }
+   return i;
+ }
+ 
Index: gcc/gensupport.h
===================================================================
*** gcc/gensupport.h.orig
--- gcc/gensupport.h
*************** extern struct pred_data *lookup_predicat
*** 81,86 ****
--- 81,90 ----
  extern void add_predicate_code (struct pred_data *, enum rtx_code);
  extern void add_predicate (struct pred_data *);
  
+ typedef void (*mnemonic_callback_t) (const char *, void *);
+ 
+ extern int find_mnemonics (rtx, mnemonic_callback_t, void *);
+ 
  #define FOR_ALL_PREDICATES(p) for (p = first_predicate; p; p = p->next)
  
  #endif /* GCC_GENSUPPORT_H */
Index: gcc/defaults.h
===================================================================
*** gcc/defaults.h.orig
--- gcc/defaults.h
*************** see the files COPYING3 and COPYING.RUNTI
*** 1184,1189 ****
--- 1184,1193 ----
  #define DEFAULT_PCC_STRUCT_RETURN 1
  #endif
  
+ #ifndef TARGET_WANT_MNEMONIC_ATTR
+ #define TARGET_WANT_MNEMONIC_ATTR 0
+ #endif
+ 
  #ifdef GCC_INSN_FLAGS_H
  /* Dependent default target macro definitions
  
Index: gcc/doc/tm.texi.in
===================================================================
*** gcc/doc/tm.texi.in.orig
--- gcc/doc/tm.texi.in
*************** value of @code{TARGET_CONST_ANCHOR} is a
*** 11247,11249 ****
--- 11247,11257 ----
  MIPS, where add-immediate takes a 16-bit signed value,
  @code{TARGET_CONST_ANCHOR} is set to @samp{0x8000}.  The default value
  is zero, which disables this optimization.  @end deftypevr
+ 
+ @defmac TARGET_WANT_MNEMONIC_ATTR
+ Define this macro to evaluate to true if you want the 'mnemonic' insn
+ attribute to be generated for the insn definitions in your back-end.
+ genattr and genattrtab then will try to parse the output template of
+ the insn definitions in order to generate a proper @code{(set_attr
+ "mnemonic" "...")} attribute definition.
+ @end defmac
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi.orig
--- gcc/doc/tm.texi
*************** value of @code{TARGET_CONST_ANCHOR} is a
*** 11287,11289 ****
--- 11287,11297 ----
  MIPS, where add-immediate takes a 16-bit signed value,
  @code{TARGET_CONST_ANCHOR} is set to @samp{0x8000}.  The default value
  is zero, which disables this optimization.  @end deftypevr
+ 
+ @defmac TARGET_WANT_MNEMONIC_ATTR
+ Define this macro to evaluate to true if you want the 'mnemonic' insn
+ attribute to be generated for the insn definitions in your back-end.
+ genattr and genattrtab then will try to parse the output template of
+ the insn definitions in order to generate a proper @code{(set_attr
+ "mnemonic" "...")} attribute definition.
+ @end defmac


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]