This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] insn mnemonic attribute v2
- From: "Andreas Krebbel" <krebbel at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: rth at redhat dot com
- Date: Fri, 12 Nov 2010 22:38:43 +0100
- Subject: [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