13. genconfig工具
这个工具将产生诸如“已知最大操作数编号”,“在任一指令中match_dup的最大数目”,“在一个split中已知的最大指令数”等,连同定义来表示是否出现特殊指令的宏,例如HAVE_conditional_move, HAVE_peephole2,到文件insn-config.h
260 int
261 main (int argc, char **argv) ingenconfig.c
262 {
263 rtx desc;
264
265 progname= "genconfig";
266
267 if (argc <= 1)
268 fatal ("no input file name");
269
270 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
271 return (FATAL_EXIT_CODE);
272
273 puts ("/* Generated automatically by the program`genconfig'");
274 puts (" from the machinedescription file `md'. */\n");
275 puts ("#ifndef GCC_INSN_CONFIG_H");
276 puts ("#define GCC_INSN_CONFIG_H\n");
277
278 /* Allow at least 30 operands for the sake ofasm constructs. */
279 /* ??? We *really* ought to reorganize thingssuch that there
280 is no fixed upper bound. */
281 max_recog_operands= 29; /* Wewill add 1 later. */
282 max_dup_operands= 1;
283
284 /* Read the machine description. */
285
286 while (1)
287 {
288 int line_no, insn_code_number = 0;
289
290 desc = read_md_rtx (&line_no,&insn_code_number);
291 if (desc == NULL)
292 break;
293
294 switch (GET_CODE (desc))
295 {
296 case DEFINE_INSN:
297 gen_insn (desc);
298 break;
299
300 case DEFINE_EXPAND:
301 gen_expand (desc);
302 break;
303
304 case DEFINE_SPLIT:
305 gen_split (desc);
306 break;
307
308 case DEFINE_PEEPHOLE2:
309 have_peephole2_flag= 1;
310 gen_peephole2 (desc);
311 break;
312
313 case DEFINE_PEEPHOLE:
314 have_peephole_flag= 1;
315 gen_peephole (desc);
316 break;
317
318 default:
319 break;
320 }
321 }
322
323 printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands+ 1);
324 printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
325
326 /* This is conditionally defined, in case theuser writes code which emits
327 more splits than we can readily see (andknows s/he does it). */
328 printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
329 printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
330 printf ("#endif\n");
331
332 if (have_cc0_flag)
333 {
334 printf ("#define HAVE_cc0 1\n");
335 printf ("#define CC0_P(X) ((X) == cc0_rtx)\n");
336 }
337 else
338 {
339 printf ("#define CC0_P(X) 0\n");
340 }
341
342 if (have_cmove_flag)
343 printf ("#define HAVE_conditional_move 1\n");
344
345 if (have_cond_exec_flag)
346 printf ("#define HAVE_conditional_execution 1\n");
347
348 if (have_lo_sum_flag)
349 printf ("#define HAVE_lo_sum 1\n");
350
351 if (have_peephole_flag)
352 printf ("#define HAVE_peephole 1\n");
353
354 if (have_peephole2_flag)
355 {
356 printf ("#define HAVE_peephole2 1\n");
357 printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
358 }
359
360 puts("\n#endif /* GCC_INSN_CONFIG_H */");
361
362 if (ferror (stdout) || fflush (stdout) || fclose (stdout))
363 return FATAL_EXIT_CODE;
364
365 return SUCCESS_EXIT_CODE;
366 }
仅以gen_insn作为例子,对于其它模式(pattern),其处理函数是类似的。
170 static void
171 gen_insn (rtx insn) in genconfig.c
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 }
我们已经看到define_insn模式的第二个孩子是一个不完整的RTL表达式向量的RTL模板,它显示了这个指令看起来应该像什么。它是不完整的,因为它可能包含了表达式match_operand,match_operator,及match_dup,它们代表了该指令的操作数。为这个向量中的每个项,调用walk_insn_part。
66 static void
67 walk_insn_part (rtx part, int recog_p, int non_pc_set_src) in genconfig.c
68 {
69 int i, j;
70 RTX_CODE code;
71 const char *format_ptr;
72
73 if (part == 0)
74 return;
75
76 code = GET_CODE (part);
77 switch (code)
78 {
79 case CLOBBER:
80 clobbers_seen_this_insn++;
81 break;
82
83 case MATCH_OPERAND:
84 if (XINT (part, 0) > max_recog_operands)
85 max_recog_operands = XINT (part, 0);
86 return;
87
88 case MATCH_OP_DUP:
89 case MATCH_PAR_DUP:
90 ++dup_operands_seen_this_insn;
91 case MATCH_SCRATCH:
92 case MATCH_PARALLEL:
93 case MATCH_OPERATOR:
94 if (XINT (part, 0) > max_recog_operands)
95 max_recog_operands = XINT (part, 0);
96 /* Now scan the rtl's in the vector inside theMATCH_OPERATOR or
97 MATCH_PARALLEL. */
98 break;
99
100 case LABEL_REF:
101 if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND)
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 aconditional move if the
129 two arms of the IF_THEN_ELSE are bothMATCH_OPERAND. Otherwise,
130 we have some specific IF_THEN_ELSEconstruct (like the doz
131 instruction on the RS/6000) that can'tbe 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: caseCONST_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 }
如果该模式(pattern)被发现在一个它通常将被识别,而不是仅产生一个指令的上下文中,参数recog_p将是非0值。而如果这个模式被发现在一个目标不是(PC)的SET的SET_SRC中,参数non_pc_set_src将是非0值。