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,函數在此傳回。