190075Sobrien/* Support routines for the various generation passes.
2169689Skan   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
3132718Skan   Free Software Foundation, Inc.
490075Sobrien
590075Sobrien   This file is part of GCC.
690075Sobrien
790075Sobrien   GCC is free software; you can redistribute it and/or modify it
890075Sobrien   under the terms of the GNU General Public License as published by
990075Sobrien   the Free Software Foundation; either version 2, or (at your option)
1090075Sobrien   any later version.
1190075Sobrien
1290075Sobrien   GCC is distributed in the hope that it will be useful, but WITHOUT
1390075Sobrien   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1490075Sobrien   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1590075Sobrien   License for more details.
1690075Sobrien
1790075Sobrien   You should have received a copy of the GNU General Public License
1890075Sobrien   along with GCC; see the file COPYING.  If not, write to the Free
19169689Skan   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan   02110-1301, USA.  */
2190075Sobrien
22132718Skan#include "bconfig.h"
2390075Sobrien#include "system.h"
24132718Skan#include "coretypes.h"
25132718Skan#include "tm.h"
2690075Sobrien#include "rtl.h"
2790075Sobrien#include "obstack.h"
2890075Sobrien#include "errors.h"
29117395Skan#include "hashtab.h"
3090075Sobrien#include "gensupport.h"
3190075Sobrien
3290075Sobrien
3390075Sobrien/* In case some macros used by files we include need it, define this here.  */
3490075Sobrienint target_flags;
3590075Sobrien
36117395Skanint insn_elision = 1;
37117395Skan
38169689Skanconst char *in_fname;
39169689Skan
40169689Skan/* This callback will be invoked whenever an rtl include directive is
41169689Skan   processed.  To be used for creation of the dependency file.  */
42169689Skanvoid (*include_callback) (const char *);
43169689Skan
4490075Sobrienstatic struct obstack obstack;
4590075Sobrienstruct obstack *rtl_obstack = &obstack;
4690075Sobrien
4790075Sobrienstatic int sequence_num;
4890075Sobrienstatic int errors;
4990075Sobrien
5090075Sobrienstatic int predicable_default;
5190075Sobrienstatic const char *predicable_true;
5290075Sobrienstatic const char *predicable_false;
5390075Sobrien
54117395Skanstatic htab_t condition_table;
55117395Skan
5690075Sobrienstatic char *base_dir = NULL;
5790075Sobrien
5890075Sobrien/* We initially queue all patterns, process the define_insn and
5990075Sobrien   define_cond_exec patterns, then return them one at a time.  */
6090075Sobrien
6190075Sobrienstruct queue_elem
6290075Sobrien{
6390075Sobrien  rtx data;
64117395Skan  const char *filename;
6590075Sobrien  int lineno;
6690075Sobrien  struct queue_elem *next;
67169689Skan  /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
68169689Skan     points to the generated DEFINE_SPLIT.  */
69169689Skan  struct queue_elem *split;
7090075Sobrien};
7190075Sobrien
7290075Sobrienstatic struct queue_elem *define_attr_queue;
7390075Sobrienstatic struct queue_elem **define_attr_tail = &define_attr_queue;
74169689Skanstatic struct queue_elem *define_pred_queue;
75169689Skanstatic struct queue_elem **define_pred_tail = &define_pred_queue;
7690075Sobrienstatic struct queue_elem *define_insn_queue;
7790075Sobrienstatic struct queue_elem **define_insn_tail = &define_insn_queue;
7890075Sobrienstatic struct queue_elem *define_cond_exec_queue;
7990075Sobrienstatic struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
8090075Sobrienstatic struct queue_elem *other_queue;
8190075Sobrienstatic struct queue_elem **other_tail = &other_queue;
8290075Sobrien
83169689Skanstatic struct queue_elem *queue_pattern (rtx, struct queue_elem ***,
84169689Skan					 const char *, int);
8590075Sobrien
8690075Sobrien/* Current maximum length of directory names in the search path
8790075Sobrien   for include files.  (Altered as we get more of them.)  */
8890075Sobrien
8990075Sobriensize_t max_include_len;
9090075Sobrien
9190075Sobrienstruct file_name_list
9290075Sobrien  {
9390075Sobrien    struct file_name_list *next;
9490075Sobrien    const char *fname;
9590075Sobrien  };
9690075Sobrien
97117395Skanstruct file_name_list *first_dir_md_include = 0;  /* First dir to search */
9890075Sobrien        /* First dir to search for <file> */
9990075Sobrienstruct file_name_list *first_bracket_include = 0;
100117395Skanstruct file_name_list *last_dir_md_include = 0;        /* Last in chain */
10190075Sobrien
102132718Skanstatic void remove_constraints (rtx);
103132718Skanstatic void process_rtx (rtx, int);
10490075Sobrien
105132718Skanstatic int is_predicable (struct queue_elem *);
106132718Skanstatic void identify_predicable_attribute (void);
107132718Skanstatic int n_alternatives (const char *);
108132718Skanstatic void collect_insn_data (rtx, int *, int *);
109132718Skanstatic rtx alter_predicate_for_insn (rtx, int, int, int);
110132718Skanstatic const char *alter_test_for_insn (struct queue_elem *,
111132718Skan					struct queue_elem *);
112132718Skanstatic char *shift_output_template (char *, const char *, int);
113132718Skanstatic const char *alter_output_for_insn (struct queue_elem *,
114132718Skan					  struct queue_elem *,
115132718Skan					  int, int);
116132718Skanstatic void process_one_cond_exec (struct queue_elem *);
117132718Skanstatic void process_define_cond_exec (void);
118132718Skanstatic void process_include (rtx, int);
119132718Skanstatic char *save_string (const char *, int);
120169689Skanstatic void init_predicate_table (void);
121169689Skanstatic void record_insn_name (int, const char *);
12290075Sobrien
12390075Sobrienvoid
124132718Skanmessage_with_line (int lineno, const char *msg, ...)
12590075Sobrien{
126132718Skan  va_list ap;
12790075Sobrien
128132718Skan  va_start (ap, msg);
129132718Skan
13090075Sobrien  fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
13190075Sobrien  vfprintf (stderr, msg, ap);
13290075Sobrien  fputc ('\n', stderr);
13390075Sobrien
134132718Skan  va_end (ap);
13590075Sobrien}
13690075Sobrien
13790075Sobrien/* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
13890075Sobrien   the gensupport programs.  */
13990075Sobrien
14090075Sobrienrtx
141169689Skangen_rtx_CONST_INT (enum machine_mode ARG_UNUSED (mode),
142132718Skan		   HOST_WIDE_INT arg)
14390075Sobrien{
14490075Sobrien  rtx rt = rtx_alloc (CONST_INT);
14590075Sobrien
14690075Sobrien  XWINT (rt, 0) = arg;
14790075Sobrien  return rt;
14890075Sobrien}
14990075Sobrien
150169689Skan/* Queue PATTERN on LIST_TAIL.  Return the address of the new queue
151169689Skan   element.  */
15290075Sobrien
153169689Skanstatic struct queue_elem *
154132718Skanqueue_pattern (rtx pattern, struct queue_elem ***list_tail,
155132718Skan	       const char *filename, int lineno)
15690075Sobrien{
157169689Skan  struct queue_elem *e = XNEW(struct queue_elem);
15890075Sobrien  e->data = pattern;
159117395Skan  e->filename = filename;
16090075Sobrien  e->lineno = lineno;
16190075Sobrien  e->next = NULL;
162169689Skan  e->split = NULL;
16390075Sobrien  **list_tail = e;
16490075Sobrien  *list_tail = &e->next;
165169689Skan  return e;
16690075Sobrien}
16790075Sobrien
16890075Sobrien/* Recursively remove constraints from an rtx.  */
16990075Sobrien
17090075Sobrienstatic void
171132718Skanremove_constraints (rtx part)
17290075Sobrien{
17390075Sobrien  int i, j;
17490075Sobrien  const char *format_ptr;
17590075Sobrien
17690075Sobrien  if (part == 0)
17790075Sobrien    return;
17890075Sobrien
17990075Sobrien  if (GET_CODE (part) == MATCH_OPERAND)
18090075Sobrien    XSTR (part, 2) = "";
18190075Sobrien  else if (GET_CODE (part) == MATCH_SCRATCH)
18290075Sobrien    XSTR (part, 1) = "";
18390075Sobrien
18490075Sobrien  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
18590075Sobrien
18690075Sobrien  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
18790075Sobrien    switch (*format_ptr++)
18890075Sobrien      {
18990075Sobrien      case 'e':
19090075Sobrien      case 'u':
19190075Sobrien	remove_constraints (XEXP (part, i));
19290075Sobrien	break;
19390075Sobrien      case 'E':
19490075Sobrien	if (XVEC (part, i) != NULL)
19590075Sobrien	  for (j = 0; j < XVECLEN (part, i); j++)
19690075Sobrien	    remove_constraints (XVECEXP (part, i, j));
19790075Sobrien	break;
19890075Sobrien      }
19990075Sobrien}
20090075Sobrien
201132718Skan/* Process an include file assuming that it lives in gcc/config/{target}/
202117395Skan   if the include looks like (include "file").  */
20390075Sobrien
204117395Skanstatic void
205132718Skanprocess_include (rtx desc, int lineno)
20690075Sobrien{
20790075Sobrien  const char *filename = XSTR (desc, 0);
208117395Skan  const char *old_filename;
209117395Skan  int old_lineno;
210117395Skan  char *pathname;
21190075Sobrien  FILE *input_file;
21290075Sobrien
213117395Skan  /* If specified file name is absolute, skip the include stack.  */
214132718Skan  if (! IS_ABSOLUTE_PATH (filename))
21590075Sobrien    {
216117395Skan      struct file_name_list *stackp;
21790075Sobrien
218117395Skan      /* Search directory path, trying to open the file.  */
219117395Skan      for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
22090075Sobrien	{
221117395Skan	  static const char sep[2] = { DIR_SEPARATOR, '\0' };
222117395Skan
223117395Skan	  pathname = concat (stackp->fname, sep, filename, NULL);
224117395Skan	  input_file = fopen (pathname, "r");
225132718Skan	  if (input_file != NULL)
226117395Skan	    goto success;
227117395Skan	  free (pathname);
22890075Sobrien	}
22990075Sobrien    }
230117395Skan
231117395Skan  if (base_dir)
232117395Skan    pathname = concat (base_dir, filename, NULL);
233117395Skan  else
234117395Skan    pathname = xstrdup (filename);
235117395Skan  input_file = fopen (pathname, "r");
236117395Skan  if (input_file == NULL)
23790075Sobrien    {
238117395Skan      free (pathname);
239117395Skan      message_with_line (lineno, "include file `%s' not found", filename);
240117395Skan      errors = 1;
241117395Skan      return;
242117395Skan    }
243117395Skan success:
24490075Sobrien
245117395Skan  /* Save old cursor; setup new for the new file.  Note that "lineno" the
246117395Skan     argument to this function is the beginning of the include statement,
247117395Skan     while read_rtx_lineno has already been advanced.  */
248117395Skan  old_filename = read_rtx_filename;
249117395Skan  old_lineno = read_rtx_lineno;
250117395Skan  read_rtx_filename = pathname;
251117395Skan  read_rtx_lineno = 1;
25290075Sobrien
253169689Skan  if (include_callback)
254169689Skan    include_callback (pathname);
255169689Skan
256117395Skan  /* Read the entire file.  */
257169689Skan  while (read_rtx (input_file, &desc, &lineno))
258169689Skan    process_rtx (desc, lineno);
25990075Sobrien
260117395Skan  /* Do not free pathname.  It is attached to the various rtx queue
261117395Skan     elements.  */
26290075Sobrien
263117395Skan  read_rtx_filename = old_filename;
264117395Skan  read_rtx_lineno = old_lineno;
26590075Sobrien
266117395Skan  fclose (input_file);
26790075Sobrien}
26890075Sobrien
269132718Skan/* Process a top level rtx in some way, queuing as appropriate.  */
27090075Sobrien
27190075Sobrienstatic void
272132718Skanprocess_rtx (rtx desc, int lineno)
27390075Sobrien{
27490075Sobrien  switch (GET_CODE (desc))
27590075Sobrien    {
27690075Sobrien    case DEFINE_INSN:
277117395Skan      queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
27890075Sobrien      break;
27990075Sobrien
28090075Sobrien    case DEFINE_COND_EXEC:
281117395Skan      queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
28290075Sobrien      break;
28390075Sobrien
28490075Sobrien    case DEFINE_ATTR:
285117395Skan      queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
28690075Sobrien      break;
28790075Sobrien
288169689Skan    case DEFINE_PREDICATE:
289169689Skan    case DEFINE_SPECIAL_PREDICATE:
290169689Skan    case DEFINE_CONSTRAINT:
291169689Skan    case DEFINE_REGISTER_CONSTRAINT:
292169689Skan    case DEFINE_MEMORY_CONSTRAINT:
293169689Skan    case DEFINE_ADDRESS_CONSTRAINT:
294169689Skan      queue_pattern (desc, &define_pred_tail, read_rtx_filename, lineno);
295169689Skan      break;
296169689Skan
29790075Sobrien    case INCLUDE:
298117395Skan      process_include (desc, lineno);
29990075Sobrien      break;
30090075Sobrien
30190075Sobrien    case DEFINE_INSN_AND_SPLIT:
30290075Sobrien      {
30390075Sobrien	const char *split_cond;
30490075Sobrien	rtx split;
30590075Sobrien	rtvec attr;
30690075Sobrien	int i;
307169689Skan	struct queue_elem *insn_elem;
308169689Skan	struct queue_elem *split_elem;
30990075Sobrien
31090075Sobrien	/* Create a split with values from the insn_and_split.  */
31190075Sobrien	split = rtx_alloc (DEFINE_SPLIT);
31290075Sobrien
31390075Sobrien	i = XVECLEN (desc, 1);
31490075Sobrien	XVEC (split, 0) = rtvec_alloc (i);
31590075Sobrien	while (--i >= 0)
31690075Sobrien	  {
31790075Sobrien	    XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
31890075Sobrien	    remove_constraints (XVECEXP (split, 0, i));
31990075Sobrien	  }
32090075Sobrien
32190075Sobrien	/* If the split condition starts with "&&", append it to the
32290075Sobrien	   insn condition to create the new split condition.  */
32390075Sobrien	split_cond = XSTR (desc, 4);
32490075Sobrien	if (split_cond[0] == '&' && split_cond[1] == '&')
325169689Skan	  {
326169689Skan	    copy_rtx_ptr_loc (split_cond + 2, split_cond);
327169689Skan	    split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2);
328169689Skan	  }
32990075Sobrien	XSTR (split, 1) = split_cond;
33090075Sobrien	XVEC (split, 2) = XVEC (desc, 5);
33190075Sobrien	XSTR (split, 3) = XSTR (desc, 6);
33290075Sobrien
33390075Sobrien	/* Fix up the DEFINE_INSN.  */
33490075Sobrien	attr = XVEC (desc, 7);
33590075Sobrien	PUT_CODE (desc, DEFINE_INSN);
33690075Sobrien	XVEC (desc, 4) = attr;
33790075Sobrien
33890075Sobrien	/* Queue them.  */
339169689Skan	insn_elem
340169689Skan	  = queue_pattern (desc, &define_insn_tail, read_rtx_filename,
341169689Skan			   lineno);
342169689Skan	split_elem
343169689Skan	  = queue_pattern (split, &other_tail, read_rtx_filename, lineno);
344169689Skan	insn_elem->split = split_elem;
34590075Sobrien	break;
34690075Sobrien      }
34790075Sobrien
34890075Sobrien    default:
349117395Skan      queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
35090075Sobrien      break;
35190075Sobrien    }
35290075Sobrien}
35390075Sobrien
35490075Sobrien/* Return true if attribute PREDICABLE is true for ELEM, which holds
35590075Sobrien   a DEFINE_INSN.  */
35690075Sobrien
35790075Sobrienstatic int
358132718Skanis_predicable (struct queue_elem *elem)
35990075Sobrien{
36090075Sobrien  rtvec vec = XVEC (elem->data, 4);
36190075Sobrien  const char *value;
36290075Sobrien  int i;
36390075Sobrien
36490075Sobrien  if (! vec)
36590075Sobrien    return predicable_default;
36690075Sobrien
36790075Sobrien  for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
36890075Sobrien    {
36990075Sobrien      rtx sub = RTVEC_ELT (vec, i);
37090075Sobrien      switch (GET_CODE (sub))
37190075Sobrien	{
37290075Sobrien	case SET_ATTR:
37390075Sobrien	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
37490075Sobrien	    {
37590075Sobrien	      value = XSTR (sub, 1);
37690075Sobrien	      goto found;
37790075Sobrien	    }
37890075Sobrien	  break;
37990075Sobrien
38090075Sobrien	case SET_ATTR_ALTERNATIVE:
38190075Sobrien	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
38290075Sobrien	    {
38390075Sobrien	      message_with_line (elem->lineno,
38490075Sobrien				 "multiple alternatives for `predicable'");
38590075Sobrien	      errors = 1;
38690075Sobrien	      return 0;
38790075Sobrien	    }
38890075Sobrien	  break;
38990075Sobrien
39090075Sobrien	case SET:
39190075Sobrien	  if (GET_CODE (SET_DEST (sub)) != ATTR
39290075Sobrien	      || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
39390075Sobrien	    break;
39490075Sobrien	  sub = SET_SRC (sub);
39590075Sobrien	  if (GET_CODE (sub) == CONST_STRING)
39690075Sobrien	    {
39790075Sobrien	      value = XSTR (sub, 0);
39890075Sobrien	      goto found;
39990075Sobrien	    }
40090075Sobrien
40190075Sobrien	  /* ??? It would be possible to handle this if we really tried.
40290075Sobrien	     It's not easy though, and I'm not going to bother until it
40390075Sobrien	     really proves necessary.  */
40490075Sobrien	  message_with_line (elem->lineno,
40590075Sobrien			     "non-constant value for `predicable'");
40690075Sobrien	  errors = 1;
40790075Sobrien	  return 0;
40890075Sobrien
40990075Sobrien	default:
410169689Skan	  gcc_unreachable ();
41190075Sobrien	}
41290075Sobrien    }
41390075Sobrien
41490075Sobrien  return predicable_default;
41590075Sobrien
41690075Sobrien found:
41790075Sobrien  /* Verify that predicability does not vary on the alternative.  */
41890075Sobrien  /* ??? It should be possible to handle this by simply eliminating
41990075Sobrien     the non-predicable alternatives from the insn.  FRV would like
42090075Sobrien     to do this.  Delay this until we've got the basics solid.  */
42190075Sobrien  if (strchr (value, ',') != NULL)
42290075Sobrien    {
42390075Sobrien      message_with_line (elem->lineno,
42490075Sobrien			 "multiple alternatives for `predicable'");
42590075Sobrien      errors = 1;
42690075Sobrien      return 0;
42790075Sobrien    }
42890075Sobrien
42990075Sobrien  /* Find out which value we're looking at.  */
43090075Sobrien  if (strcmp (value, predicable_true) == 0)
43190075Sobrien    return 1;
43290075Sobrien  if (strcmp (value, predicable_false) == 0)
43390075Sobrien    return 0;
43490075Sobrien
43590075Sobrien  message_with_line (elem->lineno,
43690075Sobrien		     "unknown value `%s' for `predicable' attribute",
43790075Sobrien		     value);
43890075Sobrien  errors = 1;
43990075Sobrien  return 0;
44090075Sobrien}
44190075Sobrien
44290075Sobrien/* Examine the attribute "predicable"; discover its boolean values
44390075Sobrien   and its default.  */
44490075Sobrien
44590075Sobrienstatic void
446132718Skanidentify_predicable_attribute (void)
44790075Sobrien{
44890075Sobrien  struct queue_elem *elem;
44990075Sobrien  char *p_true, *p_false;
45090075Sobrien  const char *value;
45190075Sobrien
45290075Sobrien  /* Look for the DEFINE_ATTR for `predicable', which must exist.  */
45390075Sobrien  for (elem = define_attr_queue; elem ; elem = elem->next)
45490075Sobrien    if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
45590075Sobrien      goto found;
45690075Sobrien
45790075Sobrien  message_with_line (define_cond_exec_queue->lineno,
45890075Sobrien		     "attribute `predicable' not defined");
45990075Sobrien  errors = 1;
46090075Sobrien  return;
46190075Sobrien
46290075Sobrien found:
46390075Sobrien  value = XSTR (elem->data, 1);
464117395Skan  p_false = xstrdup (value);
46590075Sobrien  p_true = strchr (p_false, ',');
46690075Sobrien  if (p_true == NULL || strchr (++p_true, ',') != NULL)
46790075Sobrien    {
46890075Sobrien      message_with_line (elem->lineno,
46990075Sobrien			 "attribute `predicable' is not a boolean");
47090075Sobrien      errors = 1;
471169689Skan      if (p_false)
472169689Skan        free (p_false);
47390075Sobrien      return;
47490075Sobrien    }
47590075Sobrien  p_true[-1] = '\0';
47690075Sobrien
47790075Sobrien  predicable_true = p_true;
47890075Sobrien  predicable_false = p_false;
47990075Sobrien
48090075Sobrien  switch (GET_CODE (XEXP (elem->data, 2)))
48190075Sobrien    {
48290075Sobrien    case CONST_STRING:
48390075Sobrien      value = XSTR (XEXP (elem->data, 2), 0);
48490075Sobrien      break;
48590075Sobrien
48690075Sobrien    case CONST:
48790075Sobrien      message_with_line (elem->lineno,
48890075Sobrien			 "attribute `predicable' cannot be const");
48990075Sobrien      errors = 1;
490169689Skan      if (p_false)
491169689Skan	free (p_false);
49290075Sobrien      return;
49390075Sobrien
49490075Sobrien    default:
49590075Sobrien      message_with_line (elem->lineno,
49690075Sobrien			 "attribute `predicable' must have a constant default");
49790075Sobrien      errors = 1;
498169689Skan      if (p_false)
499169689Skan	free (p_false);
50090075Sobrien      return;
50190075Sobrien    }
50290075Sobrien
50390075Sobrien  if (strcmp (value, p_true) == 0)
50490075Sobrien    predicable_default = 1;
50590075Sobrien  else if (strcmp (value, p_false) == 0)
50690075Sobrien    predicable_default = 0;
50790075Sobrien  else
50890075Sobrien    {
50990075Sobrien      message_with_line (elem->lineno,
51090075Sobrien			 "unknown value `%s' for `predicable' attribute",
51190075Sobrien			 value);
51290075Sobrien      errors = 1;
513169689Skan      if (p_false)
514169689Skan	free (p_false);
51590075Sobrien    }
51690075Sobrien}
51790075Sobrien
51890075Sobrien/* Return the number of alternatives in constraint S.  */
51990075Sobrien
52090075Sobrienstatic int
521132718Skann_alternatives (const char *s)
52290075Sobrien{
52390075Sobrien  int n = 1;
52490075Sobrien
52590075Sobrien  if (s)
52690075Sobrien    while (*s)
52790075Sobrien      n += (*s++ == ',');
52890075Sobrien
52990075Sobrien  return n;
53090075Sobrien}
53190075Sobrien
53290075Sobrien/* Determine how many alternatives there are in INSN, and how many
53390075Sobrien   operands.  */
53490075Sobrien
53590075Sobrienstatic void
536132718Skancollect_insn_data (rtx pattern, int *palt, int *pmax)
53790075Sobrien{
53890075Sobrien  const char *fmt;
53990075Sobrien  enum rtx_code code;
54090075Sobrien  int i, j, len;
54190075Sobrien
54290075Sobrien  code = GET_CODE (pattern);
54390075Sobrien  switch (code)
54490075Sobrien    {
54590075Sobrien    case MATCH_OPERAND:
54690075Sobrien      i = n_alternatives (XSTR (pattern, 2));
54790075Sobrien      *palt = (i > *palt ? i : *palt);
548132718Skan      /* Fall through.  */
54990075Sobrien
55090075Sobrien    case MATCH_OPERATOR:
55190075Sobrien    case MATCH_SCRATCH:
55290075Sobrien    case MATCH_PARALLEL:
55390075Sobrien      i = XINT (pattern, 0);
55490075Sobrien      if (i > *pmax)
55590075Sobrien	*pmax = i;
55690075Sobrien      break;
55790075Sobrien
55890075Sobrien    default:
55990075Sobrien      break;
56090075Sobrien    }
56190075Sobrien
56290075Sobrien  fmt = GET_RTX_FORMAT (code);
56390075Sobrien  len = GET_RTX_LENGTH (code);
56490075Sobrien  for (i = 0; i < len; i++)
56590075Sobrien    {
56690075Sobrien      switch (fmt[i])
56790075Sobrien	{
56890075Sobrien	case 'e': case 'u':
56990075Sobrien	  collect_insn_data (XEXP (pattern, i), palt, pmax);
57090075Sobrien	  break;
57190075Sobrien
57290075Sobrien	case 'V':
57390075Sobrien	  if (XVEC (pattern, i) == NULL)
57490075Sobrien	    break;
575132718Skan	  /* Fall through.  */
57690075Sobrien	case 'E':
57790075Sobrien	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
57890075Sobrien	    collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
57990075Sobrien	  break;
58090075Sobrien
58190075Sobrien	case 'i': case 'w': case '0': case 's': case 'S': case 'T':
58290075Sobrien	  break;
58390075Sobrien
58490075Sobrien	default:
585169689Skan	  gcc_unreachable ();
58690075Sobrien	}
58790075Sobrien    }
58890075Sobrien}
58990075Sobrien
59090075Sobrienstatic rtx
591132718Skanalter_predicate_for_insn (rtx pattern, int alt, int max_op, int lineno)
59290075Sobrien{
59390075Sobrien  const char *fmt;
59490075Sobrien  enum rtx_code code;
59590075Sobrien  int i, j, len;
59690075Sobrien
59790075Sobrien  code = GET_CODE (pattern);
59890075Sobrien  switch (code)
59990075Sobrien    {
60090075Sobrien    case MATCH_OPERAND:
60190075Sobrien      {
60290075Sobrien	const char *c = XSTR (pattern, 2);
60390075Sobrien
60490075Sobrien	if (n_alternatives (c) != 1)
60590075Sobrien	  {
60690075Sobrien	    message_with_line (lineno,
60790075Sobrien			       "too many alternatives for operand %d",
60890075Sobrien			       XINT (pattern, 0));
60990075Sobrien	    errors = 1;
61090075Sobrien	    return NULL;
61190075Sobrien	  }
61290075Sobrien
61390075Sobrien	/* Replicate C as needed to fill out ALT alternatives.  */
61490075Sobrien	if (c && *c && alt > 1)
61590075Sobrien	  {
61690075Sobrien	    size_t c_len = strlen (c);
61790075Sobrien	    size_t len = alt * (c_len + 1);
618169689Skan	    char *new_c = XNEWVEC(char, len);
61990075Sobrien
62090075Sobrien	    memcpy (new_c, c, c_len);
62190075Sobrien	    for (i = 1; i < alt; ++i)
62290075Sobrien	      {
62390075Sobrien		new_c[i * (c_len + 1) - 1] = ',';
62490075Sobrien		memcpy (&new_c[i * (c_len + 1)], c, c_len);
62590075Sobrien	      }
62690075Sobrien	    new_c[len - 1] = '\0';
62790075Sobrien	    XSTR (pattern, 2) = new_c;
62890075Sobrien	  }
62990075Sobrien      }
630132718Skan      /* Fall through.  */
63190075Sobrien
63290075Sobrien    case MATCH_OPERATOR:
63390075Sobrien    case MATCH_SCRATCH:
63490075Sobrien    case MATCH_PARALLEL:
63590075Sobrien      XINT (pattern, 0) += max_op;
63690075Sobrien      break;
63790075Sobrien
63890075Sobrien    default:
63990075Sobrien      break;
64090075Sobrien    }
64190075Sobrien
64290075Sobrien  fmt = GET_RTX_FORMAT (code);
64390075Sobrien  len = GET_RTX_LENGTH (code);
64490075Sobrien  for (i = 0; i < len; i++)
64590075Sobrien    {
64690075Sobrien      rtx r;
64790075Sobrien
64890075Sobrien      switch (fmt[i])
64990075Sobrien	{
65090075Sobrien	case 'e': case 'u':
65190075Sobrien	  r = alter_predicate_for_insn (XEXP (pattern, i), alt,
65290075Sobrien					max_op, lineno);
65390075Sobrien	  if (r == NULL)
65490075Sobrien	    return r;
65590075Sobrien	  break;
65690075Sobrien
65790075Sobrien	case 'E':
65890075Sobrien	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
65990075Sobrien	    {
66090075Sobrien	      r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
66190075Sobrien					    alt, max_op, lineno);
66290075Sobrien	      if (r == NULL)
66390075Sobrien		return r;
66490075Sobrien	    }
66590075Sobrien	  break;
66690075Sobrien
66790075Sobrien	case 'i': case 'w': case '0': case 's':
66890075Sobrien	  break;
66990075Sobrien
67090075Sobrien	default:
671169689Skan	  gcc_unreachable ();
67290075Sobrien	}
67390075Sobrien    }
67490075Sobrien
67590075Sobrien  return pattern;
67690075Sobrien}
67790075Sobrien
67890075Sobrienstatic const char *
679132718Skanalter_test_for_insn (struct queue_elem *ce_elem,
680132718Skan		     struct queue_elem *insn_elem)
68190075Sobrien{
682169689Skan  return join_c_conditions (XSTR (ce_elem->data, 1),
683169689Skan			    XSTR (insn_elem->data, 2));
68490075Sobrien}
68590075Sobrien
686169689Skan/* Adjust all of the operand numbers in SRC to match the shift they'll
68790075Sobrien   get from an operand displacement of DISP.  Return a pointer after the
68890075Sobrien   adjusted string.  */
68990075Sobrien
69090075Sobrienstatic char *
691169689Skanshift_output_template (char *dest, const char *src, int disp)
69290075Sobrien{
693169689Skan  while (*src)
69490075Sobrien    {
695169689Skan      char c = *src++;
696169689Skan      *dest++ = c;
69790075Sobrien      if (c == '%')
69890075Sobrien	{
699169689Skan	  c = *src++;
70090075Sobrien	  if (ISDIGIT ((unsigned char) c))
70190075Sobrien	    c += disp;
70290075Sobrien	  else if (ISALPHA (c))
70390075Sobrien	    {
704169689Skan	      *dest++ = c;
705169689Skan	      c = *src++ + disp;
70690075Sobrien	    }
707169689Skan	  *dest++ = c;
70890075Sobrien	}
70990075Sobrien    }
71090075Sobrien
711169689Skan  return dest;
71290075Sobrien}
71390075Sobrien
71490075Sobrienstatic const char *
715132718Skanalter_output_for_insn (struct queue_elem *ce_elem,
716132718Skan		       struct queue_elem *insn_elem,
717132718Skan		       int alt, int max_op)
71890075Sobrien{
71990075Sobrien  const char *ce_out, *insn_out;
720169689Skan  char *result, *p;
72190075Sobrien  size_t len, ce_len, insn_len;
72290075Sobrien
72390075Sobrien  /* ??? Could coordinate with genoutput to not duplicate code here.  */
72490075Sobrien
72590075Sobrien  ce_out = XSTR (ce_elem->data, 2);
72690075Sobrien  insn_out = XTMPL (insn_elem->data, 3);
72790075Sobrien  if (!ce_out || *ce_out == '\0')
72890075Sobrien    return insn_out;
72990075Sobrien
73090075Sobrien  ce_len = strlen (ce_out);
73190075Sobrien  insn_len = strlen (insn_out);
73290075Sobrien
73390075Sobrien  if (*insn_out == '*')
73490075Sobrien    /* You must take care of the predicate yourself.  */
73590075Sobrien    return insn_out;
73690075Sobrien
73790075Sobrien  if (*insn_out == '@')
73890075Sobrien    {
73990075Sobrien      len = (ce_len + 1) * alt + insn_len + 1;
740169689Skan      p = result = XNEWVEC(char, len);
74190075Sobrien
74290075Sobrien      do
74390075Sobrien	{
74490075Sobrien	  do
74590075Sobrien	    *p++ = *insn_out++;
74690075Sobrien	  while (ISSPACE ((unsigned char) *insn_out));
74790075Sobrien
74890075Sobrien	  if (*insn_out != '#')
74990075Sobrien	    {
75090075Sobrien	      p = shift_output_template (p, ce_out, max_op);
75190075Sobrien	      *p++ = ' ';
75290075Sobrien	    }
75390075Sobrien
75490075Sobrien	  do
75590075Sobrien	    *p++ = *insn_out++;
75690075Sobrien	  while (*insn_out && *insn_out != '\n');
75790075Sobrien	}
75890075Sobrien      while (*insn_out);
75990075Sobrien      *p = '\0';
76090075Sobrien    }
76190075Sobrien  else
76290075Sobrien    {
76390075Sobrien      len = ce_len + 1 + insn_len + 1;
764169689Skan      result = XNEWVEC (char, len);
76590075Sobrien
766169689Skan      p = shift_output_template (result, ce_out, max_op);
76790075Sobrien      *p++ = ' ';
76890075Sobrien      memcpy (p, insn_out, insn_len + 1);
76990075Sobrien    }
77090075Sobrien
771169689Skan  return result;
77290075Sobrien}
77390075Sobrien
77490075Sobrien/* Replicate insns as appropriate for the given DEFINE_COND_EXEC.  */
77590075Sobrien
77690075Sobrienstatic void
777132718Skanprocess_one_cond_exec (struct queue_elem *ce_elem)
77890075Sobrien{
77990075Sobrien  struct queue_elem *insn_elem;
78090075Sobrien  for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
78190075Sobrien    {
78290075Sobrien      int alternatives, max_operand;
783169689Skan      rtx pred, insn, pattern, split;
784169689Skan      int i;
78590075Sobrien
78690075Sobrien      if (! is_predicable (insn_elem))
78790075Sobrien	continue;
78890075Sobrien
78990075Sobrien      alternatives = 1;
79090075Sobrien      max_operand = -1;
79190075Sobrien      collect_insn_data (insn_elem->data, &alternatives, &max_operand);
79290075Sobrien      max_operand += 1;
79390075Sobrien
79490075Sobrien      if (XVECLEN (ce_elem->data, 0) != 1)
79590075Sobrien	{
79690075Sobrien	  message_with_line (ce_elem->lineno,
79790075Sobrien			     "too many patterns in predicate");
79890075Sobrien	  errors = 1;
79990075Sobrien	  return;
80090075Sobrien	}
80190075Sobrien
80290075Sobrien      pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
80390075Sobrien      pred = alter_predicate_for_insn (pred, alternatives, max_operand,
80490075Sobrien				       ce_elem->lineno);
80590075Sobrien      if (pred == NULL)
80690075Sobrien	return;
80790075Sobrien
80890075Sobrien      /* Construct a new pattern for the new insn.  */
80990075Sobrien      insn = copy_rtx (insn_elem->data);
81090075Sobrien      XSTR (insn, 0) = "";
81190075Sobrien      pattern = rtx_alloc (COND_EXEC);
81290075Sobrien      XEXP (pattern, 0) = pred;
81390075Sobrien      if (XVECLEN (insn, 1) == 1)
81490075Sobrien	{
81590075Sobrien	  XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
81690075Sobrien	  XVECEXP (insn, 1, 0) = pattern;
81790075Sobrien	  PUT_NUM_ELEM (XVEC (insn, 1), 1);
81890075Sobrien	}
81990075Sobrien      else
82090075Sobrien	{
82190075Sobrien	  XEXP (pattern, 1) = rtx_alloc (PARALLEL);
82290075Sobrien	  XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
82390075Sobrien	  XVEC (insn, 1) = rtvec_alloc (1);
82490075Sobrien	  XVECEXP (insn, 1, 0) = pattern;
82590075Sobrien	}
82690075Sobrien
82790075Sobrien      XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
82890075Sobrien      XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
82990075Sobrien					      alternatives, max_operand);
83090075Sobrien
83190075Sobrien      /* ??? Set `predicable' to false.  Not crucial since it's really
83290075Sobrien         only used here, and we won't reprocess this new pattern.  */
83390075Sobrien
83490075Sobrien      /* Put the new pattern on the `other' list so that it
83590075Sobrien	 (a) is not reprocessed by other define_cond_exec patterns
83690075Sobrien	 (b) appears after all normal define_insn patterns.
83790075Sobrien
83890075Sobrien	 ??? B is debatable.  If one has normal insns that match
83990075Sobrien	 cond_exec patterns, they will be preferred over these
84090075Sobrien	 generated patterns.  Whether this matters in practice, or if
84190075Sobrien	 it's a good thing, or whether we should thread these new
84290075Sobrien	 patterns into the define_insn chain just after their generator
84390075Sobrien	 is something we'll have to experiment with.  */
84490075Sobrien
845117395Skan      queue_pattern (insn, &other_tail, insn_elem->filename,
846117395Skan		     insn_elem->lineno);
847169689Skan
848169689Skan      if (!insn_elem->split)
849169689Skan	continue;
850169689Skan
851169689Skan      /* If the original insn came from a define_insn_and_split,
852169689Skan	 generate a new split to handle the predicated insn.  */
853169689Skan      split = copy_rtx (insn_elem->split->data);
854169689Skan      /* Predicate the pattern matched by the split.  */
855169689Skan      pattern = rtx_alloc (COND_EXEC);
856169689Skan      XEXP (pattern, 0) = pred;
857169689Skan      if (XVECLEN (split, 0) == 1)
858169689Skan	{
859169689Skan	  XEXP (pattern, 1) = XVECEXP (split, 0, 0);
860169689Skan	  XVECEXP (split, 0, 0) = pattern;
861169689Skan	  PUT_NUM_ELEM (XVEC (split, 0), 1);
862169689Skan	}
863169689Skan      else
864169689Skan	{
865169689Skan	  XEXP (pattern, 1) = rtx_alloc (PARALLEL);
866169689Skan	  XVEC (XEXP (pattern, 1), 0) = XVEC (split, 0);
867169689Skan	  XVEC (split, 0) = rtvec_alloc (1);
868169689Skan	  XVECEXP (split, 0, 0) = pattern;
869169689Skan	}
870169689Skan      /* Predicate all of the insns generated by the split.  */
871169689Skan      for (i = 0; i < XVECLEN (split, 2); i++)
872169689Skan	{
873169689Skan	  pattern = rtx_alloc (COND_EXEC);
874169689Skan	  XEXP (pattern, 0) = pred;
875169689Skan	  XEXP (pattern, 1) = XVECEXP (split, 2, i);
876169689Skan	  XVECEXP (split, 2, i) = pattern;
877169689Skan	}
878169689Skan      /* Add the new split to the queue.  */
879169689Skan      queue_pattern (split, &other_tail, read_rtx_filename,
880169689Skan		     insn_elem->split->lineno);
88190075Sobrien    }
88290075Sobrien}
88390075Sobrien
88490075Sobrien/* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
88590075Sobrien   patterns appropriately.  */
88690075Sobrien
88790075Sobrienstatic void
888132718Skanprocess_define_cond_exec (void)
88990075Sobrien{
89090075Sobrien  struct queue_elem *elem;
89190075Sobrien
89290075Sobrien  identify_predicable_attribute ();
89390075Sobrien  if (errors)
89490075Sobrien    return;
89590075Sobrien
89690075Sobrien  for (elem = define_cond_exec_queue; elem ; elem = elem->next)
89790075Sobrien    process_one_cond_exec (elem);
89890075Sobrien}
89990075Sobrien
90090075Sobrienstatic char *
901132718Skansave_string (const char *s, int len)
90290075Sobrien{
903169689Skan  char *result = XNEWVEC (char, len + 1);
90490075Sobrien
90590075Sobrien  memcpy (result, s, len);
90690075Sobrien  result[len] = 0;
90790075Sobrien  return result;
90890075Sobrien}
90990075Sobrien
91090075Sobrien
91190075Sobrien/* The entry point for initializing the reader.  */
91290075Sobrien
91390075Sobrienint
914169689Skaninit_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *))
91590075Sobrien{
916169689Skan  FILE *input_file;
917169689Skan  int c, i, lineno;
918169689Skan  char *lastsl;
919169689Skan  rtx desc;
920169689Skan  bool no_more_options;
921169689Skan  bool already_read_stdin;
92290075Sobrien
923169689Skan  /* Unlock the stdio streams.  */
924169689Skan  unlock_std_streams ();
925169689Skan
926169689Skan  /* First we loop over all the options.  */
92790075Sobrien  for (i = 1; i < argc; i++)
92890075Sobrien    {
92990075Sobrien      if (argv[i][0] != '-')
930169689Skan	continue;
931169689Skan
932169689Skan      c = argv[i][1];
933169689Skan      switch (c)
93490075Sobrien	{
935169689Skan	case 'I':		/* Add directory to path for includes.  */
936169689Skan	  {
937169689Skan	    struct file_name_list *dirtmp;
93890075Sobrien
939169689Skan	    dirtmp = XNEW (struct file_name_list);
940169689Skan	    dirtmp->next = 0;	/* New one goes on the end */
941169689Skan	    if (first_dir_md_include == 0)
942169689Skan	      first_dir_md_include = dirtmp;
943169689Skan	    else
944169689Skan	      last_dir_md_include->next = dirtmp;
945169689Skan	    last_dir_md_include = dirtmp;	/* Tail follows the last one */
946169689Skan	    if (argv[i][1] == 'I' && argv[i][2] != 0)
947169689Skan	      dirtmp->fname = argv[i] + 2;
948169689Skan	    else if (i + 1 == argc)
949169689Skan	      fatal ("directory name missing after -I option");
950169689Skan	    else
951169689Skan	      dirtmp->fname = argv[++i];
952169689Skan	    if (strlen (dirtmp->fname) > max_include_len)
953169689Skan	      max_include_len = strlen (dirtmp->fname);
954169689Skan	  }
955169689Skan	  break;
95690075Sobrien
957169689Skan	case '\0':
958169689Skan	  /* An argument consisting of exactly one dash is a request to
959169689Skan	     read stdin.  This will be handled in the second loop.  */
960169689Skan	  continue;
96190075Sobrien
962169689Skan	case '-':
963169689Skan	  /* An argument consisting of just two dashes causes option
964169689Skan	     parsing to cease.  */
965169689Skan	  if (argv[i][2] == '\0')
966169689Skan	    goto stop_parsing_options;
96790075Sobrien
968169689Skan	default:
969169689Skan	  /* The program may have provided a callback so it can
970169689Skan	     accept its own options.  */
971169689Skan	  if (parse_opt && parse_opt (argv[i]))
972169689Skan	    break;
97390075Sobrien
974169689Skan	  fatal ("invalid option `%s'", argv[i]);
975169689Skan	}
97690075Sobrien    }
97790075Sobrien
978169689Skan stop_parsing_options:
979117395Skan
980169689Skan  /* Prepare to read input.  */
981169689Skan  condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
982169689Skan  init_predicate_table ();
98390075Sobrien  obstack_init (rtl_obstack);
98490075Sobrien  errors = 0;
98590075Sobrien  sequence_num = 0;
986169689Skan  no_more_options = false;
987169689Skan  already_read_stdin = false;
98890075Sobrien
989169689Skan
990169689Skan  /* Now loop over all input files.  */
991169689Skan  for (i = 1; i < argc; i++)
99290075Sobrien    {
993169689Skan      if (argv[i][0] == '-')
994169689Skan	{
995169689Skan	  if (argv[i][1] == '\0')
996169689Skan	    {
997169689Skan	      /* Read stdin.  */
998169689Skan	      if (already_read_stdin)
999169689Skan		fatal ("cannot read standard input twice");
1000169689Skan
1001169689Skan	      base_dir = NULL;
1002169689Skan	      read_rtx_filename = in_fname = "<stdin>";
1003169689Skan	      read_rtx_lineno = 1;
1004169689Skan	      input_file = stdin;
1005169689Skan	      already_read_stdin = true;
100690075Sobrien
1007169689Skan	      while (read_rtx (input_file, &desc, &lineno))
1008169689Skan		process_rtx (desc, lineno);
1009169689Skan	      fclose (input_file);
1010169689Skan	      continue;
1011169689Skan	    }
1012169689Skan	  else if (argv[i][1] == '-' && argv[i][2] == '\0')
1013169689Skan	    {
1014169689Skan	      /* No further arguments are to be treated as options.  */
1015169689Skan	      no_more_options = true;
1016169689Skan	      continue;
1017169689Skan	    }
1018169689Skan	  else if (!no_more_options)
1019169689Skan	    continue;
1020169689Skan	}
102190075Sobrien
1022169689Skan      /* If we get here we are looking at a non-option argument, i.e.
1023169689Skan	 a file to be processed.  */
1024169689Skan
1025169689Skan      in_fname = argv[i];
1026169689Skan      lastsl = strrchr (in_fname, '/');
1027169689Skan      if (lastsl != NULL)
1028169689Skan	base_dir = save_string (in_fname, lastsl - in_fname + 1 );
1029169689Skan      else
1030169689Skan	base_dir = NULL;
1031169689Skan
1032169689Skan      read_rtx_filename = in_fname;
1033169689Skan      read_rtx_lineno = 1;
1034169689Skan      input_file = fopen (in_fname, "r");
1035169689Skan      if (input_file == 0)
1036169689Skan	{
1037169689Skan	  perror (in_fname);
1038169689Skan	  return FATAL_EXIT_CODE;
1039169689Skan	}
1040169689Skan
1041169689Skan      while (read_rtx (input_file, &desc, &lineno))
1042169689Skan	process_rtx (desc, lineno);
1043169689Skan      fclose (input_file);
104490075Sobrien    }
104590075Sobrien
1046169689Skan  /* If we get to this point without having seen any files to process,
1047169689Skan     read standard input now.  */
1048169689Skan  if (!in_fname)
1049169689Skan    {
1050169689Skan      base_dir = NULL;
1051169689Skan      read_rtx_filename = in_fname = "<stdin>";
1052169689Skan      read_rtx_lineno = 1;
1053169689Skan      input_file = stdin;
1054169689Skan
1055169689Skan      while (read_rtx (input_file, &desc, &lineno))
1056169689Skan	process_rtx (desc, lineno);
1057169689Skan      fclose (input_file);
1058169689Skan    }
1059169689Skan
106090075Sobrien  /* Process define_cond_exec patterns.  */
106190075Sobrien  if (define_cond_exec_queue != NULL)
106290075Sobrien    process_define_cond_exec ();
106390075Sobrien
106490075Sobrien  return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
106590075Sobrien}
106690075Sobrien
1067169689Skan/* Programs that don't have their own options can use this entry point
1068169689Skan   instead.  */
1069169689Skanint
1070169689Skaninit_md_reader_args (int argc, char **argv)
1071169689Skan{
1072169689Skan  return init_md_reader_args_cb (argc, argv, 0);
1073169689Skan}
1074169689Skan
107590075Sobrien/* The entry point for reading a single rtx from an md file.  */
107690075Sobrien
107790075Sobrienrtx
1078132718Skanread_md_rtx (int *lineno, int *seqnr)
107990075Sobrien{
108090075Sobrien  struct queue_elem **queue, *elem;
108190075Sobrien  rtx desc;
108290075Sobrien
1083117395Skan discard:
1084117395Skan
108590075Sobrien  /* Read all patterns from a given queue before moving on to the next.  */
108690075Sobrien  if (define_attr_queue != NULL)
108790075Sobrien    queue = &define_attr_queue;
1088169689Skan  else if (define_pred_queue != NULL)
1089169689Skan    queue = &define_pred_queue;
109090075Sobrien  else if (define_insn_queue != NULL)
109190075Sobrien    queue = &define_insn_queue;
109290075Sobrien  else if (other_queue != NULL)
109390075Sobrien    queue = &other_queue;
109490075Sobrien  else
109590075Sobrien    return NULL_RTX;
109690075Sobrien
109790075Sobrien  elem = *queue;
109890075Sobrien  *queue = elem->next;
109990075Sobrien  desc = elem->data;
1100117395Skan  read_rtx_filename = elem->filename;
110190075Sobrien  *lineno = elem->lineno;
110290075Sobrien  *seqnr = sequence_num;
110390075Sobrien
110490075Sobrien  free (elem);
110590075Sobrien
1106117395Skan  /* Discard insn patterns which we know can never match (because
1107117395Skan     their C test is provably always false).  If insn_elision is
1108117395Skan     false, our caller needs to see all the patterns.  Note that the
1109117395Skan     elided patterns are never counted by the sequence numbering; it
1110117395Skan     it is the caller's responsibility, when insn_elision is false, not
1111117395Skan     to use elided pattern numbers for anything.  */
111290075Sobrien  switch (GET_CODE (desc))
111390075Sobrien    {
111490075Sobrien    case DEFINE_INSN:
111590075Sobrien    case DEFINE_EXPAND:
1116117395Skan      if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
1117117395Skan	sequence_num++;
1118117395Skan      else if (insn_elision)
1119117395Skan	goto discard;
1120169689Skan
1121169689Skan      /* *seqnr is used here so the name table will match caller's
1122169689Skan	 idea of insn numbering, whether or not elision is active.  */
1123169689Skan      record_insn_name (*seqnr, XSTR (desc, 0));
1124117395Skan      break;
1125117395Skan
112690075Sobrien    case DEFINE_SPLIT:
112790075Sobrien    case DEFINE_PEEPHOLE:
112890075Sobrien    case DEFINE_PEEPHOLE2:
1129117395Skan      if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
1130117395Skan	sequence_num++;
1131117395Skan      else if (insn_elision)
1132117395Skan	    goto discard;
113390075Sobrien      break;
113490075Sobrien
113590075Sobrien    default:
113690075Sobrien      break;
113790075Sobrien    }
113890075Sobrien
113990075Sobrien  return desc;
114090075Sobrien}
1141117395Skan
1142117395Skan/* Helper functions for insn elision.  */
1143117395Skan
1144117395Skan/* Compute a hash function of a c_test structure, which is keyed
1145117395Skan   by its ->expr field.  */
1146117395Skanhashval_t
1147132718Skanhash_c_test (const void *x)
1148117395Skan{
1149117395Skan  const struct c_test *a = (const struct c_test *) x;
1150117395Skan  const unsigned char *base, *s = (const unsigned char *) a->expr;
1151117395Skan  hashval_t hash;
1152117395Skan  unsigned char c;
1153117395Skan  unsigned int len;
1154117395Skan
1155117395Skan  base = s;
1156117395Skan  hash = 0;
1157117395Skan
1158117395Skan  while ((c = *s++) != '\0')
1159117395Skan    {
1160117395Skan      hash += c + (c << 17);
1161117395Skan      hash ^= hash >> 2;
1162117395Skan    }
1163117395Skan
1164117395Skan  len = s - base;
1165117395Skan  hash += len + (len << 17);
1166117395Skan  hash ^= hash >> 2;
1167117395Skan
1168117395Skan  return hash;
1169117395Skan}
1170117395Skan
1171117395Skan/* Compare two c_test expression structures.  */
1172117395Skanint
1173132718Skancmp_c_test (const void *x, const void *y)
1174117395Skan{
1175117395Skan  const struct c_test *a = (const struct c_test *) x;
1176117395Skan  const struct c_test *b = (const struct c_test *) y;
1177117395Skan
1178117395Skan  return !strcmp (a->expr, b->expr);
1179117395Skan}
1180117395Skan
1181117395Skan/* Given a string representing a C test expression, look it up in the
1182117395Skan   condition_table and report whether or not its value is known
1183117395Skan   at compile time.  Returns a tristate: 1 for known true, 0 for
1184117395Skan   known false, -1 for unknown.  */
1185117395Skanint
1186132718Skanmaybe_eval_c_test (const char *expr)
1187117395Skan{
1188117395Skan  const struct c_test *test;
1189117395Skan  struct c_test dummy;
1190117395Skan
1191117395Skan  if (expr[0] == 0)
1192117395Skan    return 1;
1193117395Skan
1194117395Skan  dummy.expr = expr;
1195169689Skan  test = (const struct c_test *)htab_find (condition_table, &dummy);
1196117395Skan  if (!test)
1197169689Skan    return -1;
1198117395Skan  return test->value;
1199117395Skan}
1200117395Skan
1201169689Skan/* Record the C test expression EXPR in the condition_table, with
1202169689Skan   value VAL.  Duplicates clobber previous entries.  */
1203169689Skan
1204169689Skanvoid
1205169689Skanadd_c_test (const char *expr, int value)
1206169689Skan{
1207169689Skan  struct c_test *test;
1208169689Skan
1209169689Skan  if (expr[0] == 0)
1210169689Skan    return;
1211169689Skan
1212169689Skan  test = XNEW (struct c_test);
1213169689Skan  test->expr = expr;
1214169689Skan  test->value = value;
1215169689Skan
1216169689Skan  *(htab_find_slot (condition_table, test, INSERT)) = test;
1217169689Skan}
1218169689Skan
1219169689Skan/* For every C test, call CALLBACK with two arguments: a pointer to
1220169689Skan   the condition structure and INFO.  Stops when CALLBACK returns zero.  */
1221169689Skanvoid
1222169689Skantraverse_c_tests (htab_trav callback, void *info)
1223169689Skan{
1224169689Skan  if (condition_table)
1225169689Skan    htab_traverse (condition_table, callback, info);
1226169689Skan}
1227169689Skan
1228169689Skan
1229117395Skan/* Given a string, return the number of comma-separated elements in it.
1230117395Skan   Return 0 for the null string.  */
1231117395Skanint
1232132718Skann_comma_elts (const char *s)
1233117395Skan{
1234117395Skan  int n;
1235117395Skan
1236117395Skan  if (*s == '\0')
1237117395Skan    return 0;
1238117395Skan
1239117395Skan  for (n = 1; *s; s++)
1240117395Skan    if (*s == ',')
1241117395Skan      n++;
1242117395Skan
1243117395Skan  return n;
1244117395Skan}
1245117395Skan
1246117395Skan/* Given a pointer to a (char *), return a pointer to the beginning of the
1247117395Skan   next comma-separated element in the string.  Advance the pointer given
1248117395Skan   to the end of that element.  Return NULL if at end of string.  Caller
1249117395Skan   is responsible for copying the string if necessary.  White space between
1250117395Skan   a comma and an element is ignored.  */
1251117395Skan
1252117395Skanconst char *
1253132718Skanscan_comma_elt (const char **pstr)
1254117395Skan{
1255117395Skan  const char *start;
1256117395Skan  const char *p = *pstr;
1257117395Skan
1258117395Skan  if (*p == ',')
1259117395Skan    p++;
1260117395Skan  while (ISSPACE(*p))
1261117395Skan    p++;
1262117395Skan
1263117395Skan  if (*p == '\0')
1264117395Skan    return NULL;
1265117395Skan
1266117395Skan  start = p;
1267117395Skan
1268117395Skan  while (*p != ',' && *p != '\0')
1269117395Skan    p++;
1270117395Skan
1271117395Skan  *pstr = p;
1272117395Skan  return start;
1273117395Skan}
1274169689Skan
1275169689Skan/* Helper functions for define_predicate and define_special_predicate
1276169689Skan   processing.  Shared between genrecog.c and genpreds.c.  */
1277169689Skan
1278169689Skanstatic htab_t predicate_table;
1279169689Skanstruct pred_data *first_predicate;
1280169689Skanstatic struct pred_data **last_predicate = &first_predicate;
1281169689Skan
1282169689Skanstatic hashval_t
1283169689Skanhash_struct_pred_data (const void *ptr)
1284169689Skan{
1285169689Skan  return htab_hash_string (((const struct pred_data *)ptr)->name);
1286169689Skan}
1287169689Skan
1288169689Skanstatic int
1289169689Skaneq_struct_pred_data (const void *a, const void *b)
1290169689Skan{
1291169689Skan  return !strcmp (((const struct pred_data *)a)->name,
1292169689Skan		  ((const struct pred_data *)b)->name);
1293169689Skan}
1294169689Skan
1295169689Skanstruct pred_data *
1296169689Skanlookup_predicate (const char *name)
1297169689Skan{
1298169689Skan  struct pred_data key;
1299169689Skan  key.name = name;
1300169689Skan  return (struct pred_data *) htab_find (predicate_table, &key);
1301169689Skan}
1302169689Skan
1303169689Skanvoid
1304169689Skanadd_predicate (struct pred_data *pred)
1305169689Skan{
1306169689Skan  void **slot = htab_find_slot (predicate_table, pred, INSERT);
1307169689Skan  if (*slot)
1308169689Skan    {
1309169689Skan      error ("duplicate predicate definition for '%s'", pred->name);
1310169689Skan      return;
1311169689Skan    }
1312169689Skan  *slot = pred;
1313169689Skan  *last_predicate = pred;
1314169689Skan  last_predicate = &pred->next;
1315169689Skan}
1316169689Skan
1317169689Skan/* This array gives the initial content of the predicate table.  It
1318169689Skan   has entries for all predicates defined in recog.c.  */
1319169689Skan
1320169689Skanstruct std_pred_table
1321169689Skan{
1322169689Skan  const char *name;
1323169689Skan  bool special;
1324169689Skan  RTX_CODE codes[NUM_RTX_CODE];
1325169689Skan};
1326169689Skan
1327169689Skanstatic const struct std_pred_table std_preds[] = {
1328169689Skan  {"general_operand", false, {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1329169689Skan			      LABEL_REF, SUBREG, REG, MEM }},
1330169689Skan  {"address_operand", true, {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1331169689Skan			     LABEL_REF, SUBREG, REG, MEM,
1332169689Skan			     PLUS, MINUS, MULT}},
1333169689Skan  {"register_operand", false, {SUBREG, REG}},
1334169689Skan  {"pmode_register_operand", true, {SUBREG, REG}},
1335169689Skan  {"scratch_operand", false, {SCRATCH, REG}},
1336169689Skan  {"immediate_operand", false, {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1337169689Skan				LABEL_REF}},
1338169689Skan  {"const_int_operand", false, {CONST_INT}},
1339169689Skan  {"const_double_operand", false, {CONST_INT, CONST_DOUBLE}},
1340169689Skan  {"nonimmediate_operand", false, {SUBREG, REG, MEM}},
1341169689Skan  {"nonmemory_operand", false, {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1342169689Skan			        LABEL_REF, SUBREG, REG}},
1343169689Skan  {"push_operand", false, {MEM}},
1344169689Skan  {"pop_operand", false, {MEM}},
1345169689Skan  {"memory_operand", false, {SUBREG, MEM}},
1346169689Skan  {"indirect_operand", false, {SUBREG, MEM}},
1347169689Skan  {"comparison_operator", false, {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU,
1348169689Skan				  UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
1349169689Skan				  UNLT, LTGT}}
1350169689Skan};
1351169689Skan#define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
1352169689Skan
1353169689Skan/* Initialize the table of predicate definitions, starting with
1354169689Skan   the information we have on generic predicates.  */
1355169689Skan
1356169689Skanstatic void
1357169689Skaninit_predicate_table (void)
1358169689Skan{
1359169689Skan  size_t i, j;
1360169689Skan  struct pred_data *pred;
1361169689Skan
1362169689Skan  predicate_table = htab_create_alloc (37, hash_struct_pred_data,
1363169689Skan				       eq_struct_pred_data, 0,
1364169689Skan				       xcalloc, free);
1365169689Skan
1366169689Skan  for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
1367169689Skan    {
1368169689Skan      pred = XCNEW (struct pred_data);
1369169689Skan      pred->name = std_preds[i].name;
1370169689Skan      pred->special = std_preds[i].special;
1371169689Skan
1372169689Skan      for (j = 0; std_preds[i].codes[j] != 0; j++)
1373169689Skan	{
1374169689Skan	  enum rtx_code code = std_preds[i].codes[j];
1375169689Skan
1376169689Skan	  pred->codes[code] = true;
1377169689Skan	  if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
1378169689Skan	    pred->allows_non_const = true;
1379169689Skan	  if (code != REG
1380169689Skan	      && code != SUBREG
1381169689Skan	      && code != MEM
1382169689Skan	      && code != CONCAT
1383169689Skan	      && code != PARALLEL
1384169689Skan	      && code != STRICT_LOW_PART)
1385169689Skan	    pred->allows_non_lvalue = true;
1386169689Skan	}
1387169689Skan      if (j == 1)
1388169689Skan	pred->singleton = std_preds[i].codes[0];
1389169689Skan
1390169689Skan      add_predicate (pred);
1391169689Skan    }
1392169689Skan}
1393169689Skan
1394169689Skan/* These functions allow linkage with print-rtl.c.  Also, some generators
1395169689Skan   like to annotate their output with insn names.  */
1396169689Skan
1397169689Skan/* Holds an array of names indexed by insn_code_number.  */
1398169689Skanstatic char **insn_name_ptr = 0;
1399169689Skanstatic int insn_name_ptr_size = 0;
1400169689Skan
1401169689Skanconst char *
1402169689Skanget_insn_name (int code)
1403169689Skan{
1404169689Skan  if (code < insn_name_ptr_size)
1405169689Skan    return insn_name_ptr[code];
1406169689Skan  else
1407169689Skan    return NULL;
1408169689Skan}
1409169689Skan
1410169689Skanstatic void
1411169689Skanrecord_insn_name (int code, const char *name)
1412169689Skan{
1413169689Skan  static const char *last_real_name = "insn";
1414169689Skan  static int last_real_code = 0;
1415169689Skan  char *new;
1416169689Skan
1417169689Skan  if (insn_name_ptr_size <= code)
1418169689Skan    {
1419169689Skan      int new_size;
1420169689Skan      new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
1421169689Skan      insn_name_ptr = xrealloc (insn_name_ptr, sizeof(char *) * new_size);
1422169689Skan      memset (insn_name_ptr + insn_name_ptr_size, 0,
1423169689Skan	      sizeof(char *) * (new_size - insn_name_ptr_size));
1424169689Skan      insn_name_ptr_size = new_size;
1425169689Skan    }
1426169689Skan
1427169689Skan  if (!name || name[0] == '\0')
1428169689Skan    {
1429169689Skan      new = xmalloc (strlen (last_real_name) + 10);
1430169689Skan      sprintf (new, "%s+%d", last_real_name, code - last_real_code);
1431169689Skan    }
1432169689Skan  else
1433169689Skan    {
1434169689Skan      last_real_name = new = xstrdup (name);
1435169689Skan      last_real_code = code;
1436169689Skan    }
1437169689Skan
1438169689Skan  insn_name_ptr[code] = new;
1439169689Skan}
1440