2de3f4481c3a57463f23477b4ae5f50333b541a3
[platform/upstream/gcc.git] / gcc / gensupport.c
1 /* Support routines for the various generation passes.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3
4    This file is part of GNU CC.
5
6    GNU CC is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GNU CC is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GNU CC; see the file COPYING.  If not, write to
18    the Free Software Foundation, 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include "hconfig.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "obstack.h"
25 #include "errors.h"
26 #include "gensupport.h"
27
28
29 static struct obstack obstack;
30 struct obstack *rtl_obstack = &obstack;
31
32 #define obstack_chunk_alloc xmalloc
33 #define obstack_chunk_free free
34
35 static FILE *input_file;
36
37 static int sequence_num;
38
39 struct queue_elem {
40     rtx data;
41     struct queue_elem *next;
42 };
43
44 static struct queue_elem *rtx_ready_queue;
45
46 static void remove_constraints PARAMS ((rtx));
47 static void process_rtx PARAMS ((rtx *));
48 \f
49 void
50 message_with_line VPARAMS ((int lineno, const char *msg, ...))
51 {
52 #ifndef ANSI_PROTOTYPES
53   int lineno;
54   const char *msg;
55 #endif
56   va_list ap;
57
58   VA_START (ap, msg);
59
60 #ifndef ANSI_PROTOTYPES
61   lineno = va_arg (ap, int);
62   msg = va_arg (ap, const char *);
63 #endif
64
65   fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
66   vfprintf (stderr, msg, ap);
67   fputc ('\n', stderr);
68
69   va_end (ap);
70 }
71 \f
72 /* Recursively remove constraints from an rtx.  */
73
74 static void
75 remove_constraints (part)
76      rtx part;
77 {
78   register int i, j;
79   register const char *format_ptr;
80
81   if (part == 0)
82     return;
83
84   if (GET_CODE (part) == MATCH_OPERAND)
85     XSTR (part, 2) = "";
86   else if (GET_CODE (part) == MATCH_SCRATCH)
87     XSTR (part, 1) = "";
88
89   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
90
91   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
92     switch (*format_ptr++)
93       {
94       case 'e':
95       case 'u':
96         remove_constraints (XEXP (part, i));
97         break;
98       case 'E':
99         if (XVEC (part, i) != NULL)
100           for (j = 0; j < XVECLEN (part, i); j++)
101             remove_constraints (XVECEXP (part, i, j));
102         break;
103       }
104 }
105
106 /* Handle any synthetic top level rtx, i.e. anything except:
107        DEFINE_INSN
108        DEFINE_EXPAND
109        DEFINE_SPLIT
110        DEFINE_PEEPHOLE
111        DEFINE_PEEPHOLE2
112        DEFINE_ATTRIBUTE
113        DEFINE_FUNCTION_UNIT
114        DEFINE_ASM_ATTRIBUTES */
115
116 static void
117 process_rtx (desc)
118     rtx* desc;
119 {
120   if (GET_CODE (*desc) == DEFINE_INSN_AND_SPLIT) 
121     {
122       struct queue_elem* elem = xmalloc (sizeof (struct queue_elem));
123       const char *split_cond;
124   
125       /* Create a split with values from the insn_and_split. */
126       rtx split = rtx_alloc (DEFINE_SPLIT);
127       XEXP (split, 0) = copy_rtx (XEXP (*desc, 1));
128       remove_constraints (XEXP (split, 0));
129       split_cond = XSTR (split, 1) = XSTR (*desc, 4);
130   
131       /* If the split condition starts with "&&", append it to the
132          insn condition to create the new split condition.  */
133       if (split_cond[0] == '&' && split_cond[1] == '&')
134         {
135         const char *insn_cond = XSTR (*desc, 2);
136         char *combined = 
137             xmalloc (strlen (insn_cond) + strlen (split_cond) + 1);
138         strcpy (combined, insn_cond);
139         strcat (combined, split_cond);
140         XSTR (split, 1) = combined;
141         }
142   
143       XVEC (split, 2) = XVEC (*desc, 5);
144       XSTR (split, 3) = XSTR (*desc, 6);
145   
146       /* Fix up the DEFINE_INSN.  */
147       PUT_CODE (*desc, DEFINE_INSN);
148       XVEC (*desc, 4) = XVEC (*desc, 7);
149   
150       /* Return the DEFINE_INSN part, and put the DEFINE_SPLIT
151          in the queue.  */
152       elem->next = rtx_ready_queue;
153       elem->data = split;       
154       rtx_ready_queue = elem;  
155     }
156 }
157 \f
158 /* The entry point for initializing the reader.  */
159
160 int 
161 init_md_reader (filename)
162     const char *filename;
163 {
164   read_rtx_filename = filename;
165   input_file = fopen (filename, "r");
166   if (input_file == 0)
167     {
168       perror (filename);
169       return FATAL_EXIT_CODE;
170     }
171
172   obstack_init (rtl_obstack);
173   sequence_num = 0;
174   rtx_ready_queue = NULL; 
175
176   return SUCCESS_EXIT_CODE;
177 }
178
179
180 /* The entry point for reading a single rtx from an md file.  */
181
182 rtx 
183 read_md_rtx (lineno, seqnr)
184     int *lineno;
185     int *seqnr;
186
187   rtx desc;
188
189   if (rtx_ready_queue != NULL) 
190     {
191       desc = rtx_ready_queue->data;
192       rtx_ready_queue = rtx_ready_queue->next;
193     }
194   else 
195     {
196       int c;
197       c = read_skip_spaces (input_file);
198       if (c == EOF)
199         return NULL;
200
201       ungetc (c, input_file);
202       desc = read_rtx (input_file);
203       process_rtx (&desc);
204     }
205   *lineno = read_rtx_lineno;
206   *seqnr = sequence_num;
207   switch (GET_CODE (desc))
208     {
209       case DEFINE_INSN:
210       case DEFINE_EXPAND:
211       case DEFINE_SPLIT:
212       case DEFINE_PEEPHOLE:
213       case DEFINE_PEEPHOLE2:
214         sequence_num++;
215         break;
216
217       default:
218         break;
219     }
220
221   return desc;
222 }