/* Generate code from to output assembler insns as recognized from rtl.
Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002,
- 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 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 the Free
-Software Foundation; either version 2, or (at your option) any later
+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
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This program reads the machine description for the compiler target machine
and produces a file containing these things:
- 1. An array of `struct insn_data', which is indexed by insn code number,
+ 1. An array of `struct insn_data_d', which is indexed by insn code number,
which contains:
a. `name' is the name for that pattern. Nameless patterns are
#include "tm.h"
#include "rtl.h"
#include "errors.h"
+#include "read-md.h"
#include "gensupport.h"
/* No instruction can have more operands than this. Sorry for this
{
struct data *next;
const char *name;
- const char *template;
+ const char *template_code;
int code_number;
int index_number;
const char *filename;
printf ("#include \"function.h\"\n");
printf ("#include \"regs.h\"\n");
printf ("#include \"hard-reg-set.h\"\n");
- printf ("#include \"real.h\"\n");
printf ("#include \"insn-config.h\"\n\n");
printf ("#include \"conditions.h\"\n");
printf ("#include \"insn-attr.h\"\n\n");
printf ("#include \"recog.h\"\n\n");
- printf ("#include \"toplev.h\"\n");
+ printf ("#include \"diagnostic-core.h\"\n");
printf ("#include \"output.h\"\n");
printf ("#include \"target.h\"\n");
printf ("#include \"tm-constrs.h\"\n");
printf (" %d,\n", d->strict_low);
+ printf (" %d,\n", d->constraint == NULL ? 1 : 0);
+
printf (" %d\n", d->eliminable);
printf(" },\n");
}
printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n");
- printf ("\nconst struct insn_data insn_data[] = \n{\n");
+ printf ("\nconst struct insn_data_d insn_data[] = \n{\n");
for (d = idata; d; d = d->next)
{
break;
case INSN_OUTPUT_FORMAT_SINGLE:
{
- const char *p = d->template;
+ const char *p = d->template_code;
char prev = 0;
printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
max_opno = opno;
if (max_opno >= MAX_MAX_OPERANDS)
{
- message_with_line (d->lineno,
- "maximum number of operands exceeded");
- have_error = 1;
+ error_with_line (d->lineno, "maximum number of operands exceeded");
return;
}
if (d->operand[opno].seen)
- {
- message_with_line (d->lineno,
- "repeated operand number %d\n", opno);
- have_error = 1;
- }
+ error_with_line (d->lineno, "repeated operand number %d\n", opno);
d->operand[opno].seen = 1;
d->operand[opno].mode = GET_MODE (part);
max_opno = opno;
if (max_opno >= MAX_MAX_OPERANDS)
{
- message_with_line (d->lineno,
- "maximum number of operands exceeded");
- have_error = 1;
+ error_with_line (d->lineno, "maximum number of operands exceeded");
return;
}
if (d->operand[opno].seen)
- {
- message_with_line (d->lineno,
- "repeated operand number %d\n", opno);
- have_error = 1;
- }
+ error_with_line (d->lineno, "repeated operand number %d\n", opno);
d->operand[opno].seen = 1;
d->operand[opno].mode = GET_MODE (part);
max_opno = opno;
if (max_opno >= MAX_MAX_OPERANDS)
{
- message_with_line (d->lineno,
- "maximum number of operands exceeded");
- have_error = 1;
+ error_with_line (d->lineno, "maximum number of operands exceeded");
return;
}
if (d->operand[opno].seen)
- {
- message_with_line (d->lineno,
- "repeated operand number %d\n", opno);
- have_error = 1;
- }
+ error_with_line (d->lineno, "repeated operand number %d\n", opno);
d->operand[opno].seen = 1;
d->operand[opno].mode = GET_MODE (part);
templates, or C code to generate the assembler code template. */
static void
-process_template (struct data *d, const char *template)
+process_template (struct data *d, const char *template_code)
{
const char *cp;
int i;
/* Templates starting with * contain straight code to be run. */
- if (template[0] == '*')
+ if (template_code[0] == '*')
{
- d->template = 0;
+ d->template_code = 0;
d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
puts ("\nstatic const char *");
printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n",
d->code_number);
puts ("{");
- print_rtx_ptr_loc (template);
- puts (template + 1);
+ print_md_ptr_loc (template_code);
+ puts (template_code + 1);
puts ("}");
}
/* If the assembler code template starts with a @ it is a newline-separated
list of assembler code templates, one for each alternative. */
- else if (template[0] == '@')
+ else if (template_code[0] == '@')
{
- d->template = 0;
+ d->template_code = 0;
d->output_format = INSN_OUTPUT_FORMAT_MULTI;
printf ("\nstatic const char * const output_%d[] = {\n", d->code_number);
- for (i = 0, cp = &template[1]; *cp; )
+ for (i = 0, cp = &template_code[1]; *cp; )
{
const char *ep, *sp;
message_with_line (d->lineno,
"'@' is redundant for output template with single alternative");
if (i != d->n_alternatives)
- {
- message_with_line (d->lineno,
- "wrong number of alternatives in the output template");
- have_error = 1;
- }
+ error_with_line (d->lineno,
+ "wrong number of alternatives in the output template");
printf ("};\n");
}
else
{
- d->template = template;
+ d->template_code = template_code;
d->output_format = INSN_OUTPUT_FORMAT_SINGLE;
}
}
if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c)))
{
- message_with_line (d->lineno,
- "invalid length %d for char '%c' in alternative %d of operand %d",
- len, c, which_alternative, start);
+ error_with_line (d->lineno,
+ "invalid length %d for char '%c' in"
+ " alternative %d of operand %d",
+ len, c, which_alternative, start);
len = 1;
- have_error = 1;
}
#endif
for (i = 1; i < len; i++)
if (p[i] == '\0')
{
- message_with_line (d->lineno,
- "NUL in alternative %d of operand %d",
- which_alternative, start);
+ error_with_line (d->lineno,
+ "NUL in alternative %d of operand %d",
+ which_alternative, start);
alternative_count_unsure = 1;
break;
}
else if (strchr (",#*", p[i]))
{
- message_with_line (d->lineno,
- "'%c' in alternative %d of operand %d",
- p[i], which_alternative, start);
+ error_with_line (d->lineno,
+ "'%c' in alternative %d of operand %d",
+ p[i], which_alternative, start);
alternative_count_unsure = 1;
}
}
- if (alternative_count_unsure)
- have_error = 1;
- else if (n == 0)
- n = d->operand[start].n_alternatives;
- else if (n != d->operand[start].n_alternatives)
+ if (!alternative_count_unsure)
{
- message_with_line (d->lineno,
+ if (n == 0)
+ n = d->operand[start].n_alternatives;
+ else if (n != d->operand[start].n_alternatives)
+ error_with_line (d->lineno,
"wrong number of alternatives in operand %d",
start);
- have_error = 1;
}
}
for (i = 0; i < d->n_operands; ++i)
if (d->operand[i].seen == 0)
- {
- message_with_line (d->lineno, "missing operand %d", i);
- have_error = 1;
- }
+ error_with_line (d->lineno, "missing operand %d", i);
+}
+
+static void
+validate_optab_operands (struct data *d)
+{
+ if (!d->name || d->name[0] == '\0' || d->name[0] == '*')
+ return;
+
+ /* Miscellaneous tests. */
+ if (strncmp (d->name, "cstore", 6) == 0
+ && d->name[strlen (d->name) - 1] == '4'
+ && d->operand[0].mode == VOIDmode)
+ {
+ message_with_line (d->lineno, "missing mode for operand 0 of cstore");
+ have_error = 1;
+ }
}
\f
/* Look at a define_insn just read. Assign its code number. Record
d->code_number = next_code_number;
d->index_number = next_index_number;
- d->filename = read_rtx_filename;
+ d->filename = read_md_filename;
d->lineno = lineno;
if (XSTR (insn, 0)[0])
d->name = XSTR (insn, 0);
#endif
validate_insn_operands (d);
validate_insn_alternatives (d);
+ validate_optab_operands (d);
place_operands (d);
process_template (d, XTMPL (insn, 3));
}
d->code_number = next_code_number;
d->index_number = next_index_number;
- d->filename = read_rtx_filename;
+ d->filename = read_md_filename;
d->lineno = lineno;
d->name = 0;
d->code_number = next_code_number;
d->index_number = next_index_number;
- d->filename = read_rtx_filename;
+ d->filename = read_md_filename;
d->lineno = lineno;
if (XSTR (insn, 0)[0])
d->name = XSTR (insn, 0);
d->n_operands = max_opno + 1;
d->n_dups = num_dups;
- d->template = 0;
+ d->template_code = 0;
d->output_format = INSN_OUTPUT_FORMAT_NONE;
validate_insn_alternatives (d);
+ validate_optab_operands (d);
place_operands (d);
}
\f
d->code_number = next_code_number;
d->index_number = next_index_number;
- d->filename = read_rtx_filename;
+ d->filename = read_md_filename;
d->lineno = lineno;
d->name = 0;
d->n_operands = max_opno + 1;
d->n_dups = 0;
d->n_alternatives = 0;
- d->template = 0;
+ d->template_code = 0;
d->output_format = INSN_OUTPUT_FORMAT_NONE;
place_operands (d);
progname = "genoutput";
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
output_prologue ();
{
const char *name = XSTR (exp, 0);
unsigned int namelen = strlen (name);
- struct constraint_data **iter, **slot, *new;
+ struct constraint_data **iter, **slot, *new_cdata;
- if (strchr (indep_constraints, name[0]))
+ /* The 'm' constraint is special here since that constraint letter
+ can be overridden by the back end by defining the
+ TARGET_MEM_CONSTRAINT macro. */
+ if (strchr (indep_constraints, name[0]) && name[0] != 'm')
{
if (name[1] == '\0')
- message_with_line (lineno, "constraint letter '%s' cannot be "
- "redefined by the machine description", name);
+ error_with_line (lineno, "constraint letter '%s' cannot be "
+ "redefined by the machine description", name);
else
- message_with_line (lineno, "constraint name '%s' cannot be defined by "
- "the machine description, as it begins with '%c'",
- name, name[0]);
- have_error = 1;
+ error_with_line (lineno, "constraint name '%s' cannot be defined by "
+ "the machine description, as it begins with '%c'",
+ name, name[0]);
return;
}
if (!strcmp ((*iter)->name, name))
{
- message_with_line (lineno, "redefinition of constraint '%s'", name);
+ error_with_line (lineno, "redefinition of constraint '%s'", name);
message_with_line ((*iter)->lineno, "previous definition is here");
- have_error = 1;
return;
}
else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
{
- message_with_line (lineno, "defining constraint '%s' here", name);
+ error_with_line (lineno, "defining constraint '%s' here", name);
message_with_line ((*iter)->lineno, "renders constraint '%s' "
"(defined here) a prefix", (*iter)->name);
- have_error = 1;
return;
}
else if (!strncmp ((*iter)->name, name, namelen))
{
- message_with_line (lineno, "constraint '%s' is a prefix", name);
+ error_with_line (lineno, "constraint '%s' is a prefix", name);
message_with_line ((*iter)->lineno, "of constraint '%s' "
"(defined here)", (*iter)->name);
- have_error = 1;
return;
}
}
- new = xmalloc (sizeof (struct constraint_data) + namelen);
- strcpy ((char *)new + offsetof(struct constraint_data, name), name);
- new->namelen = namelen;
- new->lineno = lineno;
- new->next_this_letter = *slot;
- *slot = new;
+ new_cdata = XNEWVAR (struct constraint_data, sizeof (struct constraint_data) + namelen);
+ strcpy ((char *)new_cdata + offsetof(struct constraint_data, name), name);
+ new_cdata->namelen = namelen;
+ new_cdata->lineno = lineno;
+ new_cdata->next_this_letter = *slot;
+ *slot = new_cdata;
}
/* Return the length of the constraint name beginning at position S
if (!strncmp (s, p->name, p->namelen))
return p->namelen;
- message_with_line (lineno,
- "error: undefined machine-specific constraint "
- "at this point: \"%s\"", s);
+ error_with_line (lineno,
+ "error: undefined machine-specific constraint "
+ "at this point: \"%s\"", s);
message_with_line (lineno, "note: in operand %d", opno);
- have_error = 1;
return 1; /* safe */
}