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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [gensupport.c] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Support routines for the various generation passes.
2
   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of GCC.
6
 
7
   GCC is free software; you can redistribute it and/or modify it
8
   under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2, or (at your option)
10
   any later version.
11
 
12
   GCC is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with GCC; see the file COPYING.  If not, write to the Free
19
   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20
   02110-1301, USA.  */
21
 
22
#include "bconfig.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "rtl.h"
27
#include "obstack.h"
28
#include "errors.h"
29
#include "hashtab.h"
30
#include "gensupport.h"
31
 
32
 
33
/* In case some macros used by files we include need it, define this here.  */
34
int target_flags;
35
 
36
int insn_elision = 1;
37
 
38
const char *in_fname;
39
 
40
/* This callback will be invoked whenever an rtl include directive is
41
   processed.  To be used for creation of the dependency file.  */
42
void (*include_callback) (const char *);
43
 
44
static struct obstack obstack;
45
struct obstack *rtl_obstack = &obstack;
46
 
47
static int sequence_num;
48
static int errors;
49
 
50
static int predicable_default;
51
static const char *predicable_true;
52
static const char *predicable_false;
53
 
54
static htab_t condition_table;
55
 
56
static char *base_dir = NULL;
57
 
58
/* We initially queue all patterns, process the define_insn and
59
   define_cond_exec patterns, then return them one at a time.  */
60
 
61
struct queue_elem
62
{
63
  rtx data;
64
  const char *filename;
65
  int lineno;
66
  struct queue_elem *next;
67
  /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
68
     points to the generated DEFINE_SPLIT.  */
69
  struct queue_elem *split;
70
};
71
 
72
static struct queue_elem *define_attr_queue;
73
static struct queue_elem **define_attr_tail = &define_attr_queue;
74
static struct queue_elem *define_pred_queue;
75
static struct queue_elem **define_pred_tail = &define_pred_queue;
76
static struct queue_elem *define_insn_queue;
77
static struct queue_elem **define_insn_tail = &define_insn_queue;
78
static struct queue_elem *define_cond_exec_queue;
79
static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
80
static struct queue_elem *other_queue;
81
static struct queue_elem **other_tail = &other_queue;
82
 
83
static struct queue_elem *queue_pattern (rtx, struct queue_elem ***,
84
                                         const char *, int);
85
 
86
/* Current maximum length of directory names in the search path
87
   for include files.  (Altered as we get more of them.)  */
88
 
89
size_t max_include_len;
90
 
91
struct file_name_list
92
  {
93
    struct file_name_list *next;
94
    const char *fname;
95
  };
96
 
97
struct file_name_list *first_dir_md_include = 0;  /* First dir to search */
98
        /* First dir to search for <file> */
99
struct file_name_list *first_bracket_include = 0;
100
struct file_name_list *last_dir_md_include = 0;        /* Last in chain */
101
 
102
static void remove_constraints (rtx);
103
static void process_rtx (rtx, int);
104
 
105
static int is_predicable (struct queue_elem *);
106
static void identify_predicable_attribute (void);
107
static int n_alternatives (const char *);
108
static void collect_insn_data (rtx, int *, int *);
109
static rtx alter_predicate_for_insn (rtx, int, int, int);
110
static const char *alter_test_for_insn (struct queue_elem *,
111
                                        struct queue_elem *);
112
static char *shift_output_template (char *, const char *, int);
113
static const char *alter_output_for_insn (struct queue_elem *,
114
                                          struct queue_elem *,
115
                                          int, int);
116
static void process_one_cond_exec (struct queue_elem *);
117
static void process_define_cond_exec (void);
118
static void process_include (rtx, int);
119
static char *save_string (const char *, int);
120
static void init_predicate_table (void);
121
 
122
void
123
message_with_line (int lineno, const char *msg, ...)
124
{
125
  va_list ap;
126
 
127
  va_start (ap, msg);
128
 
129
  fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
130
  vfprintf (stderr, msg, ap);
131
  fputc ('\n', stderr);
132
 
133
  va_end (ap);
134
}
135
 
136
/* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
137
   the gensupport programs.  */
138
 
139
rtx
140
gen_rtx_CONST_INT (enum machine_mode ARG_UNUSED (mode),
141
                   HOST_WIDE_INT arg)
142
{
143
  rtx rt = rtx_alloc (CONST_INT);
144
 
145
  XWINT (rt, 0) = arg;
146
  return rt;
147
}
148
 
149
/* Queue PATTERN on LIST_TAIL.  Return the address of the new queue
150
   element.  */
151
 
152
static struct queue_elem *
153
queue_pattern (rtx pattern, struct queue_elem ***list_tail,
154
               const char *filename, int lineno)
155
{
156
  struct queue_elem *e = XNEW(struct queue_elem);
157
  e->data = pattern;
158
  e->filename = filename;
159
  e->lineno = lineno;
160
  e->next = NULL;
161
  e->split = NULL;
162
  **list_tail = e;
163
  *list_tail = &e->next;
164
  return e;
165
}
166
 
167
/* Recursively remove constraints from an rtx.  */
168
 
