1/* Generate code from machine description to emit insns as rtl.
2   Copyright (C) 1987-2015 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3.  If not see
18<http://www.gnu.org/licenses/>.  */
19
20
21#include "bconfig.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "rtl.h"
26#include "errors.h"
27#include "read-md.h"
28#include "gensupport.h"
29
30
31static int insn_code_number;
32static int insn_index_number;
33
34/* Data structure for recording the patterns of insns that have CLOBBERs.
35   We use this to output a function that adds these CLOBBERs to a
36   previously-allocated PARALLEL expression.  */
37
38struct clobber_pat
39{
40  struct clobber_ent *insns;
41  rtx pattern;
42  int first_clobber;
43  struct clobber_pat *next;
44  int has_hard_reg;
45} *clobber_list;
46
47/* Records one insn that uses the clobber list.  */
48
49struct clobber_ent
50{
51  int code_number;		/* Counts only insns.  */
52  struct clobber_ent *next;
53};
54
55static void print_code			(RTX_CODE);
56static void gen_exp			(rtx, enum rtx_code, char *);
57static void gen_insn			(rtx, int);
58static void gen_expand			(rtx);
59static void gen_split			(rtx);
60static void output_add_clobbers		(void);
61static void output_added_clobbers_hard_reg_p (void);
62static void gen_rtx_scratch		(rtx, enum rtx_code);
63static void output_peephole2_scratches	(rtx);
64
65
66static void
67print_code (RTX_CODE code)
68{
69  const char *p1;
70  for (p1 = GET_RTX_NAME (code); *p1; p1++)
71    putchar (TOUPPER (*p1));
72}
73
74static void
75gen_rtx_scratch (rtx x, enum rtx_code subroutine_type)
76{
77  if (subroutine_type == DEFINE_PEEPHOLE2)
78    {
79      printf ("operand%d", XINT (x, 0));
80    }
81  else
82    {
83      printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
84    }
85}
86
87/* Print a C expression to construct an RTX just like X,
88   substituting any operand references appearing within.  */
89
90static void
91gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
92{
93  RTX_CODE code;
94  int i;
95  int len;
96  const char *fmt;
97
98  if (x == 0)
99    {
100      printf ("NULL_RTX");
101      return;
102    }
103
104  code = GET_CODE (x);
105
106  switch (code)
107    {
108    case MATCH_OPERAND:
109    case MATCH_DUP:
110      if (used)
111	{
112	  if (used[XINT (x, 0)])
113	    {
114	      printf ("copy_rtx (operand%d)", XINT (x, 0));
115	      return;
116	    }
117	  used[XINT (x, 0)] = 1;
118	}
119      printf ("operand%d", XINT (x, 0));
120      return;
121
122    case MATCH_OP_DUP:
123      printf ("gen_rtx_fmt_");
124      for (i = 0; i < XVECLEN (x, 1); i++)
125	printf ("e");
126      printf (" (GET_CODE (operand%d), ", XINT (x, 0));
127      if (GET_MODE (x) == VOIDmode)
128	printf ("GET_MODE (operand%d)", XINT (x, 0));
129      else
130	printf ("%smode", GET_MODE_NAME (GET_MODE (x)));
131      for (i = 0; i < XVECLEN (x, 1); i++)
132	{
133	  printf (",\n\t\t");
134	  gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
135	}
136      printf (")");
137      return;
138
139    case MATCH_OPERATOR:
140      printf ("gen_rtx_fmt_");
141      for (i = 0; i < XVECLEN (x, 2); i++)
142	printf ("e");
143      printf (" (GET_CODE (operand%d)", XINT (x, 0));
144      printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
145      for (i = 0; i < XVECLEN (x, 2); i++)
146	{
147	  printf (",\n\t\t");
148	  gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
149	}
150      printf (")");
151      return;
152
153    case MATCH_PARALLEL:
154    case MATCH_PAR_DUP:
155      printf ("operand%d", XINT (x, 0));
156      return;
157
158    case MATCH_SCRATCH:
159      gen_rtx_scratch (x, subroutine_type);
160      return;
161
162    case PC:
163      printf ("pc_rtx");
164      return;
165    case RETURN:
166      printf ("ret_rtx");
167      return;
168    case SIMPLE_RETURN:
169      printf ("simple_return_rtx");
170      return;
171    case CLOBBER:
172      if (REG_P (XEXP (x, 0)))
173	{
174	  printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
175			  			     REGNO (XEXP (x, 0)));
176	  return;
177	}
178      break;
179
180    case CC0:
181      printf ("cc0_rtx");
182      return;
183
184    case CONST_INT:
185      if (INTVAL (x) == 0)
186	printf ("const0_rtx");
187      else if (INTVAL (x) == 1)
188	printf ("const1_rtx");
189      else if (INTVAL (x) == -1)
190	printf ("constm1_rtx");
191      else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
192	  && INTVAL (x) <= MAX_SAVED_CONST_INT)
193	printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
194		(int) INTVAL (x));
195      else if (INTVAL (x) == STORE_FLAG_VALUE)
196	printf ("const_true_rtx");
197      else
198	{
199	  printf ("GEN_INT (");
200	  printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
201	  printf (")");
202	}
203      return;
204
205    case CONST_DOUBLE:
206    case CONST_FIXED:
207    case CONST_WIDE_INT:
208      /* These shouldn't be written in MD files.  Instead, the appropriate
209	 routines in varasm.c should be called.  */
210      gcc_unreachable ();
211
212    default:
213      break;
214    }
215
216  printf ("gen_rtx_");
217  print_code (code);
218  printf (" (%smode", GET_MODE_NAME (GET_MODE (x)));
219
220  fmt = GET_RTX_FORMAT (code);
221  len = GET_RTX_LENGTH (code);
222  for (i = 0; i < len; i++)
223    {
224      if (fmt[i] == '0')
225	break;
226      printf (",\n\t");
227      switch (fmt[i])
228	{
229	case 'e': case 'u':
230	  gen_exp (XEXP (x, i), subroutine_type, used);
231	  break;
232
233	case 'i':
234	  printf ("%u", XINT (x, i));
235	  break;
236
237	case 's':
238	  printf ("\"%s\"", XSTR (x, i));
239	  break;
240
241	case 'E':
242	  {
243	    int j;
244	    printf ("gen_rtvec (%d", XVECLEN (x, i));
245	    for (j = 0; j < XVECLEN (x, i); j++)
246	      {
247		printf (",\n\t\t");
248		gen_exp (XVECEXP (x, i, j), subroutine_type, used);
249	      }
250	    printf (")");
251	    break;
252	  }
253
254	default:
255	  gcc_unreachable ();
256	}
257    }
258  printf (")");
259}
260
261/* Generate the `gen_...' function for a DEFINE_INSN.  */
262
263static void
264gen_insn (rtx insn, int lineno)
265{
266  struct pattern_stats stats;
267  int i;
268
269  /* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
270     registers or MATCH_SCRATCHes.  If so, store away the information for
271     later.  */
272
273  if (XVEC (insn, 1))
274    {
275      int has_hard_reg = 0;
276
277      for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
278	{
279	  if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
280	    break;
281
282	  if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
283	    has_hard_reg = 1;
284	  else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
285	    break;
286	}
287
288      if (i != XVECLEN (insn, 1) - 1)
289	{
290	  struct clobber_pat *p;
291	  struct clobber_ent *link = XNEW (struct clobber_ent);
292	  int j;
293
294	  link->code_number = insn_code_number;
295
296	  /* See if any previous CLOBBER_LIST entry is the same as this
297	     one.  */
298
299	  for (p = clobber_list; p; p = p->next)
300	    {
301	      if (p->first_clobber != i + 1
302		  || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
303		continue;
304
305	      for (j = i + 1; j < XVECLEN (insn, 1); j++)
306		{
307		  rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0);
308		  rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0);
309
310		  /* OLD and NEW_INSN are the same if both are to be a SCRATCH
311		     of the same mode,
312		     or if both are registers of the same mode and number.  */
313		  if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
314			 && ((GET_CODE (old_rtx) == MATCH_SCRATCH
315			      && GET_CODE (new_rtx) == MATCH_SCRATCH)
316			     || (REG_P (old_rtx) && REG_P (new_rtx)
317				 && REGNO (old_rtx) == REGNO (new_rtx)))))
318		    break;
319		}
320
321	      if (j == XVECLEN (insn, 1))
322		break;
323	    }
324
325	  if (p == 0)
326	    {
327	      p = XNEW (struct clobber_pat);
328
329	      p->insns = 0;
330	      p->pattern = insn;
331	      p->first_clobber = i + 1;
332	      p->next = clobber_list;
333	      p->has_hard_reg = has_hard_reg;
334	      clobber_list = p;
335	    }
336
337	  link->next = p->insns;
338	  p->insns = link;
339	}
340    }
341
342  /* Don't mention instructions whose names are the null string
343     or begin with '*'.  They are in the machine description just
344     to be recognized.  */
345  if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
346    return;
347
348  printf ("/* %s:%d */\n", read_md_filename, lineno);
349
350  /* Find out how many operands this function has.  */
351  get_pattern_stats (&stats, XVEC (insn, 1));
352  if (stats.max_dup_opno > stats.max_opno)
353    fatal ("match_dup operand number has no match_operand");
354
355  /* Output the function name and argument declarations.  */
356  printf ("rtx\ngen_%s (", XSTR (insn, 0));
357  if (stats.num_generator_args)
358    for (i = 0; i < stats.num_generator_args; i++)
359      if (i)
360	printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
361      else
362	printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
363  else
364    printf ("void");
365  printf (")\n");
366  printf ("{\n");
367
368  /* Output code to construct and return the rtl for the instruction body.  */
369
370  if (XVECLEN (insn, 1) == 1)
371    {
372      printf ("  return ");
373      gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL);
374      printf (";\n}\n\n");
375    }
376  else
377    {
378      char *used = XCNEWVEC (char, stats.num_generator_args);
379
380      printf ("  return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
381	      XVECLEN (insn, 1));
382
383      for (i = 0; i < XVECLEN (insn, 1); i++)
384	{
385	  printf (",\n\t\t");
386	  gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used);
387	}
388      printf ("));\n}\n\n");
389      XDELETEVEC (used);
390    }
391}
392
393/* Generate the `gen_...' function for a DEFINE_EXPAND.  */
394
395static void
396gen_expand (rtx expand)
397{
398  struct pattern_stats stats;
399  int i;
400  char *used;
401
402  if (strlen (XSTR (expand, 0)) == 0)
403    fatal ("define_expand lacks a name");
404  if (XVEC (expand, 1) == 0)
405    fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
406
407  /* Find out how many operands this function has.  */
408  get_pattern_stats (&stats, XVEC (expand, 1));
409
410  /* Output the function name and argument declarations.  */
411  printf ("rtx\ngen_%s (", XSTR (expand, 0));
412  if (stats.num_generator_args)
413    for (i = 0; i < stats.num_generator_args; i++)
414      if (i)
415	printf (",\n\trtx operand%d", i);
416      else
417	printf ("rtx operand%d", i);
418  else
419    printf ("void");
420  printf (")\n");
421  printf ("{\n");
422
423  /* If we don't have any C code to write, only one insn is being written,
424     and no MATCH_DUPs are present, we can just return the desired insn
425     like we do for a DEFINE_INSN.  This saves memory.  */
426  if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
427      && stats.max_opno >= stats.max_dup_opno
428      && XVECLEN (expand, 1) == 1)
429    {
430      printf ("  return ");
431      gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
432      printf (";\n}\n\n");
433      return;
434    }
435
436  /* For each operand referred to only with MATCH_DUPs,
437     make a local variable.  */
438  for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
439    printf ("  rtx operand%d;\n", i);
440  for (; i <= stats.max_scratch_opno; i++)
441    printf ("  rtx operand%d ATTRIBUTE_UNUSED;\n", i);
442  printf ("  rtx _val = 0;\n");
443  printf ("  start_sequence ();\n");
444
445  /* The fourth operand of DEFINE_EXPAND is some code to be executed
446     before the actual construction.
447     This code expects to refer to `operands'
448     just as the output-code in a DEFINE_INSN does,
449     but here `operands' is an automatic array.
450     So copy the operand values there before executing it.  */
451  if (XSTR (expand, 3) && *XSTR (expand, 3))
452    {
453      printf ("  {\n");
454      if (stats.num_operand_vars > 0)
455	printf ("    rtx operands[%d];\n", stats.num_operand_vars);
456
457      /* Output code to copy the arguments into `operands'.  */
458      for (i = 0; i < stats.num_generator_args; i++)
459	printf ("    operands[%d] = operand%d;\n", i, i);
460
461      /* Output the special code to be executed before the sequence
462	 is generated.  */
463      print_md_ptr_loc (XSTR (expand, 3));
464      printf ("%s\n", XSTR (expand, 3));
465
466      /* Output code to copy the arguments back out of `operands'
467	 (unless we aren't going to use them at all).  */
468      if (XVEC (expand, 1) != 0)
469	{
470	  for (i = 0; i < stats.num_operand_vars; i++)
471	    {
472	      printf ("    operand%d = operands[%d];\n", i, i);
473	      printf ("    (void) operand%d;\n", i);
474	    }
475	}
476      printf ("  }\n");
477    }
478
479  /* Output code to construct the rtl for the instruction bodies.
480     Use emit_insn to add them to the sequence being accumulated.
481     But don't do this if the user's code has set `no_more' nonzero.  */
482
483  used = XCNEWVEC (char, stats.num_operand_vars);
484
485  for (i = 0; i < XVECLEN (expand, 1); i++)
486    {
487      rtx next = XVECEXP (expand, 1, i);
488      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
489	  || (GET_CODE (next) == PARALLEL
490	      && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
491		   && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
492		  || ANY_RETURN_P (XVECEXP (next, 0, 0))))
493	  || ANY_RETURN_P (next))
494	printf ("  emit_jump_insn (");
495      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
496	       || GET_CODE (next) == CALL
497	       || (GET_CODE (next) == PARALLEL
498		   && GET_CODE (XVECEXP (next, 0, 0)) == SET
499		   && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
500	       || (GET_CODE (next) == PARALLEL
501		   && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
502	printf ("  emit_call_insn (");
503      else if (LABEL_P (next))
504	printf ("  emit_label (");
505      else if (GET_CODE (next) == MATCH_OPERAND
506	       || GET_CODE (next) == MATCH_DUP
507	       || GET_CODE (next) == MATCH_OPERATOR
508	       || GET_CODE (next) == MATCH_OP_DUP
509	       || GET_CODE (next) == MATCH_PARALLEL
510	       || GET_CODE (next) == MATCH_PAR_DUP
511	       || GET_CODE (next) == PARALLEL)
512	printf ("  emit (");
513      else
514	printf ("  emit_insn (");
515      gen_exp (next, DEFINE_EXPAND, used);
516      printf (");\n");
517      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
518	  && GET_CODE (SET_SRC (next)) == LABEL_REF)
519	printf ("  emit_barrier ();");
520    }
521
522  XDELETEVEC (used);
523
524  /* Call `get_insns' to extract the list of all the
525     insns emitted within this gen_... function.  */
526
527  printf ("  _val = get_insns ();\n");
528  printf ("  end_sequence ();\n");
529  printf ("  return _val;\n}\n\n");
530}
531
532/* Like gen_expand, but generates insns resulting from splitting SPLIT.  */
533
534static void
535gen_split (rtx split)
536{
537  struct pattern_stats stats;
538  int i;
539  const char *const name =
540    ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
541  const char *unused;
542  char *used;
543
544  if (XVEC (split, 0) == 0)
545    fatal ("define_%s (definition %d) lacks a pattern", name,
546	   insn_index_number);
547  else if (XVEC (split, 2) == 0)
548    fatal ("define_%s (definition %d) lacks a replacement pattern", name,
549	   insn_index_number);
550
551  /* Find out how many operands this function has.  */
552
553  get_pattern_stats (&stats, XVEC (split, 2));
554  unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : "");
555  used = XCNEWVEC (char, stats.num_operand_vars);
556
557  /* Output the prototype, function name and argument declarations.  */
558  if (GET_CODE (split) == DEFINE_PEEPHOLE2)
559    {
560      printf ("extern rtx gen_%s_%d (rtx_insn *, rtx *);\n",
561	      name, insn_code_number);
562      printf ("rtx\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
563	      name, insn_code_number, unused);
564    }
565  else
566    {
567      printf ("extern rtx gen_split_%d (rtx_insn *, rtx *);\n", insn_code_number);
568      printf ("rtx\ngen_split_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
569	      insn_code_number, unused);
570    }
571  printf ("{\n");
572
573  /* Declare all local variables.  */
574  for (i = 0; i < stats.num_operand_vars; i++)
575    printf ("  rtx operand%d;\n", i);
576  printf ("  rtx _val = 0;\n");
577
578  if (GET_CODE (split) == DEFINE_PEEPHOLE2)
579    output_peephole2_scratches (split);
580
581  printf ("  if (dump_file)\n");
582  printf ("    fprintf (dump_file, \"Splitting with gen_%s_%d\\n\");\n",
583	  name, insn_code_number);
584
585  printf ("  start_sequence ();\n");
586
587  /* The fourth operand of DEFINE_SPLIT is some code to be executed
588     before the actual construction.  */
589
590  if (XSTR (split, 3))
591    {
592      print_md_ptr_loc (XSTR (split, 3));
593      printf ("%s\n", XSTR (split, 3));
594    }
595
596  /* Output code to copy the arguments back out of `operands'  */
597  for (i = 0; i < stats.num_operand_vars; i++)
598    {
599      printf ("  operand%d = operands[%d];\n", i, i);
600      printf ("  (void) operand%d;\n", i);
601    }
602
603  /* Output code to construct the rtl for the instruction bodies.
604     Use emit_insn to add them to the sequence being accumulated.
605     But don't do this if the user's code has set `no_more' nonzero.  */
606
607  for (i = 0; i < XVECLEN (split, 2); i++)
608    {
609      rtx next = XVECEXP (split, 2, i);
610      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
611	  || (GET_CODE (next) == PARALLEL
612	      && GET_CODE (XVECEXP (next, 0, 0)) == SET
613	      && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
614	  || ANY_RETURN_P (next))
615	printf ("  emit_jump_insn (");
616      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
617	       || GET_CODE (next) == CALL
618	       || (GET_CODE (next) == PARALLEL
619		   && GET_CODE (XVECEXP (next, 0, 0)) == SET
620		   && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
621	       || (GET_CODE (next) == PARALLEL
622		   && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
623	printf ("  emit_call_insn (");
624      else if (LABEL_P (next))
625	printf ("  emit_label (");
626      else if (GET_CODE (next) == MATCH_OPERAND
627	       || GET_CODE (next) == MATCH_OPERATOR
628	       || GET_CODE (next) == MATCH_PARALLEL
629	       || GET_CODE (next) == MATCH_OP_DUP
630	       || GET_CODE (next) == MATCH_DUP
631	       || GET_CODE (next) == PARALLEL)
632	printf ("  emit (");
633      else
634	printf ("  emit_insn (");
635      gen_exp (next, GET_CODE (split), used);
636      printf (");\n");
637      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
638	  && GET_CODE (SET_SRC (next)) == LABEL_REF)
639	printf ("  emit_barrier ();");
640    }
641
642  /* Call `get_insns' to make a list of all the
643     insns emitted within this gen_... function.  */
644
645  printf ("  _val = get_insns ();\n");
646  printf ("  end_sequence ();\n");
647  printf ("  return _val;\n}\n\n");
648
649  free (used);
650}
651
652/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
653   size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
654   the end of the vector.  */
655
656static void
657output_add_clobbers (void)
658{
659  struct clobber_pat *clobber;
660  struct clobber_ent *ent;
661  int i;
662
663  printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n");
664  printf ("{\n");
665  printf ("  switch (insn_code_number)\n");
666  printf ("    {\n");
667
668  for (clobber = clobber_list; clobber; clobber = clobber->next)
669    {
670      for (ent = clobber->insns; ent; ent = ent->next)
671	printf ("    case %d:\n", ent->code_number);
672
673      for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
674	{
675	  printf ("      XVECEXP (pattern, 0, %d) = ", i);
676	  gen_exp (XVECEXP (clobber->pattern, 1, i),
677		   GET_CODE (clobber->pattern), NULL);
678	  printf (";\n");
679	}
680
681      printf ("      break;\n\n");
682    }
683
684  printf ("    default:\n");
685  printf ("      gcc_unreachable ();\n");
686  printf ("    }\n");
687  printf ("}\n");
688}
689
690/* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code
691   number that will have clobbers added (as indicated by `recog') and returns
692   1 if those include a clobber of a hard reg or 0 if all of them just clobber
693   SCRATCH.  */
694
695static void
696output_added_clobbers_hard_reg_p (void)
697{
698  struct clobber_pat *clobber;
699  struct clobber_ent *ent;
700  int clobber_p, used;
701
702  printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n");
703  printf ("{\n");
704  printf ("  switch (insn_code_number)\n");
705  printf ("    {\n");
706
707  for (clobber_p = 0; clobber_p <= 1; clobber_p++)
708    {
709      used = 0;
710      for (clobber = clobber_list; clobber; clobber = clobber->next)
711	if (clobber->has_hard_reg == clobber_p)
712	  for (ent = clobber->insns; ent; ent = ent->next)
713	    {
714	      printf ("    case %d:\n", ent->code_number);
715	      used++;
716	    }
717
718      if (used)
719	printf ("      return %d;\n\n", clobber_p);
720    }
721
722  printf ("    default:\n");
723  printf ("      gcc_unreachable ();\n");
724  printf ("    }\n");
725  printf ("}\n");
726}
727
728/* Generate code to invoke find_free_register () as needed for the
729   scratch registers used by the peephole2 pattern in SPLIT.  */
730
731static void
732output_peephole2_scratches (rtx split)
733{
734  int i;
735  int insn_nr = 0;
736  bool first = true;
737
738  for (i = 0; i < XVECLEN (split, 0); i++)
739    {
740      rtx elt = XVECEXP (split, 0, i);
741      if (GET_CODE (elt) == MATCH_SCRATCH)
742	{
743	  int last_insn_nr = insn_nr;
744	  int cur_insn_nr = insn_nr;
745	  int j;
746	  for (j = i + 1; j < XVECLEN (split, 0); j++)
747	    if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)
748	      {
749		if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))
750		  last_insn_nr = cur_insn_nr;
751	      }
752	    else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
753	      cur_insn_nr++;
754
755	  if (first)
756	    {
757	      printf ("  HARD_REG_SET _regs_allocated;\n");
758	      printf ("  CLEAR_HARD_REG_SET (_regs_allocated);\n");
759	      first = false;
760	    }
761
762	  printf ("  if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
763    return NULL;\n",
764		  XINT (elt, 0),
765		  insn_nr, last_insn_nr,
766		  XSTR (elt, 1),
767		  GET_MODE_NAME (GET_MODE (elt)));
768
769	}
770      else if (GET_CODE (elt) != MATCH_DUP)
771	insn_nr++;
772    }
773}
774
775int
776main (int argc, char **argv)
777{
778  rtx desc;
779
780  progname = "genemit";
781
782  if (!init_rtx_reader_args (argc, argv))
783    return (FATAL_EXIT_CODE);
784
785  /* Assign sequential codes to all entries in the machine description
786     in parallel with the tables in insn-output.c.  */
787
788  insn_code_number = 0;
789  insn_index_number = 0;
790
791  printf ("/* Generated automatically by the program `genemit'\n\
792from the machine description file `md'.  */\n\n");
793
794  printf ("#include \"config.h\"\n");
795  printf ("#include \"system.h\"\n");
796  printf ("#include \"coretypes.h\"\n");
797  printf ("#include \"tm.h\"\n");
798  printf ("#include \"hash-set.h\"\n");
799  printf ("#include \"machmode.h\"\n");
800  printf ("#include \"vec.h\"\n");
801  printf ("#include \"double-int.h\"\n");
802  printf ("#include \"input.h\"\n");
803  printf ("#include \"alias.h\"\n");
804  printf ("#include \"symtab.h\"\n");
805  printf ("#include \"wide-int.h\"\n");
806  printf ("#include \"inchash.h\"\n");
807  printf ("#include \"tree.h\"\n");
808  printf ("#include \"varasm.h\"\n");
809  printf ("#include \"stor-layout.h\"\n");
810  printf ("#include \"calls.h\"\n");
811  printf ("#include \"rtl.h\"\n");
812  printf ("#include \"tm_p.h\"\n");
813  printf ("#include \"hashtab.h\"\n");
814  printf ("#include \"hard-reg-set.h\"\n");
815  printf ("#include \"function.h\"\n");
816  printf ("#include \"flags.h\"\n");
817  printf ("#include \"statistics.h\"\n");
818  printf ("#include \"real.h\"\n");
819  printf ("#include \"fixed-value.h\"\n");
820  printf ("#include \"insn-config.h\"\n");
821  printf ("#include \"expmed.h\"\n");
822  printf ("#include \"dojump.h\"\n");
823  printf ("#include \"explow.h\"\n");
824  printf ("#include \"emit-rtl.h\"\n");
825  printf ("#include \"stmt.h\"\n");
826  printf ("#include \"expr.h\"\n");
827  printf ("#include \"insn-codes.h\"\n");
828  printf ("#include \"optabs.h\"\n");
829  printf ("#include \"dfp.h\"\n");
830  printf ("#include \"output.h\"\n");
831  printf ("#include \"recog.h\"\n");
832  printf ("#include \"predict.h\"\n");
833  printf ("#include \"basic-block.h\"\n");
834  printf ("#include \"resource.h\"\n");
835  printf ("#include \"reload.h\"\n");
836  printf ("#include \"diagnostic-core.h\"\n");
837  printf ("#include \"regs.h\"\n");
838  printf ("#include \"tm-constrs.h\"\n");
839  printf ("#include \"ggc.h\"\n");
840  printf ("#include \"basic-block.h\"\n");
841  printf ("#include \"dumpfile.h\"\n");
842  printf ("#include \"target.h\"\n\n");
843  printf ("#define FAIL return (end_sequence (), _val)\n");
844  printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
845
846  /* Read the machine description.  */
847
848  while (1)
849    {
850      int line_no;
851
852      desc = read_md_rtx (&line_no, &insn_code_number);
853      if (desc == NULL)
854	break;
855
856      switch (GET_CODE (desc))
857	{
858	case DEFINE_INSN:
859	  gen_insn (desc, line_no);
860	  break;
861
862	case DEFINE_EXPAND:
863	  printf ("/* %s:%d */\n", read_md_filename, line_no);
864	  gen_expand (desc);
865	  break;
866
867	case DEFINE_SPLIT:
868	  printf ("/* %s:%d */\n", read_md_filename, line_no);
869	  gen_split (desc);
870	  break;
871
872	case DEFINE_PEEPHOLE2:
873	  printf ("/* %s:%d */\n", read_md_filename, line_no);
874	  gen_split (desc);
875	  break;
876
877	default:
878	  break;
879	}
880      ++insn_index_number;
881    }
882
883  /* Write out the routines to add CLOBBERs to a pattern and say whether they
884     clobber a hard reg.  */
885  output_add_clobbers ();
886  output_added_clobbers_hard_reg_p ();
887
888  fflush (stdout);
889  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
890}
891