GCC后端及汇编发布(42)
来源:互联网 发布:知鸟论文检测系统 编辑:程序博客网 时间:2024/06/06 16:56
12. genflags工具
这个工具将输出insn-flags,由genemit生成的函数,以及一系列包含define_insn及define_expand模式的条件模板的HAVE_*宏将被声明在其中。
233 int
234 main (int argc, char **argv) ingenflags.c
235 {
236 rtx desc;
237 rtx dummy;
238 rtx *insns;
239 rtx *insn_ptr;
240
241 progname= "genflags";
242 obstack_init (&obstack);
243
244 /* We need to see all the possibilities.Elided insns may have
245 direct calls to their generators in Ccode. */
246 insn_elision= 0;
247
248 if (argc <= 1)
249 fatal ("no input file name");
250
251 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
252 return (FATAL_EXIT_CODE);
253
254 puts ("/* Generated automatically by the program `genflags'");
255 puts (" from the machine descriptionfile `md'. */\n");
256 puts ("#ifndef GCC_INSN_FLAGS_H");
257 puts ("#define GCC_INSN_FLAGS_H\n");
258
259 /* Read the machine description. */
260
261 while (1)
262 {
263 int line_no, insn_code_number = 0;
264
265 desc = read_md_rtx (&line_no,&insn_code_number);
266 if (desc == NULL)
267 break;
268 if (GET_CODE (desc) ==DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
269 gen_insn (desc);
270 }
271
272 /* Print out the prototypes now. */
273 dummy = (rtx) 0;
274 obstack_grow (&obstack, &dummy, sizeof(rtx));
275 insns = (rtx *) obstack_finish (&obstack);
276
277 for(insn_ptr = insns; *insn_ptr; insn_ptr++)
278 gen_proto (*insn_ptr);
279
280 puts("\n#endif /*GCC_INSN_FLAGS_H */");
281
282 if (ferror (stdout) || fflush (stdout) || fclose (stdout))
283 return FATAL_EXIT_CODE;
284
285 return SUCCESS_EXIT_CODE;
286 }
正如我们从其他章节中看到的,init_md_reader_args以及read_md_rtx从机器描述文件读入模式(pattern),并构建相应的,由desc所指向的rtx对象。这个对象由gen_insn来处理。
192 static void
193 gen_insn (rtx insn) ingenflags.c
194 {
195 const char *name = XSTR (insn, 0);
196 const char *p;
197 int len;
198 int truth = maybe_eval_c_test (XSTR(insn, 2));
199
200 /* Don't mention instructions whose names arethe null string
201 or begin with '*'. They are in the machinedescription just
202 to be recognized. */
203 if (name[0] == 0 || name[0] == '*')
204 return;
205
206 len = strlen (name);
207
208 if (len > max_id_len)
209 max_id_len= len;
210
211 if (truth == 0)
212 /* Emit nothing. */;
213 else if (truth == 1)
214 printf ("#define HAVE_%s 1\n", name);
215 else
216 {
217 /* Write the macro definition, putting \'s atthe end of each line,
218 if more than one. */
219 printf ("#define HAVE_%s (", name);
220 for(p = XSTR (insn, 2); *p; p++)
221 {
222 if (IS_VSPACE (*p))
223 fputs (" \\\n", stdout);
224 else
225 putchar (*p);
226 }
227 fputs (")\n", stdout);
228 }
229
230 obstack_grow (&obstack, &insn, sizeof(rtx));
231 }
我们已经知道,对于在编译时刻已知为true的表达式,maybe_eval_c_test返回1,为false的表达式则返回0,其它则返回-1。注意到在203行,匿名的,或名字以‘*’开头的模式将被忽略。而在230行,合格rtx对象的地址将被保存入obstack。
回到main,在275行,一个空rtx对象被添加到obstack以确保277行的FOR循环能正确退出。对于每个有意义的define_insn或define_expand模式(pattern),gen_proto执行以下处理。
129 static void
130 gen_proto (rtx insn) ingenflags.c
131 {
132 int num = num_operands (insn);
133 int i;
134 const char *name = XSTR (insn, 0);
135 int truth = maybe_eval_c_test (XSTR(insn, 2));
136
137 /* Many md files don't refer to the last twooperands passed to the
138 call patterns. This means their generatorfunctions will be two
139 arguments too short. Instead of changingevery md file to touch
140 those operands, we wrap the prototypes inmacros that take the
141 correct number of arguments. */
142 if (name[0] == 'c' || name[0] == 's')
143 {
144 if (!strcmp (name, "call")
145 || !strcmp (name, "call_pop")
146 || !strcmp (name, "sibcall")
147 || !strcmp (name, "sibcall_pop"))
148 gen_macro (name, num, 4);
149 else if (!strcmp (name, "call_value")
150 || !strcmp (name,"call_value_pop")
151 || !strcmp (name,"sibcall_value")
152 || !strcmp (name,"sibcall_value_pop"))
153 gen_macro (name, num, 5);
154 }
155
156 if (truth != 0)
157 printf ("extern rtx gen_%-*s (", max_id_len, name);
158 else
159 printf ("static inline rtx gen_%-*s (", max_id_len, name);
160
161 if (num == 0)
162 fputs ("void", stdout);
163 else
164 {
165 for(i = 1; i < num; i++)
166 fputs ("rtx, ",stdout);
167
168 fputs ("rtx", stdout);
169 }
170
171 puts (");");
172
173 /* Some back ends want to take the address ofgenerator functions,
174 so we cannot simply use #define for thesedummy definitions. */
175 if (truth == 0)
176 {
177 printf ("static inline rtx\ngen_%s", name);
178 if (num > 0)
179 {
180 putchar ('(');
181 for(i = 0; i < num-1; i++)
182 printf ("rtx %cATTRIBUTE_UNUSED, ", 'a' + i);
183 printf ("rtx %c ATTRIBUTE_UNUSED)\n", 'a' + i);
184 }
185 else
186 puts ("(void)");
187 puts ("{\n return0;\n}");
188 }
189
190 }
可以看到具有名字“call”,“call_pop”,“sibcall”,“sbicall_pop”,“call_value_pop”,“call_value”,“sibcall_value”以及“sibcall_value_pop”的模式(pattern)需要进一步由gen_macro进行如下处理。
100 static void
101 gen_macro (const char *name, int real, intexpect) ingenflags.c
102 {
103 int i;
104
105 if (real > expect)
106 abort ();
107 if (real == 0)
108 abort ();
109
110 /* #define GEN_CALL(A, B, C, D) gen_call((A),(B)) */
111 fputs ("#define GEN_",stdout);
112 for(i = 0; name[i]; i++)
113 putchar (TOUPPER (name[i]));
114
115 putchar('(');
116 for (i = 0; i < expect - 1; i++)
117 printf ("%c, ", i + 'A');
118 printf ("%c) gen_%s (", i + 'A', name);
119
120 for(i = 0; i < real - 1; i++)
121 printf ("(%c), ", i + 'A');
122 printf ("(%c))\n", i + 'A');
123 }
这个函数将为用于上面提及的模式(pattern)的相应的函数产生一个宏。回到gen_proto,从156到169行,输出这些函数的原型。注意到对于在编译时刻已知为false的模式(pattern)的条件模板,其定义也将出现在insn-flags中——175到188行产生这些返回0的函数。
- GCC后端及汇编发布(42)
- GCC后端及汇编发布(1)
- GCC后端及汇编发布(2)
- GCC后端及汇编发布(3)
- GCC后端及汇编发布(4)
- GCC后端及汇编发布(5)
- GCC后端及汇编发布(6)
- GCC后端及汇编发布(7)
- GCC后端及汇编发布(8)
- GCC后端及汇编发布(9)
- GCC后端及汇编发布(10)
- GCC后端及汇编发布(11)
- GCC后端及汇编发布(12)
- GCC后端及汇编发布(13)
- GCC后端及汇编发布(14)
- GCC后端及汇编发布(15)
- GCC后端及汇编发布(16)
- GCC后端及汇编发布(17)
- sqlserver中pivot的使用
- cout和printf的缓冲机制
- 窗里窗外
- COM编程入门第一部分——什么是COM,如何使用COM
- Android开发教程:蓝牙测试
- GCC后端及汇编发布(42)
- android开发环境配置
- GCC's bacl-end & assemble emission (42)
- GCC后端及汇编发布(43)
- Max row size for Sybase
- GCC's bacl-end & assemble emission (43)
- GCC后端及汇编发布(44)
- GCC's bacl-end & assemble emission (44)
- GCC后端及汇编发布(45)