118334Speter/* Generate code from to output assembler insns as recognized from rtl.
2132718Skan   Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002,
3169689Skan   2003, 2004, 2005 Free Software Foundation, Inc.
418334Speter
590075SobrienThis file is part of GCC.
618334Speter
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1118334Speter
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
2118334Speter
2218334Speter
2318334Speter/* This program reads the machine description for the compiler target machine
2418334Speter   and produces a file containing these things:
2518334Speter
2690075Sobrien   1. An array of `struct insn_data', which is indexed by insn code number,
2790075Sobrien   which contains:
2818334Speter
2990075Sobrien     a. `name' is the name for that pattern.  Nameless patterns are
3090075Sobrien     given a name.
3118334Speter
3290075Sobrien     b. `output' hold either the output template, an array of output
3390075Sobrien     templates, or an output function.
3418334Speter
3590075Sobrien     c. `genfun' is the function to generate a body for that pattern,
3690075Sobrien     given operands as arguments.
3718334Speter
3890075Sobrien     d. `n_operands' is the number of distinct operands in the pattern
3990075Sobrien     for that insn,
4018334Speter
4190075Sobrien     e. `n_dups' is the number of match_dup's that appear in the insn's
4290075Sobrien     pattern.  This says how many elements of `recog_data.dup_loc' are
4390075Sobrien     significant after an insn has been recognized.
4418334Speter
4590075Sobrien     f. `n_alternatives' is the number of alternatives in the constraints
4690075Sobrien     of each pattern.
4718334Speter
4890075Sobrien     g. `output_format' tells what type of thing `output' is.
4918334Speter
5090075Sobrien     h. `operand' is the base of an array of operand data for the insn.
5118334Speter
5290075Sobrien   2. An array of `struct insn_operand data', used by `operand' above.
5318334Speter
5490075Sobrien     a. `predicate', an int-valued function, is the match_operand predicate
5590075Sobrien     for this operand.
5618334Speter
57169689Skan     b. `constraint' is the constraint for this operand.
5818334Speter
5990075Sobrien     c. `address_p' indicates that the operand appears within ADDRESS
60169689Skan     rtx's.
6118334Speter
6290075Sobrien     d. `mode' is the machine mode that that operand is supposed to have.
6390075Sobrien
6490075Sobrien     e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART.
6590075Sobrien
6690075Sobrien     f. `eliminable', is nonzero for operands that are matched normally by
6790075Sobrien     MATCH_OPERAND; it is zero for operands that should not be changed during
6890075Sobrien     register elimination such as MATCH_OPERATORs.
6990075Sobrien
7090075Sobrien  The code number of an insn is simply its position in the machine
7190075Sobrien  description; code numbers are assigned sequentially to entries in
7290075Sobrien  the description, starting with code number 0.
7390075Sobrien
7490075Sobrien  Thus, the following entry in the machine description
7590075Sobrien
7618334Speter    (define_insn "clrdf"
7718334Speter      [(set (match_operand:DF 0 "general_operand" "")
7818334Speter	    (const_int 0))]
7918334Speter      ""
8018334Speter      "clrd %0")
8118334Speter
8290075Sobrien  assuming it is the 25th entry present, would cause
8390075Sobrien  insn_data[24].template to be "clrd %0", and
8490075Sobrien  insn_data[24].n_operands to be 1.  */
8518334Speter
86132718Skan#include "bconfig.h"
8750397Sobrien#include "system.h"
88132718Skan#include "coretypes.h"
89132718Skan#include "tm.h"
9018334Speter#include "rtl.h"
9190075Sobrien#include "errors.h"
9290075Sobrien#include "gensupport.h"
9318334Speter
9490075Sobrien/* No instruction can have more operands than this.  Sorry for this
9590075Sobrien   arbitrary limit, but what machine will have an instruction with
9690075Sobrien   this many operands?  */
9718334Speter
9818334Speter#define MAX_MAX_OPERANDS 40
9918334Speter
100132718Skanstatic int n_occurrences		(int, const char *);
101132718Skanstatic const char *strip_whitespace	(const char *);
10218334Speter
10318334Speter/* insns in the machine description are assigned sequential code numbers
10418334Speter   that are used by insn-recog.c (produced by genrecog) to communicate
10518334Speter   to insn-output.c (produced by this program).  */
10618334Speter
10718334Speterstatic int next_code_number;
10818334Speter
10918334Speter/* This counts all definitions in the md file,
11018334Speter   for the sake of error messages.  */
11118334Speter
11218334Speterstatic int next_index_number;
11318334Speter
11490075Sobrien/* This counts all operands used in the md file.  The first is null.  */
11590075Sobrien
11690075Sobrienstatic int next_operand_number = 1;
11790075Sobrien
11890075Sobrien/* Record in this chain all information about the operands we will output.  */
11990075Sobrien
12090075Sobrienstruct operand_data
12190075Sobrien{
12290075Sobrien  struct operand_data *next;
12390075Sobrien  int index;
12490075Sobrien  const char *predicate;
12590075Sobrien  const char *constraint;
12690075Sobrien  enum machine_mode mode;
12790075Sobrien  unsigned char n_alternatives;
12890075Sobrien  char address_p;
12990075Sobrien  char strict_low;
13090075Sobrien  char eliminable;
13190075Sobrien  char seen;
13290075Sobrien};
13390075Sobrien
13490075Sobrien/* Begin with a null operand at index 0.  */
13590075Sobrien
13690075Sobrienstatic struct operand_data null_operand =
13790075Sobrien{
13890075Sobrien  0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0
13990075Sobrien};
14090075Sobrien
14190075Sobrienstatic struct operand_data *odata = &null_operand;
14290075Sobrienstatic struct operand_data **odata_end = &null_operand.next;
14390075Sobrien
14490075Sobrien/* Must match the constants in recog.h.  */
14590075Sobrien
14690075Sobrien#define INSN_OUTPUT_FORMAT_NONE         0       /* abort */
14790075Sobrien#define INSN_OUTPUT_FORMAT_SINGLE       1       /* const char * */
14890075Sobrien#define INSN_OUTPUT_FORMAT_MULTI        2       /* const char * const * */
14990075Sobrien#define INSN_OUTPUT_FORMAT_FUNCTION     3       /* const char * (*)(...) */
15090075Sobrien
15118334Speter/* Record in this chain all information that we will output,
15218334Speter   associated with the code number of the insn.  */
15318334Speter
15418334Speterstruct data
15518334Speter{
15690075Sobrien  struct data *next;
15790075Sobrien  const char *name;
15890075Sobrien  const char *template;
15918334Speter  int code_number;
16018334Speter  int index_number;
161169689Skan  const char *filename;
16290075Sobrien  int lineno;
16318334Speter  int n_operands;		/* Number of operands this insn recognizes */
16418334Speter  int n_dups;			/* Number times match_dup appears in pattern */
16518334Speter  int n_alternatives;		/* Number of alternatives in each constraint */
16690075Sobrien  int operand_number;		/* Operand index in the big array.  */
16790075Sobrien  int output_format;		/* INSN_OUTPUT_FORMAT_*.  */
16890075Sobrien  struct operand_data operand[MAX_MAX_OPERANDS];
16918334Speter};
17018334Speter
17190075Sobrien/* This variable points to the first link in the insn chain.  */
17218334Speter
17390075Sobrienstatic struct data *idata, **idata_end = &idata;
17418334Speter
175132718Skanstatic void output_prologue (void);
176132718Skanstatic void output_operand_data (void);
177132718Skanstatic void output_insn_data (void);
178132718Skanstatic void output_get_insn_name (void);
179132718Skanstatic void scan_operands (struct data *, rtx, int, int);
180132718Skanstatic int compare_operands (struct operand_data *,
181132718Skan			     struct operand_data *);
182132718Skanstatic void place_operands (struct data *);
183132718Skanstatic void process_template (struct data *, const char *);
184132718Skanstatic void validate_insn_alternatives (struct data *);
185132718Skanstatic void validate_insn_operands (struct data *);
186132718Skanstatic void gen_insn (rtx, int);
187132718Skanstatic void gen_peephole (rtx, int);
188132718Skanstatic void gen_expand (rtx, int);
189132718Skanstatic void gen_split (rtx, int);
190169689Skan
191169689Skan#ifdef USE_MD_CONSTRAINTS
192169689Skan
193169689Skanstruct constraint_data
19452284Sobrien{
195169689Skan  struct constraint_data *next_this_letter;
196169689Skan  int lineno;
197169689Skan  unsigned int namelen;
198169689Skan  const char name[1];
199169689Skan};
20052284Sobrien
201169689Skan/* This is a complete list (unlike the one in genpreds.c) of constraint
202169689Skan   letters and modifiers with machine-independent meaning.  The only
203169689Skan   omission is digits, as these are handled specially.  */
204169689Skanstatic const char indep_constraints[] = ",=+%*?!#&<>EFVXgimnoprs";
20552284Sobrien
206169689Skanstatic struct constraint_data *
207169689Skanconstraints_by_letter_table[1 << CHAR_BIT];
20852284Sobrien
209169689Skanstatic int mdep_constraint_len (const char *, int, int);
210169689Skanstatic void note_constraint (rtx, int);
21152284Sobrien
212169689Skan#else  /* !USE_MD_CONSTRAINTS */
213169689Skan
214169689Skanstatic void check_constraint_len (void);
215169689Skanstatic int constraint_len (const char *, int);
216169689Skan
217169689Skan#endif /* !USE_MD_CONSTRAINTS */
218169689Skan
219169689Skan
22018334Speterstatic void
221132718Skanoutput_prologue (void)
22218334Speter{
22318334Speter  printf ("/* Generated automatically by the program `genoutput'\n\
22490075Sobrien   from the machine description file `md'.  */\n\n");
22518334Speter
22618334Speter  printf ("#include \"config.h\"\n");
22750397Sobrien  printf ("#include \"system.h\"\n");
228132718Skan  printf ("#include \"coretypes.h\"\n");
229132718Skan  printf ("#include \"tm.h\"\n");
23050397Sobrien  printf ("#include \"flags.h\"\n");
23190075Sobrien  printf ("#include \"ggc.h\"\n");
23218334Speter  printf ("#include \"rtl.h\"\n");
23390075Sobrien  printf ("#include \"expr.h\"\n");
23490075Sobrien  printf ("#include \"insn-codes.h\"\n");
23590075Sobrien  printf ("#include \"tm_p.h\"\n");
23690075Sobrien  printf ("#include \"function.h\"\n");
23718334Speter  printf ("#include \"regs.h\"\n");
23818334Speter  printf ("#include \"hard-reg-set.h\"\n");
23918334Speter  printf ("#include \"real.h\"\n");
24018334Speter  printf ("#include \"insn-config.h\"\n\n");
24118334Speter  printf ("#include \"conditions.h\"\n");
24218334Speter  printf ("#include \"insn-attr.h\"\n\n");
24318334Speter  printf ("#include \"recog.h\"\n\n");
24490075Sobrien  printf ("#include \"toplev.h\"\n");
24518334Speter  printf ("#include \"output.h\"\n");
246132718Skan  printf ("#include \"target.h\"\n");
247169689Skan  printf ("#include \"tm-constrs.h\"\n");
24818334Speter}
24918334Speter
25018334Speterstatic void
251132718Skanoutput_operand_data (void)
25218334Speter{
25390075Sobrien  struct operand_data *d;
25418334Speter
25590075Sobrien  printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n");
25690075Sobrien
25790075Sobrien  for (d = odata; d; d = d->next)
25818334Speter    {
25990075Sobrien      printf ("  {\n");
26018334Speter
26190075Sobrien      printf ("    %s,\n",
26290075Sobrien	      d->predicate && d->predicate[0] ? d->predicate : "0");
26390075Sobrien
26490075Sobrien      printf ("    \"%s\",\n", d->constraint ? d->constraint : "");
26590075Sobrien
26690075Sobrien      printf ("    %smode,\n", GET_MODE_NAME (d->mode));
26790075Sobrien
26890075Sobrien      printf ("    %d,\n", d->strict_low);
26990075Sobrien
27090075Sobrien      printf ("    %d\n", d->eliminable);
27190075Sobrien
27290075Sobrien      printf("  },\n");
27318334Speter    }
27490075Sobrien  printf("};\n\n\n");
27590075Sobrien}
27618334Speter
27790075Sobrienstatic void
278132718Skanoutput_insn_data (void)
27990075Sobrien{
28090075Sobrien  struct data *d;
28190075Sobrien  int name_offset = 0;
28290075Sobrien  int next_name_offset;
28390075Sobrien  const char * last_name = 0;
28490075Sobrien  const char * next_name = 0;
28590075Sobrien  struct data *n;
28618334Speter
28790075Sobrien  for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++)
28890075Sobrien    if (n->name)
28918334Speter      {
29090075Sobrien	next_name = n->name;
29190075Sobrien	break;
29218334Speter      }
29318334Speter
294132718Skan  printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n");
29590075Sobrien  printf ("\nconst struct insn_data insn_data[] = \n{\n");
29618334Speter
29790075Sobrien  for (d = idata; d; d = d->next)
29890075Sobrien    {
299169689Skan      printf ("  /* %s:%d */\n", d->filename, d->lineno);
30090075Sobrien      printf ("  {\n");
30118334Speter
30290075Sobrien      if (d->name)
30318334Speter	{
30490075Sobrien	  printf ("    \"%s\",\n", d->name);
30590075Sobrien	  name_offset = 0;
30690075Sobrien	  last_name = d->name;
30790075Sobrien	  next_name = 0;
30890075Sobrien	  for (n = d->next, next_name_offset = 1; n;
30990075Sobrien	       n = n->next, next_name_offset++)
31018334Speter	    {
31190075Sobrien	      if (n->name)
31290075Sobrien		{
31390075Sobrien		  next_name = n->name;
31490075Sobrien		  break;
31590075Sobrien		}
31618334Speter	    }
31718334Speter	}
31890075Sobrien      else
31918334Speter	{
32090075Sobrien	  name_offset++;
32190075Sobrien	  if (next_name && (last_name == 0
32290075Sobrien			    || name_offset > next_name_offset / 2))
32390075Sobrien	    printf ("    \"%s-%d\",\n", next_name,
32490075Sobrien		    next_name_offset - name_offset);
32590075Sobrien	  else
32690075Sobrien	    printf ("    \"%s+%d\",\n", last_name, name_offset);
32718334Speter	}
32818334Speter
32990075Sobrien      switch (d->output_format)
33090075Sobrien	{
33190075Sobrien	case INSN_OUTPUT_FORMAT_NONE:
332132718Skan	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
333132718Skan	  printf ("    { 0 },\n");
334132718Skan	  printf ("#else\n");
335132718Skan	  printf ("    { 0, 0, 0 },\n");
336132718Skan	  printf ("#endif\n");
33790075Sobrien	  break;
33890075Sobrien	case INSN_OUTPUT_FORMAT_SINGLE:
33918334Speter	  {
34090075Sobrien	    const char *p = d->template;
34190075Sobrien	    char prev = 0;
342132718Skan
343132718Skan	    printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
344132718Skan	    printf ("    { .single =\n");
345132718Skan	    printf ("#else\n");
346132718Skan	    printf ("    {\n");
347132718Skan	    printf ("#endif\n");
34890075Sobrien	    printf ("    \"");
34990075Sobrien	    while (*p)
35018334Speter	      {
35196263Sobrien		if (IS_VSPACE (*p) && prev != '\\')
35296263Sobrien		  {
35396263Sobrien		    /* Preserve two consecutive \n's or \r's, but treat \r\n
35496263Sobrien		       as a single newline.  */
35596263Sobrien		    if (*p == '\n' && prev != '\r')
35696263Sobrien		      printf ("\\n\\\n");
35796263Sobrien		  }
35890075Sobrien		else
35990075Sobrien		  putchar (*p);
36090075Sobrien		prev = *p;
36190075Sobrien		++p;
36218334Speter	      }
36390075Sobrien	    printf ("\",\n");
364132718Skan	    printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
365132718Skan	    printf ("    },\n");
366132718Skan	    printf ("#else\n");
367132718Skan	    printf ("    0, 0 },\n");
368132718Skan	    printf ("#endif\n");
36918334Speter	  }
37090075Sobrien	  break;
37190075Sobrien	case INSN_OUTPUT_FORMAT_MULTI:
372132718Skan	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
373132718Skan	  printf ("    { .multi = output_%d },\n", d->code_number);
374132718Skan	  printf ("#else\n");
375132718Skan	  printf ("    { 0, output_%d, 0 },\n", d->code_number);
376132718Skan	  printf ("#endif\n");
377132718Skan	  break;
37890075Sobrien	case INSN_OUTPUT_FORMAT_FUNCTION:
379132718Skan	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
380132718Skan	  printf ("    { .function = output_%d },\n", d->code_number);
381132718Skan	  printf ("#else\n");
382132718Skan	  printf ("    { 0, 0, output_%d },\n", d->code_number);
383132718Skan	  printf ("#endif\n");
38490075Sobrien	  break;
38590075Sobrien	default:
386169689Skan	  gcc_unreachable ();
38790075Sobrien	}
38818334Speter
38990075Sobrien      if (d->name && d->name[0] != '*')
39090075Sobrien	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
39190075Sobrien      else
39290075Sobrien	printf ("    0,\n");
39390075Sobrien
39490075Sobrien      printf ("    &operand_data[%d],\n", d->operand_number);
39590075Sobrien      printf ("    %d,\n", d->n_operands);
39690075Sobrien      printf ("    %d,\n", d->n_dups);
39790075Sobrien      printf ("    %d,\n", d->n_alternatives);
39890075Sobrien      printf ("    %d\n", d->output_format);
39990075Sobrien
40090075Sobrien      printf("  },\n");
40190075Sobrien    }
40290075Sobrien  printf ("};\n\n\n");
40318334Speter}
40490075Sobrien
40590075Sobrienstatic void
406132718Skanoutput_get_insn_name (void)
40790075Sobrien{
40890075Sobrien  printf ("const char *\n");
409132718Skan  printf ("get_insn_name (int code)\n");
41090075Sobrien  printf ("{\n");
411132718Skan  printf ("  if (code == NOOP_MOVE_INSN_CODE)\n");
412132718Skan  printf ("    return \"NOOP_MOVE\";\n");
413132718Skan  printf ("  else\n");
414132718Skan  printf ("    return insn_data[code].name;\n");
41590075Sobrien  printf ("}\n");
41690075Sobrien}
41790075Sobrien
41818334Speter
41990075Sobrien/* Stores in max_opno the largest operand number present in `part', if
42090075Sobrien   that is larger than the previous value of max_opno, and the rest of
42190075Sobrien   the operand data into `d->operand[i]'.
42218334Speter
42318334Speter   THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
42418334Speter   THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART.  */
42518334Speter
42618334Speterstatic int max_opno;
42718334Speterstatic int num_dups;
42818334Speter
42918334Speterstatic void
430132718Skanscan_operands (struct data *d, rtx part, int this_address_p,
431132718Skan	       int this_strict_low)
43218334Speter{
43390075Sobrien  int i, j;
43490075Sobrien  const char *format_ptr;
43518334Speter  int opno;
43618334Speter
43718334Speter  if (part == 0)
43818334Speter    return;
43918334Speter
44018334Speter  switch (GET_CODE (part))
44118334Speter    {
44218334Speter    case MATCH_OPERAND:
44318334Speter      opno = XINT (part, 0);
44418334Speter      if (opno > max_opno)
44518334Speter	max_opno = opno;
44618334Speter      if (max_opno >= MAX_MAX_OPERANDS)
44718334Speter	{
44890075Sobrien	  message_with_line (d->lineno,
44990075Sobrien			     "maximum number of operands exceeded");
45090075Sobrien	  have_error = 1;
45118334Speter	  return;
45218334Speter	}
45390075Sobrien      if (d->operand[opno].seen)
45418334Speter	{
45590075Sobrien	  message_with_line (d->lineno,
45690075Sobrien			     "repeated operand number %d\n", opno);
45790075Sobrien	  have_error = 1;
45818334Speter	}
45990075Sobrien
46090075Sobrien      d->operand[opno].seen = 1;
46190075Sobrien      d->operand[opno].mode = GET_MODE (part);
46290075Sobrien      d->operand[opno].strict_low = this_strict_low;
46390075Sobrien      d->operand[opno].predicate = XSTR (part, 1);
46490075Sobrien      d->operand[opno].constraint = strip_whitespace (XSTR (part, 2));
46590075Sobrien      d->operand[opno].n_alternatives
46690075Sobrien	= n_occurrences (',', d->operand[opno].constraint) + 1;
46790075Sobrien      d->operand[opno].address_p = this_address_p;
46890075Sobrien      d->operand[opno].eliminable = 1;
46918334Speter      return;
47018334Speter
47118334Speter    case MATCH_SCRATCH:
47218334Speter      opno = XINT (part, 0);
47318334Speter      if (opno > max_opno)
47418334Speter	max_opno = opno;
47518334Speter      if (max_opno >= MAX_MAX_OPERANDS)
47618334Speter	{
47790075Sobrien	  message_with_line (d->lineno,
47890075Sobrien			     "maximum number of operands exceeded");
47990075Sobrien	  have_error = 1;
48018334Speter	  return;
48118334Speter	}
48290075Sobrien      if (d->operand[opno].seen)
48318334Speter	{
48490075Sobrien	  message_with_line (d->lineno,
48590075Sobrien			     "repeated operand number %d\n", opno);
48690075Sobrien	  have_error = 1;
48718334Speter	}
48890075Sobrien
48990075Sobrien      d->operand[opno].seen = 1;
49090075Sobrien      d->operand[opno].mode = GET_MODE (part);
49190075Sobrien      d->operand[opno].strict_low = 0;
49290075Sobrien      d->operand[opno].predicate = "scratch_operand";
49390075Sobrien      d->operand[opno].constraint = strip_whitespace (XSTR (part, 1));
49490075Sobrien      d->operand[opno].n_alternatives
49590075Sobrien	= n_occurrences (',', d->operand[opno].constraint) + 1;
49690075Sobrien      d->operand[opno].address_p = 0;
49790075Sobrien      d->operand[opno].eliminable = 0;
49818334Speter      return;
49918334Speter
50018334Speter    case MATCH_OPERATOR:
50118334Speter    case MATCH_PARALLEL:
50218334Speter      opno = XINT (part, 0);
50318334Speter      if (opno > max_opno)
50418334Speter	max_opno = opno;
50518334Speter      if (max_opno >= MAX_MAX_OPERANDS)
50618334Speter	{
50790075Sobrien	  message_with_line (d->lineno,
50890075Sobrien			     "maximum number of operands exceeded");
50990075Sobrien	  have_error = 1;
51018334Speter	  return;
51118334Speter	}
51290075Sobrien      if (d->operand[opno].seen)
51390075Sobrien	{
51490075Sobrien	  message_with_line (d->lineno,
51590075Sobrien			     "repeated operand number %d\n", opno);
51690075Sobrien	  have_error = 1;
51790075Sobrien	}
51890075Sobrien
51990075Sobrien      d->operand[opno].seen = 1;
52090075Sobrien      d->operand[opno].mode = GET_MODE (part);
52190075Sobrien      d->operand[opno].strict_low = 0;
52290075Sobrien      d->operand[opno].predicate = XSTR (part, 1);
52390075Sobrien      d->operand[opno].constraint = 0;
52490075Sobrien      d->operand[opno].address_p = 0;
52590075Sobrien      d->operand[opno].eliminable = 0;
52618334Speter      for (i = 0; i < XVECLEN (part, 2); i++)
52790075Sobrien	scan_operands (d, XVECEXP (part, 2, i), 0, 0);
52818334Speter      return;
52918334Speter
53018334Speter    case MATCH_DUP:
53118334Speter    case MATCH_OP_DUP:
53218334Speter    case MATCH_PAR_DUP:
53318334Speter      ++num_dups;
53496263Sobrien      break;
53518334Speter
53618334Speter    case ADDRESS:
53790075Sobrien      scan_operands (d, XEXP (part, 0), 1, 0);
53818334Speter      return;
53918334Speter
54018334Speter    case STRICT_LOW_PART:
54190075Sobrien      scan_operands (d, XEXP (part, 0), 0, 1);
54218334Speter      return;
543132718Skan
54450397Sobrien    default:
54550397Sobrien      break;
54618334Speter    }
54718334Speter
54818334Speter  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
54918334Speter
55018334Speter  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
55118334Speter    switch (*format_ptr++)
55218334Speter      {
55318334Speter      case 'e':
55450397Sobrien      case 'u':
55590075Sobrien	scan_operands (d, XEXP (part, i), 0, 0);
55618334Speter	break;
55718334Speter      case 'E':
55818334Speter	if (XVEC (part, i) != NULL)
55918334Speter	  for (j = 0; j < XVECLEN (part, i); j++)
56090075Sobrien	    scan_operands (d, XVECEXP (part, i, j), 0, 0);
56118334Speter	break;
56218334Speter      }
56318334Speter}
56490075Sobrien
56590075Sobrien/* Compare two operands for content equality.  */
56690075Sobrien
56790075Sobrienstatic int
568132718Skancompare_operands (struct operand_data *d0, struct operand_data *d1)
56990075Sobrien{
57090075Sobrien  const char *p0, *p1;
57190075Sobrien
57290075Sobrien  p0 = d0->predicate;
57390075Sobrien  if (!p0)
57490075Sobrien    p0 = "";
57590075Sobrien  p1 = d1->predicate;
57690075Sobrien  if (!p1)
57790075Sobrien    p1 = "";
57890075Sobrien  if (strcmp (p0, p1) != 0)
57990075Sobrien    return 0;
58090075Sobrien
58190075Sobrien  p0 = d0->constraint;
58290075Sobrien  if (!p0)
58390075Sobrien    p0 = "";
58490075Sobrien  p1 = d1->constraint;
58590075Sobrien  if (!p1)
58690075Sobrien    p1 = "";
58790075Sobrien  if (strcmp (p0, p1) != 0)
58890075Sobrien    return 0;
58990075Sobrien
59090075Sobrien  if (d0->mode != d1->mode)
59190075Sobrien    return 0;
59290075Sobrien
59390075Sobrien  if (d0->strict_low != d1->strict_low)
59490075Sobrien    return 0;
59590075Sobrien
59690075Sobrien  if (d0->eliminable != d1->eliminable)
59790075Sobrien    return 0;
59890075Sobrien
59990075Sobrien  return 1;
60090075Sobrien}
60190075Sobrien
60290075Sobrien/* Scan the list of operands we've already committed to output and either
60390075Sobrien   find a subsequence that is the same, or allocate a new one at the end.  */
60490075Sobrien
60590075Sobrienstatic void
606132718Skanplace_operands (struct data *d)
60790075Sobrien{
60890075Sobrien  struct operand_data *od, *od2;
60990075Sobrien  int i;
61090075Sobrien
61190075Sobrien  if (d->n_operands == 0)
61290075Sobrien    {
61390075Sobrien      d->operand_number = 0;
61490075Sobrien      return;
61590075Sobrien    }
61690075Sobrien
61790075Sobrien  /* Brute force substring search.  */
61890075Sobrien  for (od = odata, i = 0; od; od = od->next, i = 0)
61990075Sobrien    if (compare_operands (od, &d->operand[0]))
62090075Sobrien      {
62190075Sobrien	od2 = od->next;
62290075Sobrien	i = 1;
62390075Sobrien	while (1)
62490075Sobrien	  {
62590075Sobrien	    if (i == d->n_operands)
62690075Sobrien	      goto full_match;
62790075Sobrien	    if (od2 == NULL)
62890075Sobrien	      goto partial_match;
62990075Sobrien	    if (! compare_operands (od2, &d->operand[i]))
63090075Sobrien	      break;
63190075Sobrien	    ++i, od2 = od2->next;
63290075Sobrien	  }
63390075Sobrien      }
63490075Sobrien
63590075Sobrien  /* Either partial match at the end of the list, or no match.  In either
63690075Sobrien     case, we tack on what operands are remaining to the end of the list.  */
63790075Sobrien partial_match:
63890075Sobrien  d->operand_number = next_operand_number - i;
63990075Sobrien  for (; i < d->n_operands; ++i)
64090075Sobrien    {
64190075Sobrien      od2 = &d->operand[i];
64290075Sobrien      *odata_end = od2;
64390075Sobrien      odata_end = &od2->next;
64490075Sobrien      od2->index = next_operand_number++;
64590075Sobrien    }
64690075Sobrien  *odata_end = NULL;
64790075Sobrien  return;
64890075Sobrien
64990075Sobrien full_match:
65090075Sobrien  d->operand_number = od->index;
65190075Sobrien  return;
65290075Sobrien}
65390075Sobrien
65418334Speter
65518334Speter/* Process an assembler template from a define_insn or a define_peephole.
65618334Speter   It is either the assembler code template, a list of assembler code
65718334Speter   templates, or C code to generate the assembler code template.  */
65818334Speter
65918334Speterstatic void
660132718Skanprocess_template (struct data *d, const char *template)
66118334Speter{
66290075Sobrien  const char *cp;
66390075Sobrien  int i;
66418334Speter
66590075Sobrien  /* Templates starting with * contain straight code to be run.  */
66690075Sobrien  if (template[0] == '*')
66718334Speter    {
66890075Sobrien      d->template = 0;
66990075Sobrien      d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
67018334Speter
671132718Skan      puts ("\nstatic const char *");
672132718Skan      printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n",
67390075Sobrien	      d->code_number);
67490075Sobrien      puts ("{");
675169689Skan      print_rtx_ptr_loc (template);
67690075Sobrien      puts (template + 1);
67790075Sobrien      puts ("}");
67890075Sobrien    }
67918334Speter
68018334Speter  /* If the assembler code template starts with a @ it is a newline-separated
68190075Sobrien     list of assembler code templates, one for each alternative.  */
68290075Sobrien  else if (template[0] == '@')
68318334Speter    {
68490075Sobrien      d->template = 0;
68590075Sobrien      d->output_format = INSN_OUTPUT_FORMAT_MULTI;
68618334Speter
68790075Sobrien      printf ("\nstatic const char * const output_%d[] = {\n", d->code_number);
68818334Speter
68918334Speter      for (i = 0, cp = &template[1]; *cp; )
69018334Speter	{
691169689Skan	  const char *ep, *sp;
692169689Skan
69396263Sobrien	  while (ISSPACE (*cp))
69418334Speter	    cp++;
69518334Speter
69690075Sobrien	  printf ("  \"");
697169689Skan
698169689Skan	  for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
699169689Skan	    if (!ISSPACE (*ep))
700169689Skan	      sp = ep + 1;
701169689Skan
702169689Skan	  if (sp != ep)
703169689Skan	    message_with_line (d->lineno,
704169689Skan			       "trailing whitespace in output template");
705169689Skan
706169689Skan	  while (cp < sp)
70750397Sobrien	    {
70850397Sobrien	      putchar (*cp);
70950397Sobrien	      cp++;
71050397Sobrien	    }
71118334Speter
71218334Speter	  printf ("\",\n");
71318334Speter	  i++;
71418334Speter	}
71590075Sobrien      if (i == 1)
71690075Sobrien	message_with_line (d->lineno,
71790075Sobrien			   "'@' is redundant for output template with single alternative");
71818334Speter      if (i != d->n_alternatives)
71990075Sobrien	{
72090075Sobrien	  message_with_line (d->lineno,
72190075Sobrien			     "wrong number of alternatives in the output template");
72290075Sobrien	  have_error = 1;
72390075Sobrien	}
72418334Speter
72590075Sobrien      printf ("};\n");
72618334Speter    }
72718334Speter  else
72818334Speter    {
72990075Sobrien      d->template = template;
73090075Sobrien      d->output_format = INSN_OUTPUT_FORMAT_SINGLE;
73118334Speter    }
73218334Speter}
73318334Speter
73418334Speter/* Check insn D for consistency in number of constraint alternatives.  */
73518334Speter
73618334Speterstatic void
737132718Skanvalidate_insn_alternatives (struct data *d)
73818334Speter{
73990075Sobrien  int n = 0, start;
74090075Sobrien
74190075Sobrien  /* Make sure all the operands have the same number of alternatives
74290075Sobrien     in their constraints.  Let N be that number.  */
74318334Speter  for (start = 0; start < d->n_operands; start++)
74490075Sobrien    if (d->operand[start].n_alternatives > 0)
74518334Speter      {
746132718Skan	int len, i;
747132718Skan	const char *p;
748132718Skan	char c;
749132718Skan	int which_alternative = 0;
750132718Skan	int alternative_count_unsure = 0;
751132718Skan
752132718Skan	for (p = d->operand[start].constraint; (c = *p); p += len)
753132718Skan	  {
754169689Skan#ifdef USE_MD_CONSTRAINTS
755169689Skan	    if (ISSPACE (c) || strchr (indep_constraints, c))
756169689Skan	      len = 1;
757169689Skan	    else if (ISDIGIT (c))
758169689Skan	      {
759169689Skan		const char *q = p;
760169689Skan		do
761169689Skan		  q++;
762169689Skan		while (ISDIGIT (*q));
763169689Skan		len = q - p;
764169689Skan	      }
765169689Skan	    else
766169689Skan	      len = mdep_constraint_len (p, d->lineno, start);
767169689Skan#else
768132718Skan	    len = CONSTRAINT_LEN (c, p);
769132718Skan
770132718Skan	    if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c)))
771132718Skan	      {
772132718Skan		message_with_line (d->lineno,
773132718Skan				   "invalid length %d for char '%c' in alternative %d of operand %d",
774132718Skan				    len, c, which_alternative, start);
775132718Skan		len = 1;
776132718Skan		have_error = 1;
777132718Skan	      }
778169689Skan#endif
779132718Skan
780132718Skan	    if (c == ',')
781132718Skan	      {
782132718Skan	        which_alternative++;
783132718Skan		continue;
784132718Skan	      }
785132718Skan
786132718Skan	    for (i = 1; i < len; i++)
787132718Skan	      if (p[i] == '\0')
788132718Skan		{
789132718Skan		  message_with_line (d->lineno,
790132718Skan				     "NUL in alternative %d of operand %d",
791132718Skan				     which_alternative, start);
792132718Skan		  alternative_count_unsure = 1;
793132718Skan		  break;
794132718Skan		}
795132718Skan	      else if (strchr (",#*", p[i]))
796132718Skan		{
797132718Skan		  message_with_line (d->lineno,
798132718Skan				     "'%c' in alternative %d of operand %d",
799132718Skan				     p[i], which_alternative, start);
800132718Skan		  alternative_count_unsure = 1;
801132718Skan		}
802132718Skan	  }
803132718Skan	if (alternative_count_unsure)
804132718Skan	  have_error = 1;
805132718Skan	else if (n == 0)
80690075Sobrien	  n = d->operand[start].n_alternatives;
80790075Sobrien	else if (n != d->operand[start].n_alternatives)
80890075Sobrien	  {
80990075Sobrien	    message_with_line (d->lineno,
81090075Sobrien			       "wrong number of alternatives in operand %d",
81190075Sobrien			       start);
81290075Sobrien	    have_error = 1;
81390075Sobrien	  }
81418334Speter      }
81590075Sobrien
81618334Speter  /* Record the insn's overall number of alternatives.  */
81718334Speter  d->n_alternatives = n;
81818334Speter}
81990075Sobrien
82090075Sobrien/* Verify that there are no gaps in operand numbers for INSNs.  */
82190075Sobrien
82290075Sobrienstatic void
823132718Skanvalidate_insn_operands (struct data *d)
82490075Sobrien{
82590075Sobrien  int i;
82690075Sobrien
82790075Sobrien  for (i = 0; i < d->n_operands; ++i)
82890075Sobrien    if (d->operand[i].seen == 0)
82990075Sobrien      {
83090075Sobrien	message_with_line (d->lineno, "missing operand %d", i);
83190075Sobrien	have_error = 1;
83290075Sobrien      }
83390075Sobrien}
83418334Speter
83590075Sobrien/* Look at a define_insn just read.  Assign its code number.  Record
83690075Sobrien   on idata the template and the number of arguments.  If the insn has
83790075Sobrien   a hairy output action, output a function for now.  */
83818334Speter
83918334Speterstatic void
840132718Skangen_insn (rtx insn, int lineno)
84118334Speter{
842169689Skan  struct data *d = XNEW (struct data);
84390075Sobrien  int i;
84418334Speter
84590075Sobrien  d->code_number = next_code_number;
84618334Speter  d->index_number = next_index_number;
847169689Skan  d->filename = read_rtx_filename;
84890075Sobrien  d->lineno = lineno;
84918334Speter  if (XSTR (insn, 0)[0])
85018334Speter    d->name = XSTR (insn, 0);
85118334Speter  else
85218334Speter    d->name = 0;
85318334Speter
85418334Speter  /* Build up the list in the same order as the insns are seen
85518334Speter     in the machine description.  */
85618334Speter  d->next = 0;
85790075Sobrien  *idata_end = d;
85890075Sobrien  idata_end = &d->next;
85918334Speter
86018334Speter  max_opno = -1;
86118334Speter  num_dups = 0;
86290075Sobrien  memset (d->operand, 0, sizeof (d->operand));
86318334Speter
86418334Speter  for (i = 0; i < XVECLEN (insn, 1); i++)
86590075Sobrien    scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
86618334Speter
86718334Speter  d->n_operands = max_opno + 1;
86818334Speter  d->n_dups = num_dups;
86918334Speter
870169689Skan#ifndef USE_MD_CONSTRAINTS
871132718Skan  check_constraint_len ();
872169689Skan#endif
87390075Sobrien  validate_insn_operands (d);
87418334Speter  validate_insn_alternatives (d);
87590075Sobrien  place_operands (d);
87690075Sobrien  process_template (d, XTMPL (insn, 3));
87718334Speter}
87818334Speter
87918334Speter/* Look at a define_peephole just read.  Assign its code number.
88090075Sobrien   Record on idata the template and the number of arguments.
88118334Speter   If the insn has a hairy output action, output it now.  */
88218334Speter
88318334Speterstatic void
884132718Skangen_peephole (rtx peep, int lineno)
88518334Speter{
886169689Skan  struct data *d = XNEW (struct data);
88790075Sobrien  int i;
88818334Speter
88990075Sobrien  d->code_number = next_code_number;
89018334Speter  d->index_number = next_index_number;
891169689Skan  d->filename = read_rtx_filename;
89290075Sobrien  d->lineno = lineno;
89318334Speter  d->name = 0;
89418334Speter
89518334Speter  /* Build up the list in the same order as the insns are seen
89618334Speter     in the machine description.  */
89718334Speter  d->next = 0;
89890075Sobrien  *idata_end = d;
89990075Sobrien  idata_end = &d->next;
90018334Speter
90118334Speter  max_opno = -1;
90290075Sobrien  num_dups = 0;
90390075Sobrien  memset (d->operand, 0, sizeof (d->operand));
90418334Speter
90590075Sobrien  /* Get the number of operands by scanning all the patterns of the
90690075Sobrien     peephole optimizer.  But ignore all the rest of the information
90790075Sobrien     thus obtained.  */
90818334Speter  for (i = 0; i < XVECLEN (peep, 0); i++)
90990075Sobrien    scan_operands (d, XVECEXP (peep, 0, i), 0, 0);
91018334Speter
91118334Speter  d->n_operands = max_opno + 1;
91218334Speter  d->n_dups = 0;
91318334Speter
91418334Speter  validate_insn_alternatives (d);
91590075Sobrien  place_operands (d);
91690075Sobrien  process_template (d, XTMPL (peep, 2));
91718334Speter}
91818334Speter
91918334Speter/* Process a define_expand just read.  Assign its code number,
92018334Speter   only for the purposes of `insn_gen_function'.  */
92118334Speter
92218334Speterstatic void
923132718Skangen_expand (rtx insn, int lineno)
92418334Speter{
925169689Skan  struct data *d = XNEW (struct data);
92690075Sobrien  int i;
92718334Speter
92890075Sobrien  d->code_number = next_code_number;
92918334Speter  d->index_number = next_index_number;
930169689Skan  d->filename = read_rtx_filename;
93190075Sobrien  d->lineno = lineno;
93218334Speter  if (XSTR (insn, 0)[0])
93318334Speter    d->name = XSTR (insn, 0);
93418334Speter  else
93518334Speter    d->name = 0;
93618334Speter
93718334Speter  /* Build up the list in the same order as the insns are seen
93818334Speter     in the machine description.  */
93918334Speter  d->next = 0;
94090075Sobrien  *idata_end = d;
94190075Sobrien  idata_end = &d->next;
94218334Speter
94318334Speter  max_opno = -1;
94418334Speter  num_dups = 0;
94590075Sobrien  memset (d->operand, 0, sizeof (d->operand));
94618334Speter
94718334Speter  /* Scan the operands to get the specified predicates and modes,
94818334Speter     since expand_binop needs to know them.  */
94918334Speter
95018334Speter  if (XVEC (insn, 1))
95118334Speter    for (i = 0; i < XVECLEN (insn, 1); i++)
95290075Sobrien      scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
95318334Speter
95418334Speter  d->n_operands = max_opno + 1;
95518334Speter  d->n_dups = num_dups;
95690075Sobrien  d->template = 0;
95790075Sobrien  d->output_format = INSN_OUTPUT_FORMAT_NONE;
95818334Speter
95918334Speter  validate_insn_alternatives (d);
96090075Sobrien  place_operands (d);
96118334Speter}
96218334Speter
96318334Speter/* Process a define_split just read.  Assign its code number,
96418334Speter   only for reasons of consistency and to simplify genrecog.  */
96518334Speter
96618334Speterstatic void
967132718Skangen_split (rtx split, int lineno)
96818334Speter{
969169689Skan  struct data *d = XNEW (struct data);
97090075Sobrien  int i;
97118334Speter
97290075Sobrien  d->code_number = next_code_number;
97318334Speter  d->index_number = next_index_number;
974169689Skan  d->filename = read_rtx_filename;
97590075Sobrien  d->lineno = lineno;
97618334Speter  d->name = 0;
97718334Speter
97818334Speter  /* Build up the list in the same order as the insns are seen
97918334Speter     in the machine description.  */
98018334Speter  d->next = 0;
98190075Sobrien  *idata_end = d;
98290075Sobrien  idata_end = &d->next;
98318334Speter
98418334Speter  max_opno = -1;
98518334Speter  num_dups = 0;
98690075Sobrien  memset (d->operand, 0, sizeof (d->operand));
98718334Speter
98890075Sobrien  /* Get the number of operands by scanning all the patterns of the
98990075Sobrien     split patterns.  But ignore all the rest of the information thus
99090075Sobrien     obtained.  */
99118334Speter  for (i = 0; i < XVECLEN (split, 0); i++)
99290075Sobrien    scan_operands (d, XVECEXP (split, 0, i), 0, 0);
99318334Speter
99418334Speter  d->n_operands = max_opno + 1;
99518334Speter  d->n_dups = 0;
99618334Speter  d->n_alternatives = 0;
99718334Speter  d->template = 0;
99890075Sobrien  d->output_format = INSN_OUTPUT_FORMAT_NONE;
99918334Speter
100090075Sobrien  place_operands (d);
100118334Speter}
100218334Speter
1003132718Skanextern int main (int, char **);
100418334Speter
100518334Speterint
1006132718Skanmain (int argc, char **argv)
100718334Speter{
100818334Speter  rtx desc;
100918334Speter
101090075Sobrien  progname = "genoutput";
101118334Speter
101290075Sobrien  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
101390075Sobrien    return (FATAL_EXIT_CODE);
101418334Speter
101518334Speter  output_prologue ();
101618334Speter  next_code_number = 0;
101718334Speter  next_index_number = 0;
101818334Speter
101918334Speter  /* Read the machine description.  */
102018334Speter
102118334Speter  while (1)
102218334Speter    {
102390075Sobrien      int line_no;
102490075Sobrien
102590075Sobrien      desc = read_md_rtx (&line_no, &next_code_number);
102690075Sobrien      if (desc == NULL)
102718334Speter	break;
102818334Speter
1029169689Skan      switch (GET_CODE (desc))
1030169689Skan	{
1031169689Skan	case DEFINE_INSN:
1032169689Skan	  gen_insn (desc, line_no);
1033169689Skan	  break;
1034169689Skan
1035169689Skan	case DEFINE_PEEPHOLE:
1036169689Skan	  gen_peephole (desc, line_no);
1037169689Skan	  break;
1038169689Skan
1039169689Skan	case DEFINE_EXPAND:
1040169689Skan	  gen_expand (desc, line_no);
1041169689Skan	  break;
1042169689Skan
1043169689Skan	case DEFINE_SPLIT:
1044169689Skan	case DEFINE_PEEPHOLE2:
1045169689Skan	  gen_split (desc, line_no);
1046169689Skan	  break;
1047169689Skan
1048169689Skan#ifdef USE_MD_CONSTRAINTS
1049169689Skan	case DEFINE_CONSTRAINT:
1050169689Skan	case DEFINE_REGISTER_CONSTRAINT:
1051169689Skan	case DEFINE_ADDRESS_CONSTRAINT:
1052169689Skan	case DEFINE_MEMORY_CONSTRAINT:
1053169689Skan	  note_constraint (desc, line_no);
1054169689Skan	  break;
1055169689Skan#endif
1056169689Skan
1057169689Skan	default:
1058169689Skan	  break;
1059169689Skan	}
106018334Speter      next_index_number++;
106118334Speter    }
106218334Speter
106390075Sobrien  printf("\n\n");
106490075Sobrien  output_operand_data ();
106590075Sobrien  output_insn_data ();
106690075Sobrien  output_get_insn_name ();
106718334Speter
106818334Speter  fflush (stdout);
106990075Sobrien  return (ferror (stdout) != 0 || have_error
107018334Speter	? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
107118334Speter}
107218334Speter
107390075Sobrien/* Return the number of occurrences of character C in string S or
107490075Sobrien   -1 if S is the null string.  */
107590075Sobrien
107618334Speterstatic int
1077132718Skann_occurrences (int c, const char *s)
107818334Speter{
107918334Speter  int n = 0;
108090075Sobrien
108190075Sobrien  if (s == 0 || *s == '\0')
108290075Sobrien    return -1;
108390075Sobrien
108418334Speter  while (*s)
108518334Speter    n += (*s++ == c);
108690075Sobrien
108718334Speter  return n;
108818334Speter}
108990075Sobrien
109090075Sobrien/* Remove whitespace in `s' by moving up characters until the end.
109190075Sobrien   Return a new string.  */
109290075Sobrien
109390075Sobrienstatic const char *
1094132718Skanstrip_whitespace (const char *s)
109590075Sobrien{
109690075Sobrien  char *p, *q;
109790075Sobrien  char ch;
109890075Sobrien
109990075Sobrien  if (s == 0)
110090075Sobrien    return 0;
110190075Sobrien
1102169689Skan  p = q = XNEWVEC (char, strlen (s) + 1);
110390075Sobrien  while ((ch = *s++) != '\0')
110490075Sobrien    if (! ISSPACE (ch))
110590075Sobrien      *p++ = ch;
110690075Sobrien
110790075Sobrien  *p = '\0';
110890075Sobrien  return q;
110990075Sobrien}
1110132718Skan
1111169689Skan#ifdef USE_MD_CONSTRAINTS
1112169689Skan
1113169689Skan/* Record just enough information about a constraint to allow checking
1114169689Skan   of operand constraint strings above, in validate_insn_alternatives.
1115169689Skan   Does not validate most properties of the constraint itself; does
1116169689Skan   enforce no duplicate names, no overlap with MI constraints, and no
1117169689Skan   prefixes.  EXP is the define_*constraint form, LINENO the line number
1118169689Skan   reported by the reader.  */
1119169689Skanstatic void
1120169689Skannote_constraint (rtx exp, int lineno)
1121169689Skan{
1122169689Skan  const char *name = XSTR (exp, 0);
1123169689Skan  unsigned int namelen = strlen (name);
1124169689Skan  struct constraint_data **iter, **slot, *new;
1125169689Skan
1126169689Skan  if (strchr (indep_constraints, name[0]))
1127169689Skan    {
1128169689Skan      if (name[1] == '\0')
1129169689Skan	message_with_line (lineno, "constraint letter '%s' cannot be "
1130169689Skan			   "redefined by the machine description", name);
1131169689Skan      else
1132169689Skan	message_with_line (lineno, "constraint name '%s' cannot be defined by "
1133169689Skan			   "the machine description, as it begins with '%c'",
1134169689Skan			   name, name[0]);
1135169689Skan      have_error = 1;
1136169689Skan      return;
1137169689Skan    }
1138169689Skan
1139169689Skan  slot = &constraints_by_letter_table[(unsigned int)name[0]];
1140169689Skan  for (iter = slot; *iter; iter = &(*iter)->next_this_letter)
1141169689Skan    {
1142169689Skan      /* This causes slot to end up pointing to the
1143169689Skan	 next_this_letter field of the last constraint with a name
1144169689Skan	 of equal or greater length than the new constraint; hence
1145169689Skan	 the new constraint will be inserted after all previous
1146169689Skan	 constraints with names of the same length.  */
1147169689Skan      if ((*iter)->namelen >= namelen)
1148169689Skan	slot = iter;
1149169689Skan
1150169689Skan      if (!strcmp ((*iter)->name, name))
1151169689Skan	{
1152169689Skan	  message_with_line (lineno, "redefinition of constraint '%s'", name);
1153169689Skan	  message_with_line ((*iter)->lineno, "previous definition is here");
1154169689Skan	  have_error = 1;
1155169689Skan	  return;
1156169689Skan	}
1157169689Skan      else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
1158169689Skan	{
1159169689Skan	  message_with_line (lineno, "defining constraint '%s' here", name);
1160169689Skan	  message_with_line ((*iter)->lineno, "renders constraint '%s' "
1161169689Skan			     "(defined here) a prefix", (*iter)->name);
1162169689Skan	  have_error = 1;
1163169689Skan	  return;
1164169689Skan	}
1165169689Skan      else if (!strncmp ((*iter)->name, name, namelen))
1166169689Skan	{
1167169689Skan	  message_with_line (lineno, "constraint '%s' is a prefix", name);
1168169689Skan	  message_with_line ((*iter)->lineno, "of constraint '%s' "
1169169689Skan			     "(defined here)", (*iter)->name);
1170169689Skan	  have_error = 1;
1171169689Skan	  return;
1172169689Skan	}
1173169689Skan    }
1174169689Skan  new = xmalloc (sizeof (struct constraint_data) + namelen);
1175169689Skan  strcpy ((char *)new + offsetof(struct constraint_data, name), name);
1176169689Skan  new->namelen = namelen;
1177169689Skan  new->lineno = lineno;
1178169689Skan  new->next_this_letter = *slot;
1179169689Skan  *slot = new;
1180169689Skan}
1181169689Skan
1182169689Skan/* Return the length of the constraint name beginning at position S
1183169689Skan   of an operand constraint string, or issue an error message if there
1184169689Skan   is no such constraint.  Does not expect to be called for generic
1185169689Skan   constraints.  */
1186169689Skanstatic int
1187169689Skanmdep_constraint_len (const char *s, int lineno, int opno)
1188169689Skan{
1189169689Skan  struct constraint_data *p;
1190169689Skan
1191169689Skan  p = constraints_by_letter_table[(unsigned int)s[0]];
1192169689Skan
1193169689Skan  if (p)
1194169689Skan    for (; p; p = p->next_this_letter)
1195169689Skan      if (!strncmp (s, p->name, p->namelen))
1196169689Skan	return p->namelen;
1197169689Skan
1198169689Skan  message_with_line (lineno,
1199169689Skan		     "error: undefined machine-specific constraint "
1200169689Skan		     "at this point: \"%s\"", s);
1201169689Skan  message_with_line (lineno, "note:  in operand %d", opno);
1202169689Skan  have_error = 1;
1203169689Skan  return 1; /* safe */
1204169689Skan}
1205169689Skan
1206169689Skan#else
1207132718Skan/* Verify that DEFAULT_CONSTRAINT_LEN is used properly and not
1208132718Skan   tampered with.  This isn't bullet-proof, but it should catch
1209132718Skan   most genuine mistakes.  */
1210132718Skanstatic void
1211132718Skancheck_constraint_len (void)
1212132718Skan{
1213132718Skan  const char *p;
1214132718Skan  int d;
1215132718Skan
1216132718Skan  for (p = ",#*+=&%!1234567890"; *p; p++)
1217132718Skan    for (d = -9; d < 9; d++)
1218169689Skan      gcc_assert (constraint_len (p, d) == d);
1219132718Skan}
1220132718Skan
1221132718Skanstatic int
1222132718Skanconstraint_len (const char *p, int genoutput_default_constraint_len)
1223132718Skan{
1224132718Skan  /* Check that we still match defaults.h .  First we do a generation-time
1225132718Skan     check that fails if the value is not the expected one...  */
1226169689Skan  gcc_assert (DEFAULT_CONSTRAINT_LEN (*p, p) == 1);
1227132718Skan  /* And now a compile-time check that should give a diagnostic if the
1228132718Skan     definition doesn't exactly match.  */
1229132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
1230132718Skan  /* Now re-define DEFAULT_CONSTRAINT_LEN so that we can verify it is
1231132718Skan     being used.  */
1232132718Skan#undef DEFAULT_CONSTRAINT_LEN
1233132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) \
1234132718Skan  ((C) != *p || STR != p ? -1 : genoutput_default_constraint_len)
1235132718Skan  return CONSTRAINT_LEN (*p, p);
1236132718Skan  /* And set it back.  */
1237132718Skan#undef DEFAULT_CONSTRAINT_LEN
1238132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
1239132718Skan}
1240169689Skan#endif
1241