天天看點

GCC-3.4.6源代碼學習筆記(48續2)

回到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  }