您的位置:首页 > 其它

GCC后端及汇编发布(42)

2011-10-15 08:31 507 查看

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) in
genflags.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的函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: