天天看点

GCC-3.4.6源代码学习笔记(48续)

4.2.10. 评估算术操作的代价

4.2.10.1. 创建伪函数上下文

回到backend_init,下来是init_dummy_function_start。它初始化了rtl的展开机制,因而我们可以进行一些简单序列的生成。

6518 void

6519 init_dummy_function_start (void)                                                                      in function.c

6520 {

6521   prepare_function_start (NULL);

6522 }

在这里调用了prepare_function_start来创建伪函数上下文cfun,因为下面的初始化函数需要产生rtl(在正式的代码编译中,只有完成代码解析及前端的优化后,才会生成rtl的表示形式,并交予后端)。

6482 static void

6483 prepare_function_start (tree fndecl)                                                            in function.c

6484 {

6485   if (fndecl && DECL_SAVED_INSNS (fndecl))

6486     cfun = DECL_SAVED_INSNS (fndecl);

6487   else

6488     allocate_struct_function (fndecl);

6489   init_emit ();

6490   init_varasm_status (cfun);

6491   init_expr ();

6492

6493   cse_not_expected = ! optimize;

6494

6495   

6496   caller_save_needed = 0;

6497

6498   

6499   reg_renumber = 0;

6500

6501   

6503   rtx_equal_function_value_matters = 1;

6504

6505   

6506   virtuals_instantiated = 0;

6507

6508   

6509   generating_concat_p = 1;

6510

6511   

6512   frame_pointer_needed = 0;

6513 }

结构体function保存了,描述当前被编译函数状态的所有重要的,全局及静态变量。

176    struct function GTY(())                                                                            in function.h

177    {

178      struct eh_status *eh;

179      struct stmt_status *stmt;

180      struct expr_status *expr;

181      struct emit_status *emit;

182      struct varasm_status *varasm;

183   

184     

185   

186     

187      tree decl;

188   

189     

190      struct function *outer;

191   

192     

195      int pops_args;

196   

197     

200      int args_size;

201   

202     

205      int pretend_args_size;

206   

207     

209      int outgoing_args_size;

210   

211      

213      rtx arg_offset_rtx;

214   

215     

217      CUMULATIVE_ARGS args_info;

218   

219     

223      rtx return_rtx;

224   

225     

226      rtx internal_arg_pointer;

227   

228     

230      const char *cannot_inline;

231   

232     

234      struct initial_value_struct *hard_reg_initial_vals;

235   

236     

237      int x_function_call_count;

238   

239     

242      tree x_nonlocal_labels;

243   

244     

248      rtx x_nonlocal_goto_handler_slots;

249   

250     

252      rtx x_nonlocal_goto_handler_labels;

253   

254     

257      rtx x_nonlocal_goto_stack_level;

258   

259     

263      rtx x_cleanup_label;

264   

265     

268      rtx x_return_label;

269   

270     

273      rtx x_naked_return_label;

274   

275     

276      rtx computed_goto_common_label;

277      rtx computed_goto_common_reg;

278   

279     

281      rtx x_save_expr_regs;

282   

283     

285      rtx x_stack_slot_list;

286   

287     

288      tree x_rtl_expr_chain;

289   

290     

292      rtx x_tail_recursion_label;

293   

294     

295      rtx x_tail_recursion_reentry;

296   

297     

301      rtx x_arg_pointer_save_area;

302   

303     

306      rtx x_clobber_return_insn;

307   

308     

311       HOST_WIDE_INT x_frame_offset;

312   

313     

316      tree x_context_display;

317   

318     

325      tree x_trampoline_list;

326   

327     

328      rtx x_parm_birth_insn;

329   

330     

332      rtx x_last_parm_insn;

333   

334     

336      unsigned int x_max_parm_reg;

337   

338     

342      rtx * GTY ((length ("%h.x_max_parm_reg"))) x_parm_reg_stack_loc;

343   

344     

345      struct temp_slot *x_temp_slots;

346   

347     

348      int x_temp_slot_level;

349   

350     

351      int x_var_temp_slot_level;

352   

353     

357      int x_target_temp_slot_level;

358   

359     

361      struct var_refs_queue *fixup_var_refs_queue;

362   

363     

364      int inlinable;

365      int no_debugging_symbols;

366      rtvec original_arg_vector;

367      tree original_decl_initial;

368     

370      rtx inl_last_parm_insn;

371     

372      int inl_max_label_num;

373   

374     

375      int funcdef_no;

376   

377     

378   

379     

380      struct machine_function * GTY ((maybe_undef (""))) machine;

381     

382      int stack_alignment_needed;

383     

384      int preferred_stack_boundary;

385     

386      bool recursive_call_emit;

387   

388     

389      struct language_function * language;

390   

391     

392   

393     

395      rtx epilogue_delay_list;

396   

397     

399      enum function_frequency {

400       

402        FUNCTION_FREQUENCY_UNLIKELY_EXECUTED,

403       

404        FUNCTION_FREQUENCY_NORMAL,

405       

407        FUNCTION_FREQUENCY_HOT

408      } function_frequency;

409   

410     

412      int max_jumptable_ents;

413   

414     

415   

416     

418      unsigned int returns_struct : 1;

419   

420     

422      unsigned int returns_pcc_struct : 1;

423   

424     

425      unsigned int returns_pointer : 1;

426   

427     

428      unsigned int needs_context : 1;

429   

430     

431      unsigned int calls_setjmp : 1;

432   

433     

434      unsigned int calls_longjmp : 1;

435   

436     

438      unsigned int calls_alloca : 1;

439   

440     

441      unsigned int calls_eh_return : 1;

442   

443     

444      unsigned int calls_constant_p : 1;

445   

446     

448      unsigned int has_nonlocal_label : 1;

449   

450     

452      unsigned int has_nonlocal_goto : 1;

453   

454     

455      unsigned int contains_functions : 1;

456   

457     

458      unsigned int has_computed_jump : 1;

459   

460     

464      unsigned int is_thunk : 1;

465   

466     

471      unsigned int all_throwers_are_sibcalls : 1;

472   

473     

475      unsigned int instrument_entry_exit : 1;

476   

477     

478      unsigned int profile : 1;

479   

480     

482      unsigned int limit_stack : 1;

483   

484     

485      unsigned int stdarg : 1;

486   

487     

491      unsigned int x_whole_function_mode_p : 1;

492   

493     

500      unsigned int x_dont_save_pending_sizes_p : 1;

501   

502     

503      unsigned int uses_const_pool : 1;

504   

505     

506      unsigned int uses_pic_offset_table : 1;

507   

508     

509      unsigned int uses_eh_lsda : 1;

510   

511      

512      unsigned int arg_pointer_save_area_init : 1;

513   

514     

516      unsigned int rtl_inline_init : 1;

517   

518     

519      unsigned int saved_for_inline : 1;

520    };