169
static void
170
remove_constraints (rtx part)
171
{
172
  int i, j;
173
  const char *format_ptr;
174
 
175
  if (part == 0)
176
    return;
177
 
178
  if (GET_CODE (part) == MATCH_OPERAND)
179
    XSTR (part, 2) = "";
180
  else if (GET_CODE (part) == MATCH_SCRATCH)
181
    XSTR (part, 1) = "";
182
 
183
  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
184
 
185
  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
186
    switch (*format_ptr++)
187
      {
188
      case 'e':
189
      case 'u':
190
        remove_constraints (XEXP (part, i));
191
        break;
192
      case 'E':
193
        if (XVEC (part, i) != NULL)
194
          for (j = 0; j < XVECLEN (part, i); j++)
195
            remove_constraints (XVECEXP (part, i, j));
196
        break;
197
      }
198
}
199
 
200
/* Process an include file assuming that it lives in gcc/config/{target}/
201
   if the include looks like (include "file").  */
202
 
203
static void
204
process_include (rtx desc, int lineno)
205
{
206
  const char *filename = XSTR (desc, 0);
207
  const char *old_filename;
208
  int old_lineno;
209
  char *pathname;
210
  FILE *input_file;
211
 
212
  /* If specified file name is absolute, skip the include stack.  */
213
  if (! IS_ABSOLUTE_PATH (filename))
214
    {
215
      struct file_name_list *stackp;
216
 
217
      /* Search directory path, trying to open the file.  */
218
      for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
219
        {
220
          static const char sep[2] = { DIR_SEPARATOR, '\0' };
221
 
222
          pathname = concat (stackp->fname, sep, filename, NULL);
223
          input_file = fopen (pathname, "r");
224
          if (input_file != NULL)
225
            goto success;
226
          free (pathname);
227
        }
228
    }
229
 
230
  if (base_dir)
231
    pathname = concat (base_dir, filename, NULL);
232
  else
233
    pathname = xstrdup (filename);
234
  input_file = fopen (pathname, "r");
235
  if (input_file == NULL)
236
    {
237
      free (pathname);
238
      message_with_line (lineno, "include file `%s' not found", filename);
239
      errors = 1;
240
      return;
241
    }
242
 success:
243
 
244
  /* Save old cursor; setup new for the new file.  Note that "lineno" the
245
     argument to this function is the beginning of the include statement,
246
     while read_rtx_lineno has already been advanced.  */
247
  old_filename = read_rtx_filename;
248
  old_lineno = read_rtx_lineno;
249
  read_rtx_filename = pathname;
250
  read_rtx_lineno = 1;
251
 
252
  if (include_callback)
253
    include_callback (pathname);
254
 
255
  /* Read the entire file.  */
256
  while (read_rtx (input_file, &desc, &lineno))
257
    process_rtx (desc, lineno);
258
 
259
  /* Do not free pathname.  It is attached to the various rtx queue
260
     elements.  */
261
 
262
  read_rtx_filename = old_filename;
263
  read_rtx_lineno = old_lineno;
264
 
265
  fclose (input_file);
266
}
267
 
268
/* Process a top level rtx in some way, queuing as appropriate.  */
269
 
270
static void
271
process_rtx (rtx desc, int lineno)
272
{
273
  switch (GET_CODE (desc))
274
    {
275
    case DEFINE_INSN:
276
      queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
277
      break;
278
 
279
    case DEFINE_COND_EXEC:
280
      queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
281
      break;
282
 
283
    case DEFINE_ATTR:
284
      queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
285
      break;
286
 
287
    case DEFINE_PREDICATE:
288
    case DEFINE_SPECIAL_PREDICATE:
289
      queue_pattern (desc, &define_pred_tail, read_rtx_filename, lineno);
290
      break;
291
 
292
    case INCLUDE:
293
      process_include (desc, lineno);
294
      break;
295
 
296
    case DEFINE_INSN_AND_SPLIT:
297
      {
298
        const char *split_cond;
299
        rtx split;
300
        rtvec attr;
301
        int i;
302
        struct queue_elem *insn_elem;
303
        struct queue_elem *split_elem;
304
 
305
        /* Create a split with values from the insn_and_split.  */
306
        split = rtx_alloc (DEFINE_SPLIT);
307
 
308
        i = XVECLEN (desc, 1);
309
        XVEC (split, 0) = rtvec_alloc (i);
310
        while (--i >= 0)
311
          {
312
            XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
313
            remove_constraints (XVECEXP (split, 0, i));
314
          }
315
 
316
        /* If the split condition starts with "&&", append it to the
317
           insn condition to create the new split condition.  */
318
        split_cond = XSTR (desc, 4);
319
        if (split_cond[0] == '&' && split_cond[1] == '&')
320
          {
321
            copy_rtx_ptr_loc (split_cond + 2, split_cond);
322
            split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2);
323
          }
324
        XSTR (split, 1) = split_cond;
325
        XVEC (split, 2) = XVEC (desc, 5);
326
        XSTR (split, 3) = XSTR (desc, 6);
327
 
328
        /* Fix up the DEFINE_INSN.  */
329
        attr = XVEC (desc, 7);
330
        PUT_CODE (desc, DEFINE_INSN);
331
        XVEC (desc, 4) = attr;
332
 
333
        /* Queue them.  */
334
        insn_elem
335
          = queue_pattern (desc, &define_insn_tail, read_rtx_filename,
336
                           lineno);
337
        split_elem
338
          = queue_pattern (split, &other_tail, read_rtx_filename, lineno);
339
        insn_elem->split = split_elem;
340
        break;
341
      }
342
 
343
    default:
344
      queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
345
      break;
346
    }
