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     /* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.

60        After rtl generation, it is 1 plus the largest register number used.  */

61      int x_reg_rtx_no;

62   

63     /* Lowest label number in current function.  */

64      int x_first_label_num;

65   

66      /* The ends of the doubly-linked chain of rtl for the current function.

67        Both are reset to null at the start of rtl generation for the function.

68   

69        start_sequence saves both of these on `sequence_stack' along with

70        `sequence_rtl_expr' and then starts a new, nested sequence of insns.  */

71      rtx x_first_insn;

72      rtx x_last_insn;

73   

74      /* RTL_EXPR within which the current sequence will be placed. Use to

75        prevent reuse of any temporaries within the sequence until after the

76        RTL_EXPR is emitted.  */

77      tree sequence_rtl_expr;

78   

79      /* Stack of pending (incomplete) sequences saved by `start_sequence'.

80        Each element describes one pending sequence.

81        The main insn-chain is saved in the last element of the chain,

82        unless the chain is empty.  */

83      struct sequence_stack *sequence_stack;

84   

85      /* INSN_UID for next insn emitted.

86        Reset to 1 for each function compiled.  */

87      int x_cur_insn_uid;

88   

89      /* Location the last line-number NOTE emitted.

90        This is used to avoid generating duplicates.  */

91      location_t x_last_location;

92   

93     /* The length of the regno_pointer_align, regno_decl, and x_regno_reg_rtx

94        vectors. Since these vectors are needed during the expansion phase when

95        the total number of registers in the function is not yet known, the

96        vectors are copied and made bigger when necessary.  */

97      int regno_pointer_align_length;

98   

99      /* Indexed by pseudo register number, if nonzero gives the known alignment

100      for that pseudo (if REG_POINTER is set in x_regno_reg_rtx).

101      Allocated in parallel with x_regno_reg_rtx.  */

102    unsigned char * GTY ((length ("%h.x_reg_rtx_no")))

103    regno_pointer_align;

104 

105    /* Indexed by pseudo register number, gives the rtx for that pseudo.

106      Allocated in parallel with regno_pointer_align.

107 

108      Note MEM expressions can appear in this array due to the actions

109      of put_var_into_stack.  */

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   /* Init the tables that describe all the pseudo regs.  */

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   /* Put copies of all the hard registers into regno_reg_rtx.  */

5362   memcpy (regno_reg_rtx,

5363          static_regno_reg_rtx,

5364          FIRST_PSEUDO_REGISTER * sizeof (rtx));

5365

5366   /* Put copies of all the virtual register rtx into regno_reg_rtx.  */

5367   init_virtual_regs (f->emit);

5368

5369   /* Indicate that the virtual registers and stack locations are

5370     all pointers.  */

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_rtxinit_emit_once中创建,代表了可用在rtl中的物理寄存器。它可被视为一个常量集,因为在每次编译一个函数前,整个static_regno_reg_rtx被拷贝入emit_statusx_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_ALIGNemit_status实例中指定的寄存器选择对齐要求。STACK_BOUNDARY32ABIx86机器上是字大小的(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      /* Hash facility for making memory-constants

80        from constant rtl-expressions. It is used on RISC machines

81        where immediate integer arguments and constant addresses are restricted

82        so that such constants must be stored in memory.

83   

84        This pool of constants is reinitialized for each function

85        so each function gets its own constants-pool that comes right before

86        it.  */

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     /* Pointers to first and last constant in pool.  */

93      struct pool_constant *x_first_pool;

94      struct pool_constant *x_last_pool;

95   

96      /* Current offset in constant pool (does not include any machine-specific

97        header).  */

98      HOST_WIDE_INT x_pool_offset;

99   

100    /* Number of tree-constants deferred during the expansion of this

101      function.  */

102    unsigned int deferred_constants;

103  };

 

在上面的899394行,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    /* Number of units that we should eventually pop off the stack.

124      These are the arguments to function calls that have already returned.  */

125    int x_pending_stack_adjust;

126 

127    /* Under some ABIs, it is the caller's responsibility to pop arguments

128      pushed for function calls. A naive implementation would simply pop

129      the arguments immediately after each call. However, if several

130      function calls are made in a row, it is typically cheaper to pop

131      all the arguments after all of the calls are complete since a

132      single pop instruction can be used. Therefore, GCC attempts to

133      defer popping the arguments until absolutely necessary.  (For

134      example, at the end of a conditional, the arguments must be popped,

135      since code outside the conditional won't know whether or not the

136      arguments need to be popped.)

137 

138      When INHIBIT_DEFER_POP is nonzero, however, the compiler does not

139      attempt to defer pops. Instead, the stack is popped immediately

140      after each call. Rather then setting this variable directly, use

141      NO_DEFER_POP and OK_DEFER_POP.  */

142    int x_inhibit_defer_pop;

143 

144   /* If PREFERRED_STACK_BOUNDARY and PUSH_ROUNDING are defined, the

145      stack boundary can be momentarily unaligned while pushing the arguments.

146      Record the delta since last aligned boundary here in order to get

147      stack alignment in the nested function calls working right.  */

148    int x_stack_pointer_delta;

149 

150   /* Nonzero means __builtin_saveregs has already been done in this function.

151      The value is the pseudoreg containing the value __builtin_saveregs

152      returned.  */

153    rtx x_saveregs_value;

154 

155    /* Similarly for __builtin_apply_args.  */

156    rtx x_apply_args_value;

157 

158   /* List of labels that must never be deleted.  */

159    rtx x_forced_labels;

160 

161    /* Postincrements that still need to be expanded.  */

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  }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值