现在所需要的数据已经从机器描述文件中读入,并且相应的 rtx 对象也已经被构建。不过,对于生成流水线危险识别器来说, rtx 对象还是太粗糙了。更结构化的数据将被从上面节中构建的 rtx 对象中产生出来。
main (continued)
6111 if (have_error )
6112 return FATAL_EXIT_CODE;
6113
6114 insn_code_number ++;
6115
6116 /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one. */
6117 if (! got_define_asm_attributes )
6118 {
6119 tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
6120 XVEC (tem, 0) = rtvec_alloc (0);
6121 gen_insn (tem, 0);
6122 }
6123
6124 /* Expand DEFINE_DELAY information into new attribute. */
6125 if (num_delays )
6126 expand_delays ();
在上面进行准备工作的节中, define_delay 被链接入由 delays 指向的 delay_desc 。虽然功能单元通过 define_function_unit 模式显示了它们如何被指令所使用,或者指令通过 define_insn_reservation 模式显示它们如何使用功能单元,这些模式构成了流水线危险识别器的核心,它们对指令只有很有限的描述。其它模式,即 define_insn , define_delay , define_attr 等,给出了所感兴趣的指令的细节。然后这些细节将被转换成指令的属性。这是我们需要的数据。
expand_delays 为 define_delay 生成属性。注意到 define_delay 定义同样也为新的芯片模式方式所采用,本节也同样应用于 构建基于 DFA的流水线危险识别器 一节。
1526 static void
1527 expand_delays (void) in genautomata.c
1528 {
1529 struct delay_desc *delay;
1530 rtx condexp;
1531 rtx newexp;
1532 int i;
1533 char *p;
1534
1535 /* First, generate data for `num_delay_slots' function. */
1536
1537 condexp = rtx_alloc (COND);
1538 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1539 XEXP (condexp, 1) = make_numeric_value (0);
1540
1541 for (i = 0, delay = delays ; delay; i += 2, delay = delay->next)
1542 {
1543 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1544 XVECEXP (condexp, 0, i + 1)
1545 = make_numeric_value (XVECLEN (delay->def, 1) / 3);
1546 }
1547
1548 make_internal_attr (num_delay_slots_str , condexp, ATTR_NONE);
1549
1550 /* If more than one delay type, do the same for computing the delay type. */
1551 if (num_delays > 1)
1552 {
1553 condexp = rtx_alloc (COND);
1554 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1555 XEXP (condexp, 1) = make_numeric_value (0);
1556
1557 for (i = 0, delay = delays ; delay; i += 2, delay = delay->next)
1558 {
1559 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1560 XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
1561 }
1562
1563 make_internal_attr (delay_type_str , condexp, ATTR_SPECIAL);
1564 }
num_delay_slots_str 及 delay_type_str 都在程序入口处被构建、保存入哈希表。至于 num_delay_slots_str ,其内容是“ *num_delay_slots ”,而对于 delay_type_str ,其内容是“ *delay_type ”。
在 1537 行构建的 condexp 记录了每个 define_attr 模式的测试部分及延迟槽的数目,这是属性“ *num_delay_slots ”的内容。
在 1553 行构建的 condexp 记录了每个 define_attr 模式带有延迟号码的条件部分,这是属性“ *delay_type ”的内容。
在上面 make_numeric_value 被用来构建对应数值的 rtx 对象。
5911 rtx
5912 make_numeric_value (int n) in genautomata.c
5913 {
5914 static rtx int_values[20];
5915 rtx exp;
5916 char *p;
5917
5918 if (n < 0)
5919 abort ();
5920
5921 if (n < 20 && int_values[n])
5922 return int_values[n];
5923
5924 p = attr_printf (MAX_DIGITS, "%d", n);
5925 exp = attr_rtx (CONST_STRING, p);
5926
5927 if (n < 20)
5928 int_values[n] = exp;
5929
5930 return exp;
5931 }
然后由函数 make_internal_attr 填充 attr_desc 。注意在写属性“ *delay_type ”时, ATTR_SPECIAL 被传递给 make_internal_attr ,这个函数随后在产生输出文件时将跳过对 write_attr_set 的调用。
5848 void
5849 make_internal_attr (const char *name, rtx value, int special) in genattrtab.c
5850 {
5851 struct attr_desc *attr;
5852
5853 attr = find_attr (&name, 1);
5854 if (attr->default_val)
5855 abort ();
5856
5857 attr->is_numeric = 1;
5858 attr->is_const = 0;
5859 attr->is_special = (special & ATTR_SPECIAL) != 0;
5860 attr->negative_ok = (special & ATTR_NEGATIVE_OK) != 0;
5861 attr->unsigned_p = (special & ATTR_UNSIGNED) != 0;
5862 attr->func_units_p = (special & ATTR_FUNC_UNITS) != 0;
5863 attr->blockage_p = (special & ATTR_BLOCKAGE) != 0;
5864 attr->static_p = (special & ATTR_STATIC) != 0;
5865 attr->default_val = get_attr_value (value, attr, -2);
5866 }
接着 expand_delays 为每个 define_delay 定义构建属性。注意标记 ATTR_SPECIAL 也被传递给这些属性。
expand_delays (continued)
1526 /* For each delay possibility and delay slot, compute an eligibility
1527 attribute for non-annulled insns and for each type of annulled (annul
1528 if true and annul if false). */
1529 for (delay = delays ; delay; delay = delay->next)
1530 {
1531 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
1532 {
1533 condexp = XVECEXP (delay->def, 1, i);
1534 if (condexp == 0)
1535 condexp = false_rtx ;
1536 newexp = attr_rtx (IF_THEN_ELSE, condexp,
1537 make_numeric_value (1), make_numeric_value (0));
1538
1539 p = attr_printf (sizeof "*delay__" + MAX_DIGITS * 2,
1540 "*delay_%d_%d", delay->num, i / 3);
1541 make_internal_attr (p, newexp, ATTR_SPECIAL);
1542
1543 if (have_annul_true )
1544 {
1545 condexp = XVECEXP (delay->def, 1, i + 1);
1546 if (condexp == 0) condexp = false_rtx ;
1547 newexp = attr_rtx (IF_THEN_ELSE, condexp,
1548 make_numeric_value (1),
1549 make_numeric_value (0));
1550 p = attr_printf (sizeof "*annul_true__" + MAX_DIGITS * 2,
1551 "*annul_true_%d_%d", delay->num, i / 3);
1552 make_internal_attr (p, newexp, ATTR_SPECIAL);
1553 }
1554
1555 if (have_annul_false )
1556 {
1557 condexp = XVECEXP (delay->def, 1, i + 2);
1558 if (condexp == 0) condexp = false_rtx ;
1559 newexp = attr_rtx (IF_THEN_ELSE, condexp,
1560 make_numeric_value (1),
1561 make_numeric_value (0));
1562 p = attr_printf (sizeof "*annul_false__" + MAX_DIGITS * 2,
1563 "*annul_false_%d_%d", delay->num, i / 3);
1564 make_internal_attr (p, newexp, ATTR_SPECIAL);
1565 }
1566 }
1567 }
1568 }
上面, have_annul_true 是 1 ,如果当跳转为真时,某些指令可以被取消;类似的, have_annul_false 是 1 ,如果当跳转为假时,某些指令可以被取消。显然,它们也需要被保存作属性。