347
}
348
 
349
/* Return true if attribute PREDICABLE is true for ELEM, which holds
350
   a DEFINE_INSN.  */
351
 
352
static int
353
is_predicable (struct queue_elem *elem)
354
{
355
  rtvec vec = XVEC (elem->data, 4);
356
  const char *value;
357
  int i;
358
 
359
  if (! vec)
360
    return predicable_default;
361
 
362
  for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
363
    {
364
      rtx sub = RTVEC_ELT (vec, i);
365
      switch (GET_CODE (sub))
366
        {
367
        case SET_ATTR:
368
          if (strcmp (XSTR (sub, 0), "predicable") == 0)
369
            {
370
              value = XSTR (sub, 1);
371
              goto found;
372
            }
373
          break;
374
 
375
        case SET_ATTR_ALTERNATIVE:
376
          if (strcmp (XSTR (sub, 0), "predicable") == 0)
377
            {
378
              message_with_line (elem->lineno,
379
                                 "multiple alternatives for `predicable'");
380
              errors = 1;
381
              return 0;
382
            }
383
          break;
384
 
385
        case SET:
386
          if (GET_CODE (SET_DEST (sub)) != ATTR
387
              || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
388
            break;
389
          sub = SET_SRC (sub);
390
          if (GET_CODE (sub) == CONST_STRING)
391
            {
392
              value = XSTR (sub, 0);
393
              goto found;
394
            }
395
 
396
          /* ??? It would be possible to handle this if we really tried.
397
             It's not easy though, and I'm not going to bother until it
398
             really proves necessary.  */
399
          message_with_line (elem->lineno,
400
                             "non-constant value for `predicable'");
401
          errors = 1;
402
          return 0;
403
 
404
        default:
405
          gcc_unreachable ();
406
        }
407
    }
408
 
409
  return predicable_default;
410
 
411
 found:
412
  /* Verify that predicability does not vary on the alternative.  */
413
  /* ??? It should be possible to handle this by simply eliminating
414
     the non-predicable alternatives from the insn.  FRV would like
415
     to do this.  Delay this until we've got the basics solid.  */
416
  if (strchr (value, ',') != NULL)
417
    {
418
      message_with_line (elem->lineno,
419
                         "multiple alternatives for `predicable'");
420
      errors = 1;
421
      return 0;
422
    }
423
 
424
  /* Find out which value we're looking at.  */
425
  if (strcmp (value, predicable_true) == 0)
426
    return 1;
427
  if (strcmp (value, predicable_false) == 0)
428
    return 0;
429
 
430
  message_with_line (elem->lineno,
431
                     "unknown value `%s' for `predicable' attribute",
432
                     value);
433
  errors = 1;
434
  return 0;
435
}
436
 
437
/* Examine the attribute "predicable"; discover its boolean values
438
   and its default.  */
439
 
440
static void
441
identify_predicable_attribute (void)
442
{
443
  struct queue_elem *elem;
444
  char *p_true, *p_false;
445
  const char *value;
446
 
447
  /* Look for the DEFINE_ATTR for `predicable', which must exist.  */
448
  for (elem = define_attr_queue; elem ; elem = elem->next)
449
    if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
450
      goto found;
451
 
452
  message_with_line (define_cond_exec_queue->lineno,
453
                     "attribute `predicable' not defined");
454
  errors = 1;
455
  return;
456
 
457
 found:
458
  value = XSTR (elem->data, 1);
459
  p_false = xstrdup (value);
460
  p_true = strchr (p_false, ',');
461
  if (p_true == NULL || strchr (++p_true, ',') != NULL)
462
    {
463
      message_with_line (elem->lineno,
464
                         "attribute `predicable' is not a boolean");
465
      errors = 1;
466
      return;
467
    }
468
  p_true[-1] = '\0';
469
 
470
  predicable_true = p_true;
471
  predicable_false = p_false;
472
 
473
  switch (GET_CODE (XEXP (elem->data, 2)))
474
    {
475
    case CONST_STRING:
476
      value = XSTR (XEXP (elem->data, 2), 0);
477
      break;
478
 
479
    case CONST:
480
      message_with_line (elem->lineno,
481
                         "attribute `predicable' cannot be const");
482
      errors = 1;
483
      return;
484
 
485
    default:
486
      message_with_line (elem->lineno,
487
                         "attribute `predicable' must have a constant default");
488
      errors = 1;
489
      return;
490
    }
491
 
492
  if (strcmp (value, p_true) == 0)
493
    predicable_default = 1;
494
  else if (strcmp (value, p_false) == 0)
495
    predicable_default = 0;
496
  else
497
    {
498
      message_with_line (elem->lineno,
499
                         "unknown value `%s' for `predicable' attribute",
500
                         value);
501
      errors = 1;
502
    }
503
}
504
 
505
/* Return the number of alternatives in constraint S.  */
506
 
507
static int
508
n_alternatives (const char *s)
509
{
510
  int n = 1;
511
 
512
  if (s)
513
    while (*s)
514
      n += (*s++ == ',');
515
 
516
  return n;
517
}
518
 
519
/* Determine how many alternatives there are in INSN, and how many
520
   operands.  */
521
 
522
static void
523
collect_insn_data (rtx pattern, int *palt, int *pmax)
524
{
525
  const char *fmt;
526
  enum rtx_code code;
527
  int i, j, len;
528
 
529
  code = GET_CODE (pattern);
530
  switch (code)
531
    {
532
    case MATCH_OPERAND:
533
      i = n_alternatives (XSTR (pattern, 2));
534
      *palt = (i > *palt ? i : *palt);
535
      /* Fall through.  */
536
 
537
    case MATCH_OPERATOR:
538
    case MATCH_SCRATCH:
539
    case MATCH_PARALLEL:
540
      i = XINT (pattern, 0);
541
      if (i > *pmax)
542
        *pmax = i;
543
      break;
544
 
545
    default:
546
      break;
547
    }
548
 
549
  fmt = GET_RTX_FORMAT (code);
550
  len = GET_RTX_LENGTH (code);
551
  for (i = 0; i < len; i++)
552
    {
553
      switch (fmt[i])
554
        {
555
        case 'e': case 'u':
556
          collect_insn_data (XEXP (pattern, i), palt, pmax);
557
          break;
558
 
559
        case 'V':
560
          if (XVEC (pattern, i) == NULL)
561
            break;
562
          /* Fall through.  */
563
        case 'E':
564
          for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
565
            collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
566
          break;
567
 
568
        case 'i': case 'w': case '0': case 's': case 'S': case 'T':
569
          break;
570
 
571
        default:
572
          gcc_unreachable ();
573
        }
574
    }
575
}
576
 
577
static rtx
578
alter_predicate_for_insn (rtx pattern, int alt, int max_op, int lineno)
579
{
580
  const char *fmt;
581
  enum rtx_code code;
582
  int i, j, len;
583
 
584
  code = GET_CODE (pattern);
585
  switch (code)
586
    {
587
    case MATCH_OPERAND:
588
      {
589
        const char *c = XSTR (pattern, 2);
590
 
591
        if (n_alternatives (c) != 1)
592
          {
593
            message_with_line (lineno,
594
                               "too many alternatives for operand %d",
595
                               XINT (pattern, 0));
596
            errors = 1;
597
            return NULL;
598
          }
599
 
600
        /* Replicate C as needed to fill out ALT alternatives.  */
601
        if (c && *c && alt > 1)
602
          {
603
            size_t c_len = strlen (c);
604
            size_t len = alt * (c_len + 1);
605
            char *new_c = XNEWVEC(char, len);
606
 
607
            memcpy (new_c, c, c_len);
608
            for (i = 1; i < alt; ++i)
609
              {
610
                new_c[i * (c_len + 1) - 1] = ',';
611
                memcpy (&new_c[i * (c_len + 1)], c, c_len);
612
              }
613
            new_c[len - 1] = '\0';
614
            XSTR (pattern, 2) = new_c;
615
          }
616
      }
617
      /* Fall through.  */
618
 
619
    case MATCH_OPERATOR:
620
    case MATCH_SCRATCH:
621
    case MATCH_PARALLEL:
622
      XINT (pattern, 0) += max_op;
623
      break;
624
 
625
    default:
626
      break;
627
    }
628
 
629
  fmt = GET_RTX_FORMAT (code);
630
  len = GET_RTX_LENGTH (code);
631
  for (i = 0; i < len; i++)
632
    {
633
      rtx r;
634
 
635
      switch (fmt[i])
636
        {
637
        case 'e': case 'u':
638
          r = alter_predicate_for_insn (XEXP (pattern, i), alt,
639
                                        max_op, lineno);
640
          if (r == NULL)
641
            return r;
642
          break;
643
 
644
        case 'E':
645
          for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
646
            {
647
              r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
648
                                            alt, max_op, lineno);
649
              if (r == NULL)
650
                return r;
651
            }
652
          break;
653
 
654
        case 'i': case 'w': case '0': case 's':
655
          break;
656
 
657
        default:
658
          gcc_unreachable ();
659
        }
660
    }
661
 
662
  return pattern;
663
}
664
 
665
static const char *
666
alter_test_for_insn (struct queue_elem *ce_elem,
667
                     struct queue_elem *insn_elem)
668
{
669
  return join_c_conditions (XSTR (ce_elem->data, 1),
670
                            XSTR (insn_elem->data, 2));
671
}
672
 
673
/* Adjust all of the operand numbers in SRC to match the shift they'll
674
   get from an operand displacement of DISP.  Return a pointer after the
675
   adjusted string.  */
676
 
677
static char *
678
shift_output_template (char *dest, const char *src, int disp)
679
{
680
  while (*src)
681
    {
682
      char c = *src++;
683
      *dest++ = c;
684
      if (c == '%')
685
        {
686
          c = *src++;
687
          if (ISDIGIT ((unsigned char) c))
688
            c += disp;
689
          else if (ISALPHA (c))
690
            {
691
              *dest++ = c;
692
              c = *src++ + disp;
693
            }
694
          *dest++ = c;
695
        }
696
    }
697
 
698
  return dest;
699
}
700
 
701
static const char *
702
alter_output_for_insn (struct queue_elem *ce_elem,
703
                       struct queue_elem *insn_elem,
704
                       int alt, int max_op)
705
{
706
  const char *ce_out, *insn_out;
707
  char *result, *p;
708
  size_t len, ce_len, insn_len;
709
 
710
  /* ??? Could coordinate with genoutput to not duplicate code here.  */
711
 
712
  ce_out = XSTR (ce_elem->data, 2);
713
  insn_out = XTMPL (insn_elem->data, 3);
714
  if (!ce_out || *ce_out == '\0')
715
    return insn_out;
716
 
717
  ce_len = strlen (ce_out);
718
  insn_len = strlen (insn_out);
719
 
720
  if (*insn_out == '*')
721
    /* You must take care of the predicate yourself.  */
722
    return insn_out;
723
 
724
  if (*insn_out == '@')
725
    {
726
      len = (ce_len + 1) * alt + insn_len + 1;
727
      p = result = XNEWVEC(char, len);
728
 
729
      do
730
        {
731
          do
732
            *p++ = *insn_out++;
733
          while (ISSPACE ((unsigned char) *insn_out));
734
 
735
          if (*insn_out != '#')
736
            {
737
              p = shift_output_template (p, ce_out, max_op);
738
              *p++ = ' ';
739
            }
740
 
741
          do
742
            *p++ = *insn_out++;
743
          while (*insn_out && *insn_out != '\n');
744
        }
745
      while (*insn_out);
746
      *p = '\0';
747
    }
748
  else
749
    {
750
      len = ce_len + 1 + insn_len + 1;
751
      result = XNEWVEC (char, len);
752
 
753
      p = shift_output_template (result, ce_out, max_op);
754
      *p++ = ' ';
755
      memcpy (p, insn_out, insn_len + 1);
756
    }
757
 
758
  return result;
759
}
760
 
761
/* Replicate insns as appropriate for the given DEFINE_COND_EXEC.  */
762
 
763
static void
764
process_one_cond_exec (struct queue_elem *ce_elem)
765
{
766
  struct queue_elem *insn_elem;
767
  for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
768
    {
769
      int alternatives, max_operand;
770
      rtx pred, insn, pattern, split;
771
      int i;
772
 
773
      if (! is_predicable (insn_elem))
774
        continue;
775
 
776
      alternatives = 1;
777
      max_operand = -1;
778
      collect_insn_data (insn_elem->data, &alternatives, &max_operand);
779
      max_operand += 1;
780
 
781
      if (XVECLEN (ce_elem->data, 0) != 1)
782
        {
783
          message_with_line (ce_elem->lineno,
784
                             "too many patterns in predicate");
785
          errors = 1;
786
          return;
787
        }
788
 
789
      pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
790
      pred = alter_predicate_for_insn (pred, alternatives, max_operand,
791
                                       ce_elem->lineno);
792
      if (pred == NULL)
793
        return;
794
 
795
      /* Construct a new pattern for the new insn.  */
796
      insn = copy_rtx (insn_elem->data);
797
      XSTR (insn, 0) = "";
798
      pattern = rtx_alloc (COND_EXEC);
799
      XEXP (pattern, 0) = pred;
800
      if (XVECLEN (insn, 1) == 1)
801
        {
802
          XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
803
          XVECEXP (insn, 1, 0) = pattern;
804
          PUT_NUM_ELEM (XVEC (insn, 1), 1);
805
        }
806
      else
807
        {
808
          XEXP (pattern, 1) = rtx_alloc (PARALLEL);
809
          XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
810
          XVEC (insn, 1) = rtvec_alloc (1);
811
          XVECEXP (insn, 1, 0) = pattern;
812
        }
813
 
814
      XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
815
      XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
816
                                              alternatives, max_operand);
817
 
818
      /* ??? Set `predicable' to false.  Not crucial since it's really
819
         only used here, and we won't reprocess this new pattern.  */
820
 
821
      /* Put the new pattern on the `other' list so that it
822
         (a) is not reprocessed by other define_cond_exec patterns
823
         (b) appears after all normal define_insn patterns.
824
 
825
         ??? B is debatable.  If one has normal insns that match
826
         cond_exec patterns, they will be preferred over these
827
         generated patterns.  Whether this matters in practice, or if
828
         it's a good thing, or whether we should thread these new
829
         patterns into the define_insn chain just after their generator
830
         is something we'll have to experiment with.  */
831
 
832
      queue_pattern (insn, &other_tail, insn_elem->filename,
833
                     insn_elem->lineno);
834
 
835
      if (!insn_elem->split)
836
        continue;
837
 
838
      /* If the original insn came from a define_insn_and_split,
839
         generate a new split to handle the predicated insn.  */
840
      split = copy_rtx (insn_elem->split->data);
841
      /* Predicate the pattern matched by the split.  */
842
      pattern = rtx_alloc (COND_EXEC);
843
      XEXP (pattern, 0) = pred;
844
      if (XVECLEN (split, 0) == 1)
845
        {
846
          XEXP (pattern, 1) = XVECEXP (split, 0, 0);
847
          XVECEXP (split, 0, 0) = pattern;
848
          PUT_NUM_ELEM (XVEC (split, 0), 1);
849
        }
850
      else
851
        {
852
          XEXP (pattern, 1) = rtx_alloc (PARALLEL);
853
          XVEC (XEXP (pattern, 1), 0) = XVEC (split, 0);
854
          XVEC (split, 0) = rtvec_alloc (1);
855
          XVECEXP (split, 0, 0) = pattern;
856
        }
857
      /* Predicate all of the insns generated by the split.  */
858
      for (i = 0; i < XVECLEN (split, 2); i++)
859
        {
860
          pattern = rtx_alloc (COND_EXEC);
861
          XEXP (pattern, 0) = pred;
862
          XEXP (pattern, 1) = XVECEXP (split, 2, i);
863
          XVECEXP (split, 2, i) = pattern;
864
        }
865
      /* Add the new split to the queue.  */
866
      queue_pattern (split, &other_tail, read_rtx_filename,
867
                     insn_elem->split->lineno);
868
    }
