回到lang_dependent_init,终于看到函数的结尾了,编译器的初始化马上就要完成了。
lang_dependent_init (continue)
4542 /* The following initialization functions need to generate rtl, so
4543 provide a dummy function context for them. */
4544 init_dummy_function_start ();
4545 init_expr_once ();
4546 expand_dummy_function_end ();
4547
4548 /* If dbx symbol table desired, initialize writing it and output the
4549 predefined types. */
4550 timevar_push (TV_SYMOUT);
4551
4552 #ifdef DWARF2_UNWIND_INFO
4553 if (dwarf2out_do_frame ())
4554 dwarf2out_frame_init ();
4555 #endif
4556
4557 /* Now we have the correct original filename, we can initialize
4558 debug output. */
4559 (*debug_hooks->init) (name);
4560
4561 timevar_pop (TV_SYMOUT);
4562
4563 return 1;
4564 }
这里创建伪函数上下文是不必要的,因为我们不需要产生rtl指令(调用emit_insn)。init_expr_once的目的是,找出可以直接在内存中使用的模式,并初始化块移动的optab。为了收集数据,构建了用于测试的SET指令。注意mem及mem1应该被小心选择,在任何机器上,它们都应该至少有一个是有效的,否则可能会得到错误的结果。这里选择的mem及mem1分别是栈指针及栈框指针,分别测试,由它们所引用的内存与相同模式寄存器之间的,存取操作。
232 void
233 init_expr_once (void) in expr.c
234 {
235 rtx insn, pat;
236 enum machine_mode mode;
237 int num_clobbers;
238 rtx mem, mem1;
239 rtx reg;
240
241 /* Try indexing by frame ptr and try by stack ptr.
242 It is known that on the Convex the stack ptr isn't a valid index.
243 With luck, one or the other is valid on any machine. */
244 mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
245 mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
246
247 /* A scratch register we can modify in-place below to avoid
248 useless RTL allocations. */
249 reg = gen_rtx_REG (VOIDmode, -1);
250
251 insn = rtx_alloc (INSN);
252 pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
253 PATTERN (insn) = pat;
254
255 for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
256 mode = (enum machine_mode) ((int) mode + 1))
257 {
258 int regno;
259
260 direct_load[(int) mode] = direct_store[(int) mode] = 0;
261 PUT_MODE (mem, mode);
262 PUT_MODE (mem1, mode);
263 PUT_MODE (reg, mode);
264
265 /* See if there is some register that can be used in this mode and
266 directly loaded or stored from memory. */
267
268 if (mode != VOIDmode && mode != BLKmode)
269 for (regno = 0; regno < FIRST_PSEUDO_REGISTER
270 && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0);
271 regno++)
272 {
273 if (!HARD_REGNO_MODE_OK (regno, mode))
274 continue;
275
276 REGNO (reg) = regno;
277
278 SET_SRC (pat) = mem;
279 SET_DEST (pat) = reg;
280 if (recog (pat, insn, &num_clobbers) >= 0)
281 direct_load[(int) mode] = 1;
282
283 SET_SRC (pat) = mem1;
284 SET_DEST (pat) = reg;
285 if (recog (pat, insn, &num_clobbers) >= 0)
286 direct_load[(int) mode] = 1;
287
288 SET_SRC (pat) = reg;
289 SET_DEST (pat) = mem;
290 if (recog (pat, insn, &num_clobbers) >= 0)
291 direct_store[(int) mode] = 1;
292
293 SET_SRC (pat) = reg;
294 SET_DEST (pat) = mem1;
295 if (recog (pat, insn, &num_clobbers) >= 0)
296 direct_store[(int) mode] = 1;
297 }
298 }
299
300 mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
301
302 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
303 mode = GET_MODE_WIDER_MODE (mode))
304 {
305 enum machine_mode srcmode;
306 for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
307 srcmode = GET_MODE_WIDER_MODE (srcmode))
308 {
309 enum insn_code ic;
310
311 ic = can_extend_p (mode, srcmode, 0);
312 if (ic == CODE_FOR_nothing)
313 continue;
314
315 PUT_MODE (mem, srcmode);
316
317 if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
318 float_extend_from_mem[mode][srcmode] = true;
319 }
320 }
321 }
在273行,HARD_REGNO_MODE_OK选择真实的物理寄存器。而例程recog也是由后端根据机器描述文件产生,如果考查的RTL指令可以被机器描述文件中的模式所匹配,该函数返回非0值。在317行,insn_data亦是由后端填充,函数指针predicate将选出对于该RTL指令有效的操作数(返回非0值)。这也是由后端设定的。float_extend_from_mem记录的是可以从内存进行浮点扩展的模式。