OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [genpreds.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Generate from machine description:
2
   - prototype declarations for operand predicates (tm-preds.h)
3
   - function definitions of operand predicates, if defined new-style
4
     (insn-preds.c)
5
   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2, or (at your option)
12
any later version.
13
 
14
GCC is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING.  If not, write to
21
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22
Boston, MA 02110-1301, USA.  */
23
 
24
#include "bconfig.h"
25
#include "system.h"
26
#include "coretypes.h"
27
#include "tm.h"
28
#include "rtl.h"
29
#include "errors.h"
30
#include "gensupport.h"
31
#include "obstack.h"
32
 
33
/* The new way to declare predicates is with (define_predicate) or
34
   (define_special_predicate) expressions in the machine description.
35
   This provides a function body as well as a name.  */
36
static void
37
process_define_predicate (rtx defn)
38
{
39
  struct pred_data *pred;
40
  if (XEXP (defn, 1) == 0)
41
    {
42
      error ("%s: must give a predicate expression", XSTR (defn, 0));
43
      return;
44
    }
45
 
46
  pred = xcalloc (sizeof (struct pred_data), 1);
47
  pred->name    = XSTR (defn, 0);
48
  pred->exp     = XEXP (defn, 1);
49
  pred->c_block = XSTR (defn, 2);
50
 
51
  if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
52
    pred->special = true;
53
 
54
  add_predicate (pred);
55
}
56
 
57
/* Write tm-preds.h.  Unfortunately, it is impossible to forward-declare
58
   an enumeration in portable C, so we have to condition all these
59
   prototypes on HAVE_MACHINE_MODES.  */
60
static void
61
write_tm_preds_h (void)
62
{
63
  struct pred_data *p;
64
 
65
  printf ("\
66
/* Generated automatically by the program '%s'\n\
67
   from the machine description file '%s'.  */\n\n", progname, in_fname);
68
 
69
  puts ("\
70
#ifndef GCC_TM_PREDS_H\n\
71
#define GCC_TM_PREDS_H\n\
72
\n\
73
#ifdef HAVE_MACHINE_MODES");
74
 
75
  FOR_ALL_PREDICATES (p)
76
    printf ("extern int %s (rtx, enum machine_mode);\n", p->name);
77
 
78
  puts ("\
79
#endif /* HAVE_MACHINE_MODES */\n\
80
#endif /* tm-preds.h */");
81
}
82
 
83
/* Given a predicate, if it has an embedded C block, write the block
84
   out as a static inline subroutine, and augment the RTL test with a
85
   match_test that calls that subroutine.  For instance,
86
 
87
       (define_predicate "basereg_operand"
88
         (match_operand 0 "register_operand")
89
       {
90
         if (GET_CODE (op) == SUBREG)
91
           op = SUBREG_REG (op);
92
         return REG_POINTER (op);
93
       })
94
 
95
   becomes
96
 
97
       static inline int basereg_operand_1(rtx op, enum machine_mode mode)
98
       {
99
         if (GET_CODE (op) == SUBREG)
100
           op = SUBREG_REG (op);
101
         return REG_POINTER (op);
102
       }
103
 
104
       (define_predicate "basereg_operand"
105
         (and (match_operand 0 "register_operand")
106
              (match_test "basereg_operand_1 (op, mode)")))
107
 
108
   The only wart is that there's no way to insist on a { } string in
109
   an RTL template, so we have to handle "" strings.  */
110
 
111
 
112
static void
113
write_predicate_subfunction (struct pred_data *p)
114
{
115
  const char *match_test_str;
116
  rtx match_test_exp, and_exp;
117
 
118
  if (p->c_block[0] == '\0')
119
    return;
120
 
121
  /* Construct the function-call expression.  */
122
  obstack_grow (rtl_obstack, p->name, strlen (p->name));
123
  obstack_grow (rtl_obstack, "_1 (op, mode)",
124
                sizeof "_1 (op, mode)");
125
  match_test_str = XOBFINISH (rtl_obstack, const char *);
126
 
127
  /* Add the function-call expression to the complete expression to be
128
     evaluated.  */
129
  match_test_exp = rtx_alloc (MATCH_TEST);
130
  XSTR (match_test_exp, 0) = match_test_str;
131
 
132
  and_exp = rtx_alloc (AND);
133
  XEXP (and_exp, 0) = p->exp;
134
  XEXP (and_exp, 1) = match_test_exp;
135
 
136
  p->exp = and_exp;
137
 
138
  printf ("static inline int\n"
139
          "%s_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n",
140
          p->name);
141
  print_rtx_ptr_loc (p->c_block);
142
  if (p->c_block[0] == '{')
143
    fputs (p->c_block, stdout);
144
  else
145
    printf ("{\n  %s\n}", p->c_block);
146
  fputs ("\n\n", stdout);
147
}
148
 
149
/* Given an RTL expression EXP, find all subexpressions which we may
150
   assume to perform mode tests.  Normal MATCH_OPERAND does;
151
   MATCH_CODE does if and only if it accepts CONST_INT or
152
   CONST_DOUBLE; and we have to assume that MATCH_TEST does not.
153
   These combine in almost-boolean fashion - the only exception is
154
   that (not X) must be assumed not to perform a mode test, whether or
155
   not X does.
156
 
157
   The mark is the RTL /v flag, which is true for subexpressions which
158
   do *not* perform mode tests.
159
*/
160
#define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
161
static void
162
mark_mode_tests (rtx exp)
163
{
164
  switch (GET_CODE (exp))
165
    {
166
    case MATCH_OPERAND:
167
      {
168
        struct pred_data *p = lookup_predicate (XSTR (exp, 1));
169
        if (!p)
170
          error ("reference to undefined predicate '%s'", XSTR (exp, 1));
171
        else if (p->special || GET_MODE (exp) != VOIDmode)
172
          NO_MODE_TEST (exp) = 1;
173
      }
174
      break;
175
 
176
    case MATCH_CODE:
177
      if (!strstr (XSTR (exp, 0), "const_int")
178
          && !strstr (XSTR (exp, 0), "const_double"))
179
        NO_MODE_TEST (exp) = 1;
180
      break;
181
 
182
    case MATCH_TEST:
183
    case NOT:
184
      NO_MODE_TEST (exp) = 1;
185
      break;
186
 
187
    case AND:
188
      mark_mode_tests (XEXP (exp, 0));
189
      mark_mode_tests (XEXP (exp, 1));
190
 
191
      NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
192
                            && NO_MODE_TEST (XEXP (exp, 1)));
193
      break;
194
 
195
    case IOR:
196
      mark_mode_tests (XEXP (exp, 0));
197
      mark_mode_tests (XEXP (exp, 1));
198
 
199
      NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
200
                            || NO_MODE_TEST (XEXP (exp, 1)));
201
      break;
202
 
203
    case IF_THEN_ELSE:
204
      /* A ? B : C does a mode test if (one of A and B) does a mode
205
         test, and C does too.  */
206
      mark_mode_tests (XEXP (exp, 0));
207
      mark_mode_tests (XEXP (exp, 1));
208
      mark_mode_tests (XEXP (exp, 2));
209
 
210
      NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0))
211
                             && NO_MODE_TEST (XEXP (exp, 1)))
212
                            || NO_MODE_TEST (XEXP (exp, 2)));
213
      break;
214
 
215
    default:
216
      error ("'%s' cannot be used in a define_predicate expression",
217
             GET_RTX_NAME (GET_CODE (exp)));
218
    }
219
}
220
 
221
/* Given a predicate, work out where in its RTL expression to add
222
   tests for proper modes.  Special predicates do not get any such
223
   tests.  We try to avoid adding tests when we don't have to; in
224
   particular, other normal predicates can be counted on to do it for
225
   us.  */
226
 
227
static void
228
add_mode_tests (struct pred_data *p)
229
{
230
  rtx match_test_exp, and_exp;
231
  rtx *pos;
232
 
233
  /* Don't touch special predicates.  */
234
  if (p->special)
235
    return;
236
 
237
  mark_mode_tests (p->exp);
238
 
239
  /* If the whole expression already tests the mode, we're done.  */
240
  if (!NO_MODE_TEST (p->exp))
241
    return;
242
 
243
  match_test_exp = rtx_alloc (MATCH_TEST);
244
  XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
245
  and_exp = rtx_alloc (AND);
246
  XEXP (and_exp, 1) = match_test_exp;
247
 
248
  /* It is always correct to rewrite p->exp as
249
 
250
        (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode"))
251
 
252
     but there are a couple forms where we can do better.  If the
253
     top-level pattern is an IOR, and one of the two branches does test
254
     the mode, we can wrap just the branch that doesn't.  Likewise, if
255
     we have an IF_THEN_ELSE, and one side of it tests the mode, we can
256
     wrap just the side that doesn't.  And, of course, we can repeat this
257
     descent as many times as it works.  */
258
 
259
  pos = &p->exp;
260
  for (;;)
261
    {
262
      rtx subexp = *pos;
263
 
264
      switch (GET_CODE (subexp))
265
        {
266
        case IOR:
267
          {
268
            int test0 = NO_MODE_TEST (XEXP (subexp, 0));
269
            int test1 = NO_MODE_TEST (XEXP (subexp, 1));
270
 
271
            gcc_assert (test0 || test1);
272
 
273
            if (test0 && test1)
274
              goto break_loop;
275
            pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1);
276
          }
277
          break;
278
 
279
        case IF_THEN_ELSE:
280
          {
281
            int test0 = NO_MODE_TEST (XEXP (subexp, 0));
282
            int test1 = NO_MODE_TEST (XEXP (subexp, 1));
283
            int test2 = NO_MODE_TEST (XEXP (subexp, 2));
284
 
285
            gcc_assert ((test0 && test1) || test2);
286
 
287
            if (test0 && test1 && test2)
288
              goto break_loop;
289
            if (test0 && test1)
290
              /* Must put it on the dependent clause, not the
291
                 controlling expression, or we change the meaning of
292
                 the test.  */
293
              pos = &XEXP (subexp, 1);
294
            else
295
              pos = &XEXP (subexp, 2);
296
          }
297
          break;
298
 
299
        default:
300
          goto break_loop;
301
        }
302
    }
303
 break_loop:
304
  XEXP (and_exp, 0) = *pos;
305
  *pos = and_exp;
306
}
307
 
308
 
309
/* CODES is a list of RTX codes.  Write out an expression which
310
   determines whether the operand has one of those codes.  */
311
static void
312
write_match_code (const char *codes)
313
{
314
  const char *code;
315
 
316
  while ((code = scan_comma_elt (&codes)) != 0)
317
    {
318
      fputs ("GET_CODE (op) == ", stdout);
319
      while (code < codes)
320
        {
321
          putchar (TOUPPER (*code));
322
          code++;
323
        }
324
 
325
      if (*codes == ',')
326
        fputs (" || ", stdout);
327
    }
328
}
329
 
330
/* EXP is an RTL (sub)expression for a predicate.  Recursively
331
   descend the expression and write out an equivalent C expression.  */
332
static void
333
write_predicate_expr (const char *name, rtx exp)
334
{
335
  switch (GET_CODE (exp))
336
    {
337
    case AND:
338
      putchar ('(');
339
      write_predicate_expr (name, XEXP (exp, 0));
340
      fputs (") && (", stdout);
341
      write_predicate_expr (name, XEXP (exp, 1));
342
      putchar (')');
343
      break;
344
 
345
    case IOR:
346
      putchar ('(');
347
      write_predicate_expr (name, XEXP (exp, 0));
348
      fputs (") || (", stdout);
349
      write_predicate_expr (name, XEXP (exp, 1));
350
      putchar (')');
351
      break;
352
 
353
    case NOT:
354
      fputs ("!(", stdout);
355
      write_predicate_expr (name, XEXP (exp, 0));
356
      putchar (')');
357
      break;
358
 
359
    case IF_THEN_ELSE:
360
      putchar ('(');
361
      write_predicate_expr (name, XEXP (exp, 0));
362
      fputs (") ? (", stdout);
363
      write_predicate_expr (name, XEXP (exp, 1));
364
      fputs (") : (", stdout);
365
      write_predicate_expr (name, XEXP (exp, 2));
366
      putchar (')');
367
      break;
368
 
369
    case MATCH_OPERAND:
370
      if (GET_MODE (exp) == VOIDmode)
371
        printf ("%s (op, mode)", XSTR (exp, 1));
372
      else
373
        printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]);
374
      break;
375
 
376
    case MATCH_CODE:
377
      write_match_code (XSTR (exp, 0));
378
      break;
379
 
380
    case MATCH_TEST:
381
      print_c_condition (XSTR (exp, 0));
382
      break;
383
 
384
    default:
385
      error ("%s: cannot use '%s' in a predicate expression",
386
             name, GET_RTX_NAME (GET_CODE (exp)));
387
      putchar ('0');
388
    }
389
}
390
 
391
/* Given a predicate, write out a complete C function to compute it.  */
392
static void
393
write_one_predicate_function (struct pred_data *p)
394
{
395
  if (!p->exp)
396
    return;
397
 
398
  write_predicate_subfunction (p);
399
  add_mode_tests (p);
400
 
401
  /* A normal predicate can legitimately not look at enum machine_mode
402
     if it accepts only CONST_INTs and/or CONST_DOUBLEs.  */
403
  printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
404
          "{\n  return ",
405
          p->name);
406
  write_predicate_expr (p->name, p->exp);
407
  fputs (";\n}\n\n", stdout);
408
}
409
 
410
/* Write insn-preds.c.
411
   N.B. the list of headers to include was copied from genrecog; it
412
   may not be ideal.
413
 
414
   FUTURE: Write #line markers referring back to the machine
415
   description.  (Can't practically do this now since we don't know
416
   the line number of the C block - just the line number of the enclosing
417
   expression.)  */
418
static void
419
write_insn_preds_c (void)
420
{
421
  struct pred_data *p;
422
 
423
  printf ("\
424
/* Generated automatically by the program '%s'\n\
425
   from the machine description file '%s'.  */\n\n", progname, in_fname);
426
 
427
  puts ("\
428
#include \"config.h\"\n\
429
#include \"system.h\"\n\
430
#include \"coretypes.h\"\n\
431
#include \"tm.h\"\n\
432
#include \"rtl.h\"\n\
433
#include \"tree.h\"\n\
434
#include \"tm_p.h\"\n\
435
#include \"function.h\"\n\
436
#include \"insn-config.h\"\n\
437
#include \"recog.h\"\n\
438
#include \"real.h\"\n\
439
#include \"output.h\"\n\
440
#include \"flags.h\"\n\
441
#include \"hard-reg-set.h\"\n\
442
#include \"resource.h\"\n\
443
#include \"toplev.h\"\n\
444
#include \"reload.h\"\n\
445
#include \"regs.h\"\n");
446
 
447
  FOR_ALL_PREDICATES (p)
448
    write_one_predicate_function (p);
449
}
450
 
451
/* Argument parsing.  */
452
static bool gen_header;
453
static bool
454
parse_option (const char *opt)
455
{
456
  if (!strcmp (opt, "-h"))
457
    {
458
      gen_header = true;
459
      return 1;
460
    }
461
  else
462
    return 0;
463
}
464
 
465
/* Master control.  */
466
int
467
main (int argc, char **argv)
468
{
469
  rtx defn;
470
  int pattern_lineno, next_insn_code = 0;
471
 
472
  progname = argv[0];
473
  if (argc <= 1)
474
    fatal ("no input file name");
475
  if (init_md_reader_args_cb (argc, argv, parse_option) != SUCCESS_EXIT_CODE)
476
    return FATAL_EXIT_CODE;
477
 
478
  while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
479
    {
480
      if (GET_CODE (defn) == DEFINE_PREDICATE
481
          || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
482
        process_define_predicate (defn);
483
    }
484
 
485
  if (gen_header)
486
    write_tm_preds_h ();
487
  else
488
    write_insn_preds_c ();
489
 
490
  if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
491
    return FATAL_EXIT_CODE;
492
 
493
  return SUCCESS_EXIT_CODE;
494
}
495
 
496
/* Dummy for debugging purposes.  */
497
const char *
498
get_insn_name (int code ATTRIBUTE_UNUSED)
499
{
500
  return 0;
501
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.