869
}
870
 
871
/* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
872
   patterns appropriately.  */
873
 
874
static void
875
process_define_cond_exec (void)
876
{
877
  struct queue_elem *elem;
878
 
879
  identify_predicable_attribute ();
880
  if (errors)
881
    return;
882
 
883
  for (elem = define_cond_exec_queue; elem ; elem = elem->next)
884
    process_one_cond_exec (elem);
885
}
886
 
887
static char *
888
save_string (const char *s, int len)
889
{
890
  char *result = XNEWVEC (char, len + 1);
891
 
892
  memcpy (result, s, len);
893
  result[len] = 0;
894
  return result;
895
}
896
 
897
 
898
/* The entry point for initializing the reader.  */
899
 
900
int
901
init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *))
902
{
903
  FILE *input_file;
904
  int i, lineno;
905
  size_t ix;
906
  char *lastsl;
907
  rtx desc;
908
 
909
  /* Unlock the stdio streams.  */
910
  unlock_std_streams ();
911
 
912
  for (i = 1; i < argc; i++)
913
    {
914
      if (argv[i][0] != '-')
915
        {
916
          if (in_fname)
917
            fatal ("too many input files");
918
 
919
          in_fname = argv[i];
920
        }
921
      else
922
        {
923
          int c = argv[i][1];
924
          switch (c)
925
            {
926
            case 'I':           /* Add directory to path for includes.  */
927
              {
928
                struct file_name_list *dirtmp;
929
 
930
                dirtmp = XNEW (struct file_name_list);
931
                dirtmp->next = 0;        /* New one goes on the end */
932
                if (first_dir_md_include == 0)
933
                  first_dir_md_include = dirtmp;
934
                else
935
                  last_dir_md_include->next = dirtmp;
936
                last_dir_md_include = dirtmp;   /* Tail follows the last one */
937
                if (argv[i][1] == 'I' && argv[i][2] != 0)
938
                  dirtmp->fname = argv[i] + 2;
939
                else if (i + 1 == argc)
940
                  fatal ("directory name missing after -I option");
941
                else
942
                  dirtmp->fname = argv[++i];
943
                if (strlen (dirtmp->fname) > max_include_len)
944
                  max_include_len = strlen (dirtmp->fname);
945
              }
946
              break;
947
            default:
948
              /* The program may have provided a callback so it can
949
                 accept its own options.  */
950
              if (parse_opt && parse_opt (argv[i]))
951
                break;
952
 
953
              fatal ("invalid option `%s'", argv[i]);
954
            }
955
        }
956
    }
957
 
958
  if (!in_fname)
959
    fatal ("no input file name");
960
 
961
  lastsl = strrchr (in_fname, '/');
962
  if (lastsl != NULL)
963
    base_dir = save_string (in_fname, lastsl - in_fname + 1 );
964
 
965
  read_rtx_filename = in_fname;
966
  input_file = fopen (in_fname, "r");
967
  if (input_file == 0)
968
    {
969
      perror (in_fname);
970
      return FATAL_EXIT_CODE;
971
    }
972
 
973
  /* Initialize the table of insn conditions.  */
974
  condition_table = htab_create (n_insn_conditions,
975
                                 hash_c_test, cmp_c_test, NULL);
976
 
977
  for (ix = 0; ix < n_insn_conditions; ix++)
978
    *(htab_find_slot (condition_table, &insn_conditions[ix], INSERT))
979
      = (void *) &insn_conditions[ix];
980
 
981
  init_predicate_table ();
982
 
983
  obstack_init (rtl_obstack);
984
  errors = 0;
985
  sequence_num = 0;
986
 
987
  /* Read the entire file.  */
988
  while (read_rtx (input_file, &desc, &lineno))
989
    process_rtx (desc, lineno);
990
  fclose (input_file);
991
 
992
  /* Process define_cond_exec patterns.  */
993
  if (define_cond_exec_queue != NULL)
994
    process_define_cond_exec ();
995
 
996
  return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
997
}
998
 
999
/* Programs that don't have their own options can use this entry point
1000
   instead.  */
1001
int
1002
init_md_reader_args (int argc, char **argv)
1003
{
1004
  return init_md_reader_args_cb (argc, argv, 0);
1005
}
1006
 
1007
/* The entry point for reading a single rtx from an md file.  */
1008
 