其结构中前6个成员是非常重要的部分。其中,eh_status控制了函数的异常处理;stmt_status记录了语句对栈,数据流的累积效应,这些效应将影响当前语句的翻译;expr_status则记录了函数被调用及退出的行为;emit_status控制相应的rtx形式指令的生成;varasm_status提供了记录函数中常量的方法。

6434 void

6435 allocate_struct_function (tree fndecl)                                                          in function.c

6436 {

6437   tree result;

6438

6439   cfun = ggc_alloc_cleared (sizeof (struct function));

6440

6441   max_parm_reg = LAST_VIRTUAL_REGISTER + 1;

6442

6443   cfun->stack_alignment_needed = STACK_BOUNDARY;

6444   cfun->preferred_stack_boundary = STACK_BOUNDARY;

6445

6446   current_function_funcdef_no = funcdef_no++;

6447

6448   cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;

6449

6450   init_stmt_for_function ();

6451   init_eh_for_function ();

6452

6453   (*lang_hooks.function.init) (cfun);

6454   if (init_machine_status)

6455     cfun->machine = (*init_machine_status) ();

6456

6457   if (fndecl == NULL)

6458     return;

  …

6477 }

在上面,current_function_funcdef_no,current_function_returns_pcc_struct,current_function_returns_struct,current_function_returns_pointer,max_parm_reg,current_function_needs_context都是用于从function结构体中选择特定成员的宏。例如。

558    #define current_function_funcdef_no (cfun->funcdef_no)                                   in function.h

567    #define max_parm_reg (cfun->x_max_parm_reg)

在6441行,对于x86机器,LAST_VIRTUAL_REGISTER被定义成FIRST_PSEUDO_REGISTER +4。其值是57,它定义了可被用于rtx形式代码的最大寄存器数目。

在6443及6444行,STACK_BOUNDARY定义了对栈的对齐边界要求。对于x86,这是32(4字节)。

在6446行,funcdef_no为用于概要分析(profiling)及调试等目的的标签赋予唯一的号码。在function 结构体相应的域则记录这个值。

接下来,在6450及6451行,函数init_stmt_for_function,init_eh_for_function仅是分配了结构体中的eh及stmt域,它们分别用于异常处理及语句。

在6453行,钩子lang_hooks.function.init对于C++语言是cxx_push_function_context。在当前上下文环境中,它仅为function对象分配language_function实例。结构体language_function将保存及恢复那些记录当前函数编译进度的变量。它被用于嵌套函数。

在6454行,对于x86机器,init_machine_status指向ix86_init_machine_status。它为function 对象创建了machine_function的实例,这个结构保存了与函数处理相关的机器信息。

在6457行,在这次的调用中,fndecl为null,函数在此返回。

继续阅读