Mercurial > hg > CbC > CbC_gcc
annotate gcc/genconfig.c @ 56:3c8a44c06a95
Added tag gcc-4.4.5 for changeset 77e2b8dfacca
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:41:23 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
rev | line source |
---|---|
0 | 1 /* Generate from machine description: |
2 - some #define configuration flags. | |
3 Copyright (C) 1987, 1991, 1997, 1998, 1999, 2000, 2003, 2004, 2007 | |
4 Free Software Foundation, Inc. | |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
22 | |
23 #include "bconfig.h" | |
24 #include "system.h" | |
25 #include "coretypes.h" | |
26 #include "tm.h" | |
27 #include "rtl.h" | |
28 #include "errors.h" | |
29 #include "gensupport.h" | |
30 | |
31 | |
32 /* flags to determine output of machine description dependent #define's. */ | |
33 static int max_recog_operands; /* Largest operand number seen. */ | |
34 static int max_dup_operands; /* Largest number of match_dup in any insn. */ | |
35 static int max_clobbers_per_insn; | |
36 static int have_cc0_flag; | |
37 static int have_cmove_flag; | |
38 static int have_cond_exec_flag; | |
39 static int have_lo_sum_flag; | |
40 static int have_peephole_flag; | |
41 static int have_peephole2_flag; | |
42 | |
43 /* Maximum number of insns seen in a split. */ | |
44 static int max_insns_per_split = 1; | |
45 | |
46 /* Maximum number of input insns for peephole2. */ | |
47 static int max_insns_per_peep2; | |
48 | |
49 static int clobbers_seen_this_insn; | |
50 static int dup_operands_seen_this_insn; | |
51 | |
52 static void walk_insn_part (rtx, int, int); | |
53 static void gen_insn (rtx); | |
54 static void gen_expand (rtx); | |
55 static void gen_split (rtx); | |
56 static void gen_peephole (rtx); | |
57 static void gen_peephole2 (rtx); | |
58 | |
59 /* RECOG_P will be nonzero if this pattern was seen in a context where it will | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
60 be used to recognize, rather than just generate an insn. |
0 | 61 |
62 NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC | |
63 of a SET whose destination is not (pc). */ | |
64 | |
65 static void | |
66 walk_insn_part (rtx part, int recog_p, int non_pc_set_src) | |
67 { | |
68 int i, j; | |
69 RTX_CODE code; | |
70 const char *format_ptr; | |
71 | |
72 if (part == 0) | |
73 return; | |
74 | |
75 code = GET_CODE (part); | |
76 switch (code) | |
77 { | |
78 case CLOBBER: | |
79 clobbers_seen_this_insn++; | |
80 break; | |
81 | |
82 case MATCH_OPERAND: | |
83 if (XINT (part, 0) > max_recog_operands) | |
84 max_recog_operands = XINT (part, 0); | |
85 return; | |
86 | |
87 case MATCH_OP_DUP: | |
88 case MATCH_PAR_DUP: | |
89 ++dup_operands_seen_this_insn; | |
90 case MATCH_SCRATCH: | |
91 case MATCH_PARALLEL: | |
92 case MATCH_OPERATOR: | |
93 if (XINT (part, 0) > max_recog_operands) | |
94 max_recog_operands = XINT (part, 0); | |
95 /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or | |
96 MATCH_PARALLEL. */ | |
97 break; | |
98 | |
99 case LABEL_REF: | |
100 if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND | |
101 || GET_CODE (XEXP (part, 0)) == MATCH_DUP) | |
102 break; | |
103 return; | |
104 | |
105 case MATCH_DUP: | |
106 ++dup_operands_seen_this_insn; | |
107 if (XINT (part, 0) > max_recog_operands) | |
108 max_recog_operands = XINT (part, 0); | |
109 return; | |
110 | |
111 case CC0: | |
112 if (recog_p) | |
113 have_cc0_flag = 1; | |
114 return; | |
115 | |
116 case LO_SUM: | |
117 if (recog_p) | |
118 have_lo_sum_flag = 1; | |
119 return; | |
120 | |
121 case SET: | |
122 walk_insn_part (SET_DEST (part), 0, recog_p); | |
123 walk_insn_part (SET_SRC (part), recog_p, | |
124 GET_CODE (SET_DEST (part)) != PC); | |
125 return; | |
126 | |
127 case IF_THEN_ELSE: | |
128 /* Only consider this machine as having a conditional move if the | |
129 two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise, | |
130 we have some specific IF_THEN_ELSE construct (like the doz | |
131 instruction on the RS/6000) that can't be used in the general | |
132 context we want it for. */ | |
133 | |
134 if (recog_p && non_pc_set_src | |
135 && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND | |
136 && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) | |
137 have_cmove_flag = 1; | |
138 break; | |
139 | |
140 case COND_EXEC: | |
141 if (recog_p) | |
142 have_cond_exec_flag = 1; | |
143 break; | |
144 | |
145 case REG: case CONST_INT: case SYMBOL_REF: | |
146 case PC: | |
147 return; | |
148 | |
149 default: | |
150 break; | |
151 } | |
152 | |
153 format_ptr = GET_RTX_FORMAT (GET_CODE (part)); | |
154 | |
155 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) | |
156 switch (*format_ptr++) | |
157 { | |
158 case 'e': | |
159 case 'u': | |
160 walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src); | |
161 break; | |
162 case 'E': | |
163 if (XVEC (part, i) != NULL) | |
164 for (j = 0; j < XVECLEN (part, i); j++) | |
165 walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src); | |
166 break; | |
167 } | |
168 } | |
169 | |
170 static void | |
171 gen_insn (rtx insn) | |
172 { | |
173 int i; | |
174 | |
175 /* Walk the insn pattern to gather the #define's status. */ | |
176 clobbers_seen_this_insn = 0; | |
177 dup_operands_seen_this_insn = 0; | |
178 if (XVEC (insn, 1) != 0) | |
179 for (i = 0; i < XVECLEN (insn, 1); i++) | |
180 walk_insn_part (XVECEXP (insn, 1, i), 1, 0); | |
181 | |
182 if (clobbers_seen_this_insn > max_clobbers_per_insn) | |
183 max_clobbers_per_insn = clobbers_seen_this_insn; | |
184 if (dup_operands_seen_this_insn > max_dup_operands) | |
185 max_dup_operands = dup_operands_seen_this_insn; | |
186 } | |
187 | |
188 /* Similar but scan a define_expand. */ | |
189 | |
190 static void | |
191 gen_expand (rtx insn) | |
192 { | |
193 int i; | |
194 | |
195 /* Walk the insn pattern to gather the #define's status. */ | |
196 | |
197 /* Note that we don't bother recording the number of MATCH_DUPs | |
198 that occur in a gen_expand, because only reload cares about that. */ | |
199 if (XVEC (insn, 1) != 0) | |
200 for (i = 0; i < XVECLEN (insn, 1); i++) | |
201 { | |
202 /* Compute the maximum SETs and CLOBBERS | |
203 in any one of the sub-insns; | |
204 don't sum across all of them. */ | |
205 clobbers_seen_this_insn = 0; | |
206 | |
207 walk_insn_part (XVECEXP (insn, 1, i), 0, 0); | |
208 | |
209 if (clobbers_seen_this_insn > max_clobbers_per_insn) | |
210 max_clobbers_per_insn = clobbers_seen_this_insn; | |
211 } | |
212 } | |
213 | |
214 /* Similar but scan a define_split. */ | |
215 | |
216 static void | |
217 gen_split (rtx split) | |
218 { | |
219 int i; | |
220 | |
221 /* Look through the patterns that are matched | |
222 to compute the maximum operand number. */ | |
223 for (i = 0; i < XVECLEN (split, 0); i++) | |
224 walk_insn_part (XVECEXP (split, 0, i), 1, 0); | |
225 /* Look at the number of insns this insn could split into. */ | |
226 if (XVECLEN (split, 2) > max_insns_per_split) | |
227 max_insns_per_split = XVECLEN (split, 2); | |
228 } | |
229 | |
230 static void | |
231 gen_peephole (rtx peep) | |
232 { | |
233 int i; | |
234 | |
235 /* Look through the patterns that are matched | |
236 to compute the maximum operand number. */ | |
237 for (i = 0; i < XVECLEN (peep, 0); i++) | |
238 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); | |
239 } | |
240 | |
241 static void | |
242 gen_peephole2 (rtx peep) | |
243 { | |
244 int i, n; | |
245 | |
246 /* Look through the patterns that are matched | |
247 to compute the maximum operand number. */ | |
248 for (i = XVECLEN (peep, 0) - 1; i >= 0; --i) | |
249 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); | |
250 | |
251 /* Look at the number of insns this insn can be matched from. */ | |
252 for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i) | |
253 if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP | |
254 && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH) | |
255 n++; | |
256 if (n > max_insns_per_peep2) | |
257 max_insns_per_peep2 = n; | |
258 } | |
259 | |
260 int | |
261 main (int argc, char **argv) | |
262 { | |
263 rtx desc; | |
264 | |
265 progname = "genconfig"; | |
266 | |
267 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) | |
268 return (FATAL_EXIT_CODE); | |
269 | |
270 puts ("/* Generated automatically by the program `genconfig'"); | |
271 puts (" from the machine description file `md'. */\n"); | |
272 puts ("#ifndef GCC_INSN_CONFIG_H"); | |
273 puts ("#define GCC_INSN_CONFIG_H\n"); | |
274 | |
275 /* Allow at least 30 operands for the sake of asm constructs. */ | |
276 /* ??? We *really* ought to reorganize things such that there | |
277 is no fixed upper bound. */ | |
278 max_recog_operands = 29; /* We will add 1 later. */ | |
279 max_dup_operands = 1; | |
280 | |
281 /* Read the machine description. */ | |
282 | |
283 while (1) | |
284 { | |
285 int line_no, insn_code_number = 0; | |
286 | |
287 desc = read_md_rtx (&line_no, &insn_code_number); | |
288 if (desc == NULL) | |
289 break; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
290 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
291 switch (GET_CODE (desc)) |
0 | 292 { |
293 case DEFINE_INSN: | |
294 gen_insn (desc); | |
295 break; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
296 |
0 | 297 case DEFINE_EXPAND: |
298 gen_expand (desc); | |
299 break; | |
300 | |
301 case DEFINE_SPLIT: | |
302 gen_split (desc); | |
303 break; | |
304 | |
305 case DEFINE_PEEPHOLE2: | |
306 have_peephole2_flag = 1; | |
307 gen_peephole2 (desc); | |
308 break; | |
309 | |
310 case DEFINE_PEEPHOLE: | |
311 have_peephole_flag = 1; | |
312 gen_peephole (desc); | |
313 break; | |
314 | |
315 default: | |
316 break; | |
317 } | |
318 } | |
319 | |
320 printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1); | |
321 printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands); | |
322 | |
323 /* This is conditionally defined, in case the user writes code which emits | |
324 more splits than we can readily see (and knows s/he does it). */ | |
325 printf ("#ifndef MAX_INSNS_PER_SPLIT\n"); | |
326 printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split); | |
327 printf ("#endif\n"); | |
328 | |
329 if (have_cc0_flag) | |
330 { | |
331 printf ("#define HAVE_cc0 1\n"); | |
332 printf ("#define CC0_P(X) ((X) == cc0_rtx)\n"); | |
333 } | |
334 else | |
335 { | |
336 /* We output CC0_P this way to make sure that X is declared | |
337 somewhere. */ | |
338 printf ("#define CC0_P(X) ((X) ? 0 : 0)\n"); | |
339 } | |
340 | |
341 if (have_cmove_flag) | |
342 printf ("#define HAVE_conditional_move 1\n"); | |
343 | |
344 if (have_cond_exec_flag) | |
345 printf ("#define HAVE_conditional_execution 1\n"); | |
346 | |
347 if (have_lo_sum_flag) | |
348 printf ("#define HAVE_lo_sum 1\n"); | |
349 | |
350 if (have_peephole_flag) | |
351 printf ("#define HAVE_peephole 1\n"); | |
352 | |
353 if (have_peephole2_flag) | |
354 { | |
355 printf ("#define HAVE_peephole2 1\n"); | |
356 printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2); | |
357 } | |
358 | |
359 puts("\n#endif /* GCC_INSN_CONFIG_H */"); | |
360 | |
361 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) | |
362 return FATAL_EXIT_CODE; | |
363 | |
364 return SUCCESS_EXIT_CODE; | |
365 } |