1009
rtx
1010
read_md_rtx (int *lineno, int *seqnr)
1011
{
1012
  struct queue_elem **queue, *elem;
1013
  rtx desc;
1014
 
1015
 discard:
1016
 
1017
  /* Read all patterns from a given queue before moving on to the next.  */
1018
  if (define_attr_queue != NULL)
1019
    queue = &define_attr_queue;
1020
  else if (define_pred_queue != NULL)
1021
    queue = &define_pred_queue;
1022
  else if (define_insn_queue != NULL)
1023
    queue = &define_insn_queue;
1024
  else if (other_queue != NULL)
1025
    queue = &other_queue;
1026
  else
1027
    return NULL_RTX;
1028
 
1029
  elem = *queue;
1030
  *queue = elem->next;
1031
  desc = elem->data;
1032
  read_rtx_filename = elem->filename;
1033
  *lineno = elem->lineno;
1034
  *seqnr = sequence_num;
1035
 
1036
  free (elem);
1037
 
1038
  /* Discard insn patterns which we know can never match (because
1039
     their C test is provably always false).  If insn_elision is
1040
     false, our caller needs to see all the patterns.  Note that the
1041
     elided patterns are never counted by the sequence numbering; it
1042
     it is the caller's responsibility, when insn_elision is false, not
1043
     to use elided pattern numbers for anything.  */
1044
  switch (GET_CODE (desc))
1045
    {
1046
    case DEFINE_INSN:
1047
    case DEFINE_EXPAND:
1048
      if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
1049
        sequence_num++;
1050
      else if (insn_elision)
1051
        goto discard;
1052
      break;
1053
 
1054
    case DEFINE_SPLIT:
1055
    case DEFINE_PEEPHOLE:
1056
    case DEFINE_PEEPHOLE2:
1057
      if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
1058
        sequence_num++;
1059
      else if (insn_elision)
1060
            goto discard;
1061
      break;
1062
 
1063
    default:
1064
      break;
1065
    }
1066
 
1067
  return desc;
1068
}
1069
 
1070
/* Helper functions for insn elision.  */
1071
 
1072
/* Compute a hash function of a c_test structure, which is keyed
1073
   by its ->expr field.  */
1074
hashval_t
1075
hash_c_test (const void *x)
1076
{
1077
  const struct c_test *a = (const struct c_test *) x;
1078
  const unsigned char *base, *s = (const unsigned char *) a->expr;
1079
  hashval_t hash;
1080
  unsigned char c;
1081
  unsigned int len;
1082
 
1083
  base = s;
1084
  hash = 0;
1085
 
1086
  while ((c = *s++) != '\0')
1087
    {
1088
      hash += c + (c << 17);
1089
      hash ^= hash >> 2;
1090
    }
1091
 
1092
  len = s - base;
1093
  hash += len + (len << 17);
1094
  hash ^= hash >> 2;
1095
 
1096
  return hash;
1097
}
1098
 
1099
/* Compare two c_test expression structures.  */
1100
int
1101
cmp_c_test (const void *x, const void *y)
1102
{
1103
  const struct c_test *a = (const struct c_test *) x;
1104
  const struct c_test *b = (const struct c_test *) y;
1105
 
1106
  return !strcmp (a->expr, b->expr);
1107
}
1108
 
1109
/* Given a string representing a C test expression, look it up in the
1110
   condition_table and report whether or not its value is known
1111
   at compile time.  Returns a tristate: 1 for known true, 0 for
1112
   known false, -1 for unknown.  */
1113
int
1114
maybe_eval_c_test (const char *expr)
1115
{
1116
  const struct c_test *test;
1117
  struct c_test dummy;
1118
 
1119
  if (expr[0] == 0)
1120
    return 1;
1121
 
1122
  if (insn_elision_unavailable)
1123
    return -1;
1124
 
1125
  dummy.expr = expr;
1126
  test = (const struct c_test *)htab_find (condition_table, &dummy);
1127
  gcc_assert (test);
1128
 
1129
  return test->value;
1130
}
1131
 
1132
/* Given a string, return the number of comma-separated elements in it.
1133
   Return 0 for the null string.  */
1134
int
1135
n_comma_elts (const char *s)
1136
{
1137
  int n;
1138
 
1139
  if (*s == '\0')
1140
    return 0;
1141
 
1142
  for (n = 1; *s; s++)
1143
    if (*s == ',')
1144
      n++;
1145
 
1146
  return n;
1147
}
1148
 
1149
/* Given a pointer to a (char *), return a pointer to the beginning of the
1150
   next comma-separated element in the string.  Advance the pointer given
1151
   to the end of that element.  Return NULL if at end of string.  Caller
1152
   is responsible for copying the string if necessary.  White space between
1153
   a comma and an element is ignored.  */
1154
 
1155
const char *
1156
scan_comma_elt (const char **pstr)
1157
{
1158
  const char *start;
1159
  const char *p = *pstr;
1160
 
1161
  if (*p == ',')
1162
    p++;
1163
  while (ISSPACE(*p))
1164
    p++;
1165
 
1166
  if (*p == '\0')
1167
    return NULL;
1168
 
1169
  start = p;
1170
 
1171
  while (*p != ',' && *p != '\0')
1172
    p++;
1173
 
1174
  *pstr = p;
1175
  return start;
1176
}
1177
 
1178
/* Helper functions for define_predicate and define_special_predicate
1179
   processing.  Shared between genrecog.c and genpreds.c.  */
1180
 
1181
static htab_t predicate_table;
1182
struct pred_data *first_predicate;
1183
static struct pred_data **last_predicate = &first_predicate;
1184
 
1185
static hashval_t
1186
hash_struct_pred_data (const void *ptr)
1187
{
1188
  return htab_hash_string (((const struct pred_data *)ptr)->name);
1189
}
1190
 
1191
static int
1192
eq_struct_pred_data (const void *a, const void *b)
1193
{
1194
  return !strcmp (((const struct pred_data *)a)->name,
1195
                  ((const struct pred_data *)b)->name);
1196
}
1197
 
1198
struct pred_data *
1199
lookup_predicate (const char *name)
1200
{
1201
  struct pred_data key;
1202
  key.name = name;
1203
  return htab_find (predicate_table, &key);
1204
}
1205
 
1206
void
1207
add_predicate (struct pred_data *pred)
1208
{
1209
  void **slot = htab_find_slot (predicate_table, pred, INSERT);
1210
  if (*slot)
1211
    {
1212
      error ("duplicate predicate definition for '%s'", pred->name);
1213
      return;
1214
    }
1215
  *slot = pred;
1216
  *last_predicate = pred;
1217
  last_predicate = &pred->next;
1218
}
1219
 
1220
/* This array gives the initial content of the predicate table.  It
1221
   has entries for all predicates defined in recog.c.  */
1222
 
1223
struct old_pred_table
1224
{
1225
  const char *name;
1226
  RTX_CODE codes[NUM_RTX_CODE];
1227
};
1228
 
1229
static const struct old_pred_table old_preds[] = {
1230
  {"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1231
                       LABEL_REF, SUBREG, REG, MEM }},
1232
  {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1233
                       LABEL_REF, SUBREG, REG, MEM,
1234
                       PLUS, MINUS, MULT}},
1235
  {"register_operand", {SUBREG, REG}},
1236
  {"pmode_register_operand", {SUBREG, REG}},
1237
  {"scratch_operand", {SCRATCH, REG}},
1238
  {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1239
                         LABEL_REF}},
1240
  {"const_int_operand", {CONST_INT}},
1241
  {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
1242
  {"nonimmediate_operand", {SUBREG, REG, MEM}},
1243
  {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
1244
                         LABEL_REF, SUBREG, REG}},
1245
  {"push_operand", {MEM}},
1246
  {"pop_operand", {MEM}},
1247
  {"memory_operand", {SUBREG, MEM}},
1248
  {"indirect_operand", {SUBREG, MEM}},
1249
  {"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU,
1250
                           UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
1251
                           UNLT, LTGT}}
1252
};
1253
#define NUM_KNOWN_OLD_PREDS ARRAY_SIZE (old_preds)
1254
 
1255
/* This table gives the set of special predicates.  It has entries for
1256
   all special predicates defined in recog.c.  */
1257
static const char *const old_special_pred_table[] = {
1258
  "address_operand",
1259
  "pmode_register_operand",
1260
};
1261
 
1262
#define NUM_OLD_SPECIAL_MODE_PREDS ARRAY_SIZE (old_special_pred_table)
1263
 
1264
/* Initialize the table of predicate definitions, starting with
1265
   the information we have on generic predicates.  */
1266
 
1267
static void
1268
init_predicate_table (void)
1269
{
1270
  size_t i, j;
1271
  struct pred_data *pred;
1272
 
1273
  predicate_table = htab_create_alloc (37, hash_struct_pred_data,
1274
                                       eq_struct_pred_data, 0,
1275
                                       xcalloc, free);
1276
 
1277
  for (i = 0; i < NUM_KNOWN_OLD_PREDS; i++)
1278
    {
1279
      pred = xcalloc (sizeof (struct pred_data), 1);
1280
      pred->name = old_preds[i].name;
1281
 
1282
      for (j = 0; old_preds[i].codes[j] != 0; j++)
1283
        {
1284
          enum rtx_code code = old_preds[i].codes[j];
1285
 
1286
          pred->codes[code] = true;
1287
          if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
1288
            pred->allows_non_const = true;
1289
          if (code != REG
1290
              && code != SUBREG
1291
              && code != MEM
1292
              && code != CONCAT
1293
              && code != PARALLEL
1294
              && code != STRICT_LOW_PART)
1295
            pred->allows_non_lvalue = true;
1296
        }
1297
      if (j == 1)
1298
        pred->singleton = old_preds[i].codes[0];
1299
 
1300
      add_predicate (pred);
1301
    }
1302
 
1303
  for (i = 0; i < NUM_OLD_SPECIAL_MODE_PREDS; i++)
1304
    {
1305
      pred = lookup_predicate (old_special_pred_table[i]);
1306
      if (!pred)
1307
        {
1308
          error ("old-style special predicate list refers "
1309
                 "to unknown predicate '%s'", old_special_pred_table[i]);
1310
          continue;
1311
        }
1312
      pred->special = true;
1313
    }
1314
}

powered by: WebSVN 2.1.0

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