GCC后端及汇编发布(3)

2.2. 输出指令定义模式的条件部分

接着 genconditions 将产生包含指令描述模式的条件测试部分的数组 insn_conditions 。这个数组将被用于协助优化后端功能单元的生成,我们将在后面的章节看到这一点。

 

main (continued, genconditions)

 

199    /* Read the machine description.  */

200 

201    while (1)

202    {

203      desc = read_md_rtx (&pattern_lineno, &code);

204      if (desc == NULL)

205        break ;

206 

207       /* N.B. define_insn_and_split, define_cond_exec are handled

208         entirely within read_md_rtx; we never see them.  */

209      switch (GET_CODE (desc))

210      {

211        default :

212           break ;

213 

214        case DEFINE_INSN:

215        case DEFINE_EXPAND:

216            add_condition (XSTR (desc, 2));

217            /* except.h needs to know whether there is an eh_return

218               pattern in the machine description.  */

219            if (!strcmp (XSTR (desc, 0), "eh_return"))

220               saw_eh_return = 1;

221            break ;

222 

223        case DEFINE_SPLIT:

224        case DEFINE_PEEPHOLE:

225        case DEFINE_PEEPHOLE2:

226              add_condition (XSTR (desc, 1));

227             break ;

228      }

229    }

230 

231    write_header ();

232    write_conditions ();

233 

234    fflush (stdout);

235    return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);

236  }

 

这里,在 203 行, read_md_rtx 几乎不作任何事,因为 insn_elision_unavailable 1 ——仅创建它。 read_md_rtx 仅相应地从 define_attr_queue define_insn_queue other_queue 返回 rtx 对象。

 

52    static void

53    add_condition (const char *expr)                                                          in genconditions.c

54    {

55      struct c_test *test;

56   

57      if (expr[0] == 0)

58        return ;

59   

60      test = xmalloc (sizeof (struct c_test));

61      test->expr = expr;

62   

63      *(htab_find_slot (condition_table , test, INSERT)) = test;

64    }

 

所有的模式都将被函数 add_condition 加入哈希表 condition_table 。注意传递给 add_condition 的参数,它是模式的条件部分。在 231 行, write_header 输出该输出文件的常量部分。

 

163  static void

164  write_conditions (void)                                                                              in genconditions.c

165  {

166    puts ("/

167  /* This table lists each condition found in the machine description./n/

168     Each condition is mapped to its truth value (0 or 1), or -1 if that/n/

169     cannot be calculated at compile time. *//n/

170  /n/

171  const struct c_test insn_conditions[] = {");

172 

173    htab_traverse (condition_table , write_one_condition , 0);

174 

175    puts ("};/n");

176 

177    printf ("const size_t n_insn_conditions = %lu;/n",

178           (unsigned long) htab_elements (condition_table ));

179    puts ("const int insn_elision_unavailable = 0;");

180  }

 

上面,在 173 行, htab_traverse 将为每个 condition_table 的成员调用 write_one_condition 。在这里这个函数构建了数组 insn_conditions 。注意到在 179 行,当构建 insn-recog.c 时, maybe_eval_c_test 将执行评估,因为现在 insn_elision_unavailable 0 了。

 

140  static int

141  write_one_condition (void **slot, void *dummy ATTRIBUTE_UNUSED)       in genconditions.c

142  {

143    const struct c_test *test = * (const struct c_test **) slot;

144    const char *p;

145 

146    fputs ("  { /"", stdout);

147    for (p = test->expr; *p; p++)

148    {

149      if (*p == '/n')

150        fputs ("//n///n", stdout);

151      else if (*p == '"')

152        fputs ("///"", stdout);

153      else

154        putchar (*p);

155    }

156 

157    printf ("/",/n    MAYBE_EVAL (%s) },/n", test->expr);

158    return 1;

159  }

 

上面在 157 行, MAYBE_EVAL 具有如下定义,它同样出现在产生的文件 insn-conditions.c 中(通过 write_header 输出)。

 

#if (GCC_VERSION >= 3001) || ((GCC_VERSION == 3000) && !__OPTIMIZE__)

# define MAYBE_EVAL(expr) (__builtin_constant_p(expr) ? (int) (expr) : -1)

#else

# define MAYBE_EVAL(expr) -1

#endif

 

__builtin_constant_p GCC 3.0.1 版本之后提供的内建函数,如果 expr 是编译时刻已知的常量,它返回 1 ;否则返回 0 。因此 MAYBE_EVAL ,如果表达式的值是编译时刻可以计算的,就返回这个值,否则返回 -1 。这个宏被 insn-conditions 大量用于其它工具,后面我们可以看到。它确实能帮助减小产生代码的大小,及节省处理时间,因为在处理的某个时间点上,工具可以跳过那些已知不匹配的模式。

 

你可能感兴趣的:(GCC后端及汇编发布(3))