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