回到prepare_function_start,跟着它調用了init_emit來初始化與RTL生成有關的資料結構及變量。這個資料結構是emit_status,它是function 結構體中的emit域。
57 struct emit_status GTY(()) in function.h
58 {
59
61 int x_reg_rtx_no;
62
63
64 int x_first_label_num;
65
66
71 rtx x_first_insn;
72 rtx x_last_insn;
73
74
77 tree sequence_rtl_expr;
78
79
83 struct sequence_stack *sequence_stack;
84
85
87 int x_cur_insn_uid;
88
89
91 location_t x_last_location;
92
93
97 int regno_pointer_align_length;
98
99
102 unsigned char * GTY ((length ("%h.x_reg_rtx_no")))
103 regno_pointer_align;
104
105
110 rtx * GTY ((length ("%h.x_reg_rtx_no"))) x_regno_reg_rtx;
111 };
這個結構體控制了被編譯函數的rtl形式表達式的生成。
5333 void
5334 init_emit (void) in emit-rtl.c
5335 {
5336 struct function *f = cfun;
5337
5338 f->emit = ggc_alloc (sizeof (struct emit_status));
5339 first_insn = NULL;
5340 last_insn = NULL;
5341 seq_rtl_expr = NULL;
5342 cur_insn_uid = 1;
5343 reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
5344 last_location.line = 0;
5345 last_location.file = 0;
5346 first_label_num = label_num;
5347 last_label_num = 0;
5348 seq_stack = NULL;
5349
5350
5351
5352 f->emit->regno_pointer_align_length = LAST_VIRTUAL_REGISTER + 101;
5353
5354 f->emit->regno_pointer_align
5355 = ggc_alloc_cleared (f->emit->regno_pointer_align_length
5356 * sizeof (unsigned char));
5357
5358 regno_reg_rtx
5359 = ggc_alloc (f->emit->regno_pointer_align_length * sizeof (rtx));
5360
5361
5362 memcpy (regno_reg_rtx,
5363 static_regno_reg_rtx,
5364 FIRST_PSEUDO_REGISTER * sizeof (rtx));
5365
5366
5367 init_virtual_regs (f->emit);
5368
5369
5371 REG_POINTER (stack_pointer_rtx) = 1;
5372 REG_POINTER (frame_pointer_rtx) = 1;
5373 REG_POINTER (hard_frame_pointer_rtx) = 1;
5374 REG_POINTER (arg_pointer_rtx) = 1;
5375
5376 REG_POINTER (virtual_incoming_args_rtx) = 1;
5377 REG_POINTER (virtual_stack_vars_rtx) = 1;
5378 REG_POINTER (virtual_stack_dynamic_rtx) = 1;
5379 REG_POINTER (virtual_outgoing_args_rtx) = 1;
5380 REG_POINTER (virtual_cfa_rtx) = 1;
5381
5382 #ifdef STACK_BOUNDARY
5383 REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = STACK_BOUNDARY;
5384 REGNO_POINTER_ALIGN (FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
5385 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
5386 REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = STACK_BOUNDARY;
5387
5388 REGNO_POINTER_ALIGN (VIRTUAL_INCOMING_ARGS_REGNUM) = STACK_BOUNDARY;
5389 REGNO_POINTER_ALIGN (VIRTUAL_STACK_VARS_REGNUM) = STACK_BOUNDARY;
5390 REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM) = STACK_BOUNDARY;
5391 REGNO_POINTER_ALIGN (VIRTUAL_OUTGOING_ARGS_REGNUM) = STACK_BOUNDARY;
5392 REGNO_POINTER_ALIGN (VIRTUAL_CFA_REGNUM) = BITS_PER_WORD;
5393 #endif
5394
5395 #ifdef INIT_EXPANDERS
5396 INIT_EXPANDERS;
5397 #endif
5398 }
在代碼中,為了友善通路資料成員,function結構體中所有成員都有相應定義了通路宏。下面就是在上面函數中所用到的宏的定義。
114 #define reg_rtx_no (cfun->emit->x_reg_rtx_no) in function.h
115 #define seq_rtl_expr (cfun->emit->sequence_rtl_expr)
116 #define regno_reg_rtx (cfun->emit->x_regno_reg_rtx)
117 #define seq_stack (cfun->emit->sequence_stack)
173 #define first_insn (cfun->emit->x_first_insn) in emit-rtl.h
174 #define last_insn (cfun->emit->x_last_insn)
175 #define cur_insn_uid (cfun->emit->x_cur_insn_uid)
176 #define last_location (cfun->emit->x_last_location)
177 #define first_label_num (cfun->emit->x_first_label_num)
在5362行,回憶static_regno_reg_rtx在init_emit_once中建立,代表了可用在rtl中的實體寄存器。它可被視為一個常量集,因為在每次編譯一個函數前,整個static_regno_reg_rtx被拷貝入emit_status的x_reg_rtx_no,像這裡所做的那樣。然後init_virtual_regs如下地更新特定的虛拟寄存器。
5147 void
5148 init_virtual_regs (struct emit_status *es) in emit-rtl.c
5149 {
5150 rtx *ptr = es->x_regno_reg_rtx;
5151 ptr[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
5152 ptr[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
5153 ptr[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
5154 ptr[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
5155 ptr[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx;
5156 }
上面,在指派語句的右手邊,都是從global_rtx中選出特定項的宏,這些項都是由init_emit_once所建立,而且它們都是Pmode模式。Pmode依賴于目标平台,并且在static_regno_reg_rtx的建立過程中不做考慮。
宏REG_POINTER檢查rtx對象是否是可以儲存指針值的寄存器。
1032 #define REG_POINTER(RTX) / in rtl.h
1033 (RTL_FLAG_CHECK1("REG_POINTER", (RTX), REG)->frame_related)
405 #define RTL_FLAG_CHECK1(NAME, RTX, C1) __extension__ / in rtl.h
406 ({ rtx const _rtx = (RTX); /
407 if (GET_CODE(_rtx) != C1) /
408 rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, /
409 __FUNCTION__); /
410 _rtx; })
可以看到這些特别處理的寄存器都是與棧框相關的。宏REGNO_POINTER_ALIGN為emit_status執行個體中指定的寄存器選擇對齊要求。STACK_BOUNDARY在32位ABI的x86機器上是字大小的(4位元組)。
119 #define REGNO_POINTER_ALIGN(REGNO) (cfun->emit->regno_pointer_align[REGNO])
x86機器不需要定義5395行的INIT_EXPANDERS。
在prepare_function_start中,下一個函數是init_varasm_status,它為新的function對象初始化了常量哈希池(constant hashing pool)。常量哈希池被包含在varasm_status結構體中。
75 #define MAX_RTX_HASH_TABLE 61
76
77 struct varasm_status GTY(()) in varasm.c
78 {
79
87 struct constant_descriptor_rtx ** GTY ((length ("MAX_RTX_HASH_TABLE")))
88 x_const_rtx_hash_table;
89 struct pool_constant ** GTY ((length ("MAX_RTX_HASH_TABLE")))
90 x_const_rtx_sym_hash_table;
91
92
93 struct pool_constant *x_first_pool;
94 struct pool_constant *x_last_pool;
95
96
98 HOST_WIDE_INT x_pool_offset;
99
100
102 unsigned int deferred_constants;
103 };
在上面的89,93及94行,pool_constant記錄了關于常量的足夠的資訊。其中,關鍵部分是下面2642行的rtx對象constant。
2636 struct pool_constant GTY(()) in varasm.c
2637 {
2638 struct constant_descriptor_rtx *desc;
2639 struct pool_constant *next;
2640 struct pool_constant *next_sym;
2641 rtx constant;
2642 enum machine_mode mode;
2643 int labelno;
2644 unsigned int align;
2645 HOST_WIDE_INT offset;
2646 int mark;
2647 };
2657 void
2658 init_varasm_status (struct function *f) in varasm.c
2659 {
2660 struct varasm_status *p;
2661 p = ggc_alloc (sizeof (struct varasm_status));
2662 f->varasm = p;
2663 p->x_const_rtx_hash_table
2664 = ggc_alloc_cleared (MAX_RTX_HASH_TABLE
2665 * sizeof (struct constant_descriptor_rtx *));
2666 p->x_const_rtx_sym_hash_table
2667 = ggc_alloc_cleared (MAX_RTX_HASH_TABLE
2668 * sizeof (struct pool_constant *));
2669
2670 p->x_first_pool = p->x_last_pool = 0;
2671 p->x_pool_offset = 0;
2672 p->deferred_constants = 0;
2673 }
繼續回到prepare_function_start,它接着調用init_expr來建立expr_status的執行個體。這個執行個體用來控制函數中的每個表達式的處理。
121 struct expr_status GTY(()) in function.h
122 {
123
125 int x_pending_stack_adjust;
126
127
142 int x_inhibit_defer_pop;
143
144
148 int x_stack_pointer_delta;
149
150
153 rtx x_saveregs_value;
154
155
156 rtx x_apply_args_value;
157
158
159 rtx x_forced_labels;
160
161
162 rtx x_pending_chain;
163 };
最終ggc_alloc_cleared建立了一個由0填充的對象。
325 void
326 init_expr (void) in expr.c
327 {
328 cfun->expr = ggc_alloc_cleared (sizeof (struct expr_status));
329 }