GCC后端及汇编发布(17)
来源:互联网 发布:客户跟进系统源码 编辑:程序博客网 时间:2024/05/16 05:06
9.3.2. 读入DEFINE_INSN模式
至于define_insn模式,我们使用在前一节中的如下例子:
467 (define_insn "cmpdi_ccno_1_rex64" ini386.md
468 [(set (reg17)
469 (compare (match_operand:DI 0"nonimmediate_operand" "r,?mr")
470 (match_operand:DI 1"const0_operand" "n,n")))]
471 "TARGET_64BIT &&ix86_match_ccmode (insn, CCNOmode)"
472 "@
473 test{q}/t{%0, %0|%0, %0}
474 cmp{q}/t{%1, %0|%0, %1}"
475 [(set_attr "type""test,icmp")
476 (set_attr "length_immediate""0,1")
477 (set_attr "mode" "DI")])
我们已经知道,这个模式被分为这些部分:可选的名字,RTL模板,条件,输出模板,及可选的属性向量。在经过init_md_reader_args的处理后,上面的模式将被以如下的rtx对象,载入内存。
图38:DEFINE_INSN模式的例子
因为在这个模式中仅有一部分信息是对于自动机构建有用,gen_insn只提取它感兴趣的数据。
4383 static void
4384 gen_insn (rtx exp, int lineno) ingenattrtab.c
4385 {
4386 struct insn_def*id;
4387
4388 id = oballoc (sizeof(struct insn_def));
4389 id->next = defs;
4390 defs = id;
4391 id->def = exp;
4392 id->lineno = lineno;
4393
4394 switch(GET_CODE (exp))
4395 {
4396 caseDEFINE_INSN:
4397 id->insn_code = insn_code_number;
4398 id->insn_index = insn_index_number;
4399 id->num_alternatives = count_alternatives (exp);
4400 if (id->num_alternatives == 0)
4401 id->num_alternatives = 1;
4402 id->vec_idx = 4;
4403 break;
4404
4405 caseDEFINE_PEEPHOLE:
4406 id->insn_code = insn_code_number;
4407 id->insn_index = insn_index_number;
4408 id->num_alternatives = count_alternatives (exp);
4409 if (id->num_alternatives == 0)
4410 id->num_alternatives = 1;
4411 id->vec_idx = 3;
4412 break;
4413
4414 case DEFINE_ASM_ATTRIBUTES:
4415 id->insn_code = -1;
4416 id->insn_index = -1;
4417 id->num_alternatives = 1;
4418 id->vec_idx = 0;
4419 got_define_asm_attributes = 1;
4420 break;
4421
4422 default:
4423 abort ();
4424 }
4425 }
上面在4386行,结构体insn_def具有如下定义。它是应该链表。在4389行,defs是一个insn_def的静态实例,它是该链表的表头。
146 struct insn_def ingenattrtab.c
147 {
148 struct insn_def *next; /* Next insn inchain. */
149 rtx def; /* The DEFINE_... */
150 int insn_code; /* Instruction number. */
151 int insn_index; /* Expression numer in file, for errors. */
152 int lineno; /* Line number. */
153 int num_alternatives; /* Number of alternatives. */
154 int vec_idx; /* Index of attribute vector in `def'. */
155 };
count_alternatives用于查找在操作数分配中约束的数目。它仅返回第一个找到的数字。在我们的例子中,第一个找到的约束字符串是“r, ?mr”。可用替代的数目是2,因为约束是由‘,’分隔的。
4284 static int
4285 count_alternatives (rtx exp) ingenattrtab.c
4286 {
4287 int i, j, n;
4288 const char*fmt;
4289
4290 if (GET_CODE (exp) == MATCH_OPERAND)
4291 returnn_comma_elts (XSTR (exp, 2));
4292
4293 for (i = 0,fmt = GET_RTX_FORMAT (GET_CODE (exp));
4294 i< GET_RTX_LENGTH (GET_CODE (exp)); i++)
4295 switch (*fmt++)
4296 {
4297 case 'e':
4298 case 'u':
4299 n= count_alternatives (XEXP (exp, i));
4300 if (n)
4301 return n;
4302 break;
4303
4304 case 'E':
4305 case 'V':
4306 if (XVEC (exp, i) != NULL)
4307 for (j = 0; j < XVECLEN (exp, i); j++)
4308 {
4309 n= count_alternatives (XVECEXP (exp, i, j));
4310 if(n)
4311 return n;
4312 }
4313 }
4314
4315 return 0;
4316 }
9.3.3. 读入DEFINE_ATTR模式
至于define_attr模式的目的,从gccinfo我们获取了以下的段落。
define_attr表达式用于定义每个模板机器所要求的属性。它看起来就像:
(define_attr NAME LIST-OF-VALUES DEFAULT)
NAME是一个指定将被定义属性名的字符串。
LIST-OF-VALUES或者是一个指定了一串由逗号分隔的,可被赋予该属性的值的字符串;或者是一个表示该属性接受数值的空字符串。
DEFAULT是一个属性表达式,它给出了那些匹配不包含在该属性显式值里模式的指令的值。
对于每个已定义的属性,许多定义被写入insn-attr.h文件。至于对一个属性指定一组显式的值的情形,则定义了以下:
* 一个#define被写作符号HAVE_ATTR_NAM'。
* 为attr_NAME定义了一个枚举的类,attr_NAME具有UPPER-NAME_UPPER-VALU形式的成员,其中属性名及值第一次被转换为大写。
* 一个函数get_attr_NAME被定义,向它传入一个指令,并返回该指令的属性值。
例如,如果以下出现在md文件中:
(define_attr "type" "branch,fp,load,store,arith"...)
以下的代码行将被写入insn-attr.h文件。
#define HAVE_ATTR_type
enumattr_type {TYPE_BRANCH, TYPE_FP, TYPE_LOAD,
TYPE_STORE, TYPE_ARITH};
externenum attr_type get_attr_type ();
如果该属性接受数值,将不会定义枚举类型,并且获取该属性值的函数将返回int。
至于define_attr模式,我们使用前一节中的以下的例子:
24 (define_attr "pent_prefix""false,true" in pentium.md
25 (if_then_else (ior (eq_attr "prefix_0f" "1")
26 (ior (eq_attr "prefix_data16""1")
27 (eq_attr "prefix_rep""1")))
28 (const_string "true")
29 (const_string "false")))
在经过init_md_reader_args的处理后,上面的模式将被作为以下的rtx对象载入内存。
图39:DEFINE_ATTR模式的例子
4216 static void
4217 gen_attr (rtx exp, int lineno)
4218 {
4219 struct attr_desc*attr;
4220 struct attr_value*av;
4221 const char*name_ptr;
4222 char *p;
4223
4224 /* Make a newattribute structure. Check for duplicate by looking at
4225 attr->default_val, since it isinitialized by this routine. */
4226 attr = find_attr (&XSTR (exp, 0), 1);
4227 if (attr->default_val)
4228 {
4229 message_with_line (lineno, "duplicatedefinition for attribute %s",
4230 attr->name);
4231 message_with_line (attr->lineno,"previous definition");
4232 have_error = 1;
4233 return;
4234 }
4235 attr->lineno = lineno;
4236
4237 if (*XSTR (exp, 1) == '/0')
4238 attr->is_numeric = 1;
4239 else
4240 {
4241 name_ptr = XSTR (exp, 1);
4242 while ((p =next_comma_elt (&name_ptr)) != NULL)
4243 {
4244 av= oballoc (sizeof (structattr_value));
4245 av->value = attr_rtx(CONST_STRING, p);
4246 av->next = attr->first_value;
4247 attr->first_value= av;
4248 av->first_insn = NULL;
4249 av->num_insns = 0;
4250 av->has_asm_insn = 0;
4251 }
4252 }
4253
4254 if (GET_CODE (XEXP (exp, 2)) == CONST)
4255 {
4256 attr->is_const = 1;
4257 if (attr->is_numeric)
4258 {
4259 message_with_line (lineno,
4260 "constant attributes may not takenumeric values");
4261 have_error =1;
4262 }
4263
4264 /* Get rid of theCONST node. It is allowed only at top-level. */
4265 XEXP(exp, 2) = XEXP (XEXP(exp, 2), 0);
4266 }
4267
4268 if (! strcmp_check (attr->name, length_str)&& ! attr->is_numeric)
4269 {
4270 message_with_line (lineno,
4271 "`length' attribute must take numericvalues");
4272 have_error = 1;
4273 }
4274
4275 /* Set up thedefault value. */
4276 XEXP (exp, 2) = check_attr_value (XEXP (exp,2), attr);
4277 attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
4278 }
属性的数据被保存入全局数组attrs。在这里find_attr的参数name_p指向字符串“pent_prefix”的地址。而find_attr的第二个参数是1,它将使得该函数构建一个新的对象,如果找不到它的话。我们必须防止重复定义,通过检查find_attr返回的attr的default_val。
5805 static struct attr_desc *
5806 find_attr (constchar **name_p, int create) in genattrtab.c
5807 {
5808 struct attr_desc*attr;
5809 int index;
5810 const char*name = *name_p;
5811
5812 /* Before we resortto using `strcmp', see if the string address matches
5813 anywhere. In most cases, it should havebeen canonicalized to do so. */
5814 if (name == alternative_name)
5815 returnNULL;
5816
5817 index = name[0] & (MAX_ATTRS_INDEX - 1);
5818 for (attr = attrs[index];attr; attr = attr->next)
5819 if (name == attr->name)
5820 returnattr;
5821
5822 /* Otherwise, do itthe slow way. */
5823 for (attr = attrs[index];attr; attr = attr->next)
5824 if (name[0] == attr->name[0] &&! strcmp (name, attr->name))
5825 {
5826 *name_p = attr->name;
5827 return attr;
5828 }
5829
5830 if (! create)
5831 returnNULL;
5832
5833 attr = oballoc (sizeof(struct attr_desc));
5834 attr->name = DEF_ATTR_STRING (name);
5835 attr->first_value = attr->default_val =NULL;
5836 attr->is_numeric = attr->negative_ok =attr->is_const = attr->is_special = 0;
5837 attr->unsigned_p = attr->func_units_p =attr->blockage_p = attr->static_p = 0;
5838 attr->next = attrs[index];
5839 attrs[index] = attr;
5840
5841 *name_p = attr->name;
5842
5843 return attr;
5844 }
在5808行的结构体attr_desc有以下的定义,而5818行的attrs是一个attr_desc的数组,大小为256。它实际上是一个哈希表。不过,在5817行的哈希函数不是非常好,因为仅对应于‘a-zA-Z0-9’的索引会被使用。
184 struct attr_desc in genattrtab.c
186 {
185 char *name; /* Name of attribute. */
187 struct attr_desc *next; /* Nextattribute. */
188 struct attr_value*first_value; /* First value of this attribute. */
189 struct attr_value*default_val; /* Default value for thisattribute. */
190 int lineno : 24; /* Line number. */
191 unsigned is_numeric : 1; /* Values of thisattribute are numeric. */
192 unsigned negative_ok : 1; /* Allow negativenumeric values. */
193 unsigned unsigned_p : 1; /* Make the outputfunction unsigned int. */
194 unsigned is_const : 1; /* Attribute valueconstant for each run. */
195 unsigned is_special : 1; /* Don't call`write_attr_set'. */
196 unsigned func_units_p : 1; /* This is thefunction_units attribute. */
197 unsigned blockage_p : 1; /* This is the blockagerange function. */
198 unsigned static_p : 1; /* Make the outputfunction static. */
199 };
在这个定义里,某些属性可以有多个值,以及如果该模式没有被另外指定,而被应用的一个默认值。attr_value被设计来保存这些值。
173 struct attr_value ingenattrtab.c
174 {
175 rtx value; /* Value of attribute. */
176 struct attr_value *next; /* Nextattribute value in chain. */
177 struct insn_ent *first_insn; /* First insn withthis value. */
178 int num_insns; /* Number of insns with this value. */
179 int has_asm_insn; /* True if this value used for `asm' insns */
180 };
继续gen_attr,在分配了attr_desc对象来保存新的属性之后,attr_value的对象被构建来保存属性的值。然后在4245行,attr_rtx被调用来填充这些attr_value对象。注意到第一个参数被写死为CONST_STRING。
729 staticrtx
730 attr_rtx (enumrtx_code code, ...) in genautomata.c
731 {
732 rtx result;
733 va_list p;
734
735 va_start (p, code);
736 result = attr_rtx_1(code, p);
737 va_end (p);
738 return result;
739 }
前面我们看到rtx对象可以按类别分组,已经定义了以下的rtx组别。
Ø “o”用于代表一个对象(即REG,MEM)的rtx编码
Ø “<”用于一个比较(即EQ,NE,LT)的rtx编码
Ø “1”用于一元算术表达式(即NEG,NOT)的rtx编码
Ø “c”用于可交换二元表达式(即PLUS,MULT)的rtx编码
Ø “3”用于非位域三元操作(IF_THEN_ELSE)的rtx编码
Ø “2”用于非可交换二元表达式(即MINUS,DIV)的rtx编码
Ø “b”用于一个位域操作(ZERO_EXTRACT,SIGN_EXTRACT)的rtx编码
Ø “i”用于一个机器指令(INSN,JUMP_INSN,CALL_INSN)的rtx编码
Ø “m”用于匹配指令(即MATCH_DUP)的rtx编码
Ø “g”用于组合指令(即GROUP_PARALLEL)的rtx编码
Ø “a”用于自增地址模式(即POST_DEC)的rtx编码
Ø “x”其余
Rtx编码CONST_STRING的类别是‘o’,而其格式是and the format is ‘s’(定义在rtl.def中)。
556 staticrtx
557 attr_rtx_1 (enum rtx_codecode, va_list p) ingenautomata.c
558 {
559 rtx rt_val = NULL_RTX;/* RTX to return tocaller... */
560 int hashcode;
561 struct attr_hash *h;
562 struct obstack *old_obstack = rtl_obstack;
563
564 /* For each of several cases, search the hashtable for an existing entry.
565 Use that entry if one is found; otherwisecreate a new RTL and add it
566 to the table. */
567
568 if (GET_RTX_CLASS (code) == '1')
569 {
570 rtx arg0 = va_arg (p, rtx);
571
572 /* Apermanent object cannot point to impermanent ones. */
573 if (! ATTR_PERMANENT_P (arg0))
574 {
575 rt_val = rtx_alloc (code);
576 XEXP (rt_val, 0) = arg0;
577 returnrt_val;
578 }
579
580 hashcode = ((HOST_WIDE_INT) code+ RTL_HASH (arg0));
581 for (h = attr_hash_table[hashcode% RTL_HASH_SIZE]; h; h = h->next)
582 if (h->hashcode == hashcode
583 && GET_CODE(h->u.rtl) == code
584 && XEXP(h->u.rtl, 0) == arg0)
585 return h->u.rtl;
586
587 if (h == 0)
588 {
589 rtl_obstack = hash_obstack;
590 rt_val = rtx_alloc (code);
591 XEXP (rt_val, 0) = arg0;
592 }
593 }
594 else if (GET_RTX_CLASS (code) == 'c'
595 || GET_RTX_CLASS (code) == '2'
596 || GET_RTX_CLASS (code) =='<')
597 {
598 rtx arg0 = va_arg (p, rtx);
599 rtx arg1 = va_arg (p, rtx);
600
601 /* Apermanent object cannot point to impermanent ones. */
602 if (! ATTR_PERMANENT_P(arg0) || ! ATTR_PERMANENT_P (arg1))
603 {
604 rt_val = rtx_alloc (code);
605 XEXP (rt_val, 0) = arg0;
606 XEXP (rt_val, 1) = arg1;
607 returnrt_val;
608 }
609
610 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
611 for (h = attr_hash_table[hashcode% RTL_HASH_SIZE]; h; h = h->next)
612 if (h->hashcode == hashcode
613 && GET_CODE (h->u.rtl) == code
614 && XEXP (h->u.rtl, 0) == arg0
615 && XEXP(h->u.rtl, 1) == arg1)
616 return h->u.rtl;
617
618 if (h == 0)
619 {
620 rtl_obstack = hash_obstack;
621 rt_val = rtx_alloc (code);
622 XEXP (rt_val, 0) = arg0;
623 XEXP (rt_val, 1) = arg1;
624 }
625 }
626 else if (GET_RTX_LENGTH (code) == 1
627 && GET_RTX_FORMAT (code)[0] == 's')
628 {
629 char *arg0 = va_arg (p, char *);
630
631 arg0 = DEF_ATTR_STRING (arg0);
632
633 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
634 for (h = attr_hash_table[hashcode% RTL_HASH_SIZE]; h; h = h->next)
635 if (h->hashcode == hashcode
636 && GET_CODE (h->u.rtl) == code
637 && XSTR (h->u.rtl, 0) == arg0)
638 return h->u.rtl;
639
640 if (h == 0)
641 {
642 rtl_obstack = hash_obstack;
643 rt_val = rtx_alloc (code);
644 XSTR (rt_val, 0) = arg0;
645 }
646 }
647 else if (GET_RTX_LENGTH (code) == 2
648 && GET_RTX_FORMAT (code)[0] == 's'
649 && GET_RTX_FORMAT (code)[1] == 's')
650 {
651 char *arg0 = va_arg (p, char *);
652 char *arg1 = va_arg (p, char *);
653
654 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
655 for (h = attr_hash_table[hashcode% RTL_HASH_SIZE]; h; h = h->next)
656 if (h->hashcode == hashcode
657 && GET_CODE (h->u.rtl) == code
658 && XSTR (h->u.rtl, 0) == arg0
659 && XSTR (h->u.rtl, 1) == arg1)
660 return h->u.rtl;
661
662 if (h == 0)
663 {
664 rtl_obstack = hash_obstack;
665 rt_val = rtx_alloc (code);
666 XSTR (rt_val, 0) = arg0;
667 XSTR (rt_val, 1) = arg1;
668 }
669 }
670 else if (code == CONST_INT)
671 {
672 HOST_WIDE_INT arg0 = va_arg (p,HOST_WIDE_INT);
673 if (arg0 == 0)
674 return false_rtx;
675 else if (arg0 == 1)
676 return true_rtx;
677 else
678 goto nohash;
679 }
680 else
681 {
682 int i; /* Array indices... */
683 const char *fmt; /* Current rtx's format... */
684 nohash:
685 rt_val = rtx_alloc (code); /* Allocate the storage space. */
686
687 fmt = GET_RTX_FORMAT (code); /* Find the right format... */
688 for (i = 0; i < GET_RTX_LENGTH (code);i++)
689 {
690 switch(*fmt++)
691 {
692 case'0': /*Unused field. */
693 break;
694
695 case'i': /*An integer? */
696 XINT (rt_val, i) = va_arg (p, int);
697 break;
698
699 case'w': /*A wide integer? */
700 XWINT(rt_val, i) = va_arg (p, HOST_WIDE_INT);
701 break;
702
703 case's': /*A string? */
704 XSTR (rt_val, i) = va_arg (p, char *);
705 break;
706
707 case'e': /*An expression? */
708 case'u': /*An insn? Same except when printing. */
709 XEXP (rt_val, i) = va_arg (p, rtx);
710 break;
711
712 case'E': /*An RTX vector? */
713 XVEC (rt_val, i) = va_arg (p, rtvec);
714 break;
715
716 default:
717 abort ();
718 }
719 }
720 returnrt_val;
721 }
722
723 rtl_obstack= old_obstack;
724 attr_hash_add_rtx (hashcode, rt_val);
725 ATTR_PERMANENT_P (rt_val) = 1;
726 return rt_val;
727 }
对于我们的情形,在626行的ELSE IF分支被执行(参考图39)。回到gen_attr,在4267行check_attr_value被调用来处理这个模式的第三个孩子(默认值)。这个函数,给定一个表达式,确保它是有效的形式,并且所有具名的属性值对于这个给定的属性是有效的。如果不是,发布一个致命错误。如果没有指定一个属性,它假定一个数值的属性。
1073 static rtx
1074 check_attr_value (rtx exp, struct attr_desc *attr) ingenattrtab.c
1075 {
1076 struct attr_value *av;
1077 const char*p;
1078 int i;
1079
1080 switch(GET_CODE (exp))
1081 {
1082 caseCONST_INT:
1083 if (attr && !attr->is_numeric)
1084 {
1085 message_with_line (attr->lineno,
1086 "CONST_INT not valid for non-numericattribute %s",
1087 attr->name);
1088 have_error= 1;
1089 break;
1090 }
1091
1092 if (INTVAL (exp) < 0 && !attr->negative_ok)
1093 {
1094 message_with_line (attr->lineno,
1095 "negative numeric value specified forattribute %s",
1096 attr->name);
1097 have_error= 1;
1098 break;
1099 }
1100 break;
1101
1102 caseCONST_STRING:
1103 if (! strcmp (XSTR (exp, 0),"*"))
1104 break;
1105
1106 if (attr == 0 || attr->is_numeric)
1107 {
1108 p= XSTR (exp, 0);
1109 if (attr && attr->negative_ok&& *p == '-')
1110 p++;
1111 for (; *p;p++)
1112 if (! ISDIGIT (*p))
1113 {
1114 message_with_line (attr ?attr->lineno : 0,
1115 "non-numeric value for numericattribute %s",
1116 attr ? attr->name : "internal");
1117 have_error = 1;
1118 break;
1119 }
1120 break;
1121 }
1122
1123 for (av =attr->first_value; av; av = av->next)
1124 if (GET_CODE (av->value) ==CONST_STRING
1125 && ! strcmp (XSTR (av->value, 0),XSTR (exp, 0)))
1126 break;
1127
1128 if (av == NULL)
1129 {
1130 message_with_line (attr->lineno,
1131 "unknown value `%s' for `%s'attribute",
1132 XSTR (exp, 0), attr ? attr->name :"internal");
1133 have_error= 1;
1134 }
1135 break;
1136
1137 caseIF_THEN_ELSE:
1138 XEXP (exp, 0) = check_attr_test (XEXP (exp, 0),
1139 attr ? attr->is_const : 0,
1140 attr ? attr->lineno : 0);
1141 XEXP (exp, 1) = check_attr_value (XEXP (exp,1), attr);
1142 XEXP (exp, 2) = check_attr_value (XEXP (exp,2), attr);
1143 break;
1144
1145 case PLUS:
1146 case MINUS:
1147 case MULT:
1148 case DIV:
1149 case MOD:
1150 if (attr && !attr->is_numeric)
1151 {
1152 message_with_line (attr->lineno,
1153 "invalid operation `%s' fornon-numeric attribute value",
1154 GET_RTX_NAME (GET_CODE (exp)));
1155 have_error= 1;
1156 break;
1157 }
1158 /* Fallthrough. */
1159
1160 case IOR:
1161 case AND:
1162 XEXP (exp, 0) = check_attr_value (XEXP (exp,0), attr);
1163 XEXP (exp, 1) = check_attr_value (XEXP (exp,1), attr);
1164 break;
1165
1166 case FFS:
1167 case CLZ:
1168 case CTZ:
1169 casePOPCOUNT:
1170 casePARITY:
1171 XEXP (exp, 0) = check_attr_value (XEXP (exp,0), attr);
1172 break;
1173
1174 case COND:
1175 if (XVECLEN (exp, 0) % 2 != 0)
1176 {
1177 message_with_line (attr->lineno,
1178 "first operand of COND must have evenlength");
1179 have_error = 1;
1180 break;
1181 }
1182
1183 for (i = 0; i < XVECLEN (exp, 0); i+= 2)
1184 {
1185 XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i),
1186 attr ? attr->is_const : 0,
1187 attr ? attr->lineno : 0);
1188 XVECEXP (exp, 0, i + 1)
1189 = check_attr_value(XVECEXP (exp, 0, i + 1), attr);
1190 }
1191
1192 XEXP (exp, 1) = check_attr_value (XEXP (exp,1), attr);
1193 break;
1194
1195 case ATTR:
1196 {
1197 struct attr_desc *attr2 = find_attr(&XSTR (exp, 0), 0);
1198 if (attr2 == NULL)
1199 {
1200 message_with_line (attr ? attr->lineno :0,
1201 "unknown attribute `%s' inATTR",
1202 XSTR (exp, 0));
1203 have_error = 1;
1204 }
1205 else if (attr &&attr->is_const && ! attr2->is_const)
1206 {
1207 message_with_line (attr->lineno,
1208 "non-constant attribute `%s'referenced from `%s'",
1209 XSTR (exp, 0), attr->name);
1210 have_error= 1;
1211 }
1212 else if (attr
1213 && (attr->is_numeric !=attr2->is_numeric
1214 || (! attr->negative_ok &&attr2->negative_ok)))
1215 {
1216 message_with_line (attr->lineno,
1217 "numeric attribute mismatchcalling `%s' from `%s'",
1218 XSTR (exp, 0), attr->name);
1219 have_error= 1;
1220 }
1221 }
1222 break;
1223
1224 caseSYMBOL_REF:
1225 /* A constantSYMBOL_REF is valid as a constant attribute test and
1226 is expanded later by make_canonicalinto a COND. In a non-constant
1227 attribute test, it is left be. */
1228 return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
1229
1230 default:
1231 message_with_line (attr ? attr->lineno: 0,
1232 "invalid operation `%s' for attributevalue",
1233 GET_RTX_NAME (GET_CODE (exp)));
1234 have_error = 1;
1235 break;
1236 }
1237
1238 return exp;
1239 }
对于我们的例子,check_attr_value只是检查这个attr_desc是否被正确地构建,它还尝试尽可能地简化条件代码。这个函数为这个值返回一个可能被修改过的替代的表达式。参考图39中rtx对象的第三个孩子。
在gen_attr的最后,get_attr_value被用于获取该属性的默认值。注意在这里第一个参数是define_attr模式的第三个孩子,而第三个参数是-2,它意味着不要处理一个指令,并且该指令不应该包含属性“alternative”。
1480 static struct attr_value *
1481 get_attr_value (rtx value, struct attr_desc *attr, intinsn_code) in genattrtab.c
1482 {
1483 struct attr_value*av;
1484 int num_alt = 0;
1485
1486 value = make_canonical (attr, value);
1487 if (compares_alternatives_p(value))
1488 {
1489 if (insn_code < 0 || insn_alternatives == NULL)
1490 fatal ("(eq_attr/"alternatives/" ...) used in non-insn context");
1491 else
1492 num_alt =insn_alternatives[insn_code];
1493 }
1494
1495 for (av =attr->first_value; av; av = av->next)
1496 if (rtx_equal_p (value, av->value)
1497 && (num_alt == 0 || av->first_insn == NULL
1498 || insn_alternatives[av->first_insn->insn_code]))
1499 returnav;
1500
1501 av = oballoc (sizeof(struct attr_value));
1502 av->value = value;
1503 av->next = attr->first_value;
1504 attr->first_value = av;
1505 av->first_insn = NULL;
1506 av->num_insns = 0;
1507 av->has_asm_insn = 0;
1508
1509 return av;
1510 }
get_attr_value的参数value是模式的条件模板部分,为了便于查看,我们拷贝了图39的这一部分,并显示如下。它由make_canonical改造,它为一个属性值给出了一个有效的表达式,并通过转换成一个COND来移除IF_THEN_ELSE的rtx对象。另外,它把一个属性值“*”,替换为默认属性值。
图40:改造下的exp
1376 static rtx
1377 make_canonical (structattr_desc *attr, rtx exp) in genattrtab
1378 {
1379 int i;
1380 rtx newexp;
1381
1382 switch(GET_CODE (exp))
1383 {
1384 caseCONST_INT:
1385 exp = make_numeric_value(INTVAL (exp));
1386 break;
1387
1388 caseCONST_STRING:
1389 if (! strcmp (XSTR (exp, 0),"*"))
1390 {
1391 if (attr == 0 || attr->default_val == 0)
1392 fatal ("(attr_value /"*/")used in invalid context");
1393 exp = attr->default_val->value;
1394 }
1395 else
1396 XSTR (exp, 0) = DEF_ATTR_STRING (XSTR (exp, 0));
1397
1398 break;
1399
1400 caseSYMBOL_REF:
1401 if (!attr->is_const || ATTR_IND_SIMPLIFIED_P (exp))
1402 break;
1403 /* The SYMBOL_REF is constant for a given run,so mark it as unchanging.
1404 This makes the COND something that won't beconsidered an arbitrary
1405 expression by walk_attr_value. */
1406 ATTR_IND_SIMPLIFIED_P(exp) = 1;
1407 exp = check_attr_value(exp, attr);
1408 break;
1409
1410 caseIF_THEN_ELSE:
1411 newexp = rtx_alloc (COND);
1412 XVEC (newexp, 0) = rtvec_alloc (2);
1413 XVECEXP (newexp, 0, 0) = XEXP(exp, 0);
1414 XVECEXP (newexp, 0, 1) = XEXP(exp, 1);
1415
1416 XEXP (newexp, 1) = XEXP (exp, 2);
1417
1418 exp = newexp;
1419 /* Fall throughto COND case since this is now a COND. */
1420
1421 case COND:
1422 {
1423 int allsame = 1;
1424 rtx defval;
1425
1426 /* First, check for degenerate COND. */
1427 if (XVECLEN (exp, 0) == 0)
1428 return make_canonical(attr, XEXP (exp, 1));
1429 defval = XEXP (exp,1) = make_canonical (attr, XEXP(exp, 1));
1430
1431 for (i = 0; i < XVECLEN (exp, 0); i += 2)
1432 {
1433 XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));
1434 XVECEXP (exp, 0, i + 1)
1435 = make_canonical(attr, XVECEXP (exp, 0, i + 1));
1436 if (! rtx_equal_p (XVECEXP (exp, 0, i + 1),defval))
1437 allsame = 0;
1438 }
1439 if (allsame)
1440 return defval;
1441 }
1442 break;
1443
1444 default:
1445 break;
1446 }
1447
1448 return exp;
1449 }
对于我们的情形,exp具有编码IF_THEN_ELSE。它首先被转换到COND。在1429行, make_canonical递归入新构建的COND对象,进入初始的第三个孩子IF_THEN_ELSE对象,它是CONST_STRING (“false”)。那么在1396行,DEF_ATTR_STRING更新attr_hash_table。
在1433行,copy_boolean,通过与attr_hash_table中为永久缓存的条件的比较,更新rtx对象的字符串。注意copy_boolean返回的rtx对象中的字符串,为attr_hash_table中保存的所替代。
1451 static rtx
1452 copy_boolean (rtx exp) ingenattrtab
1453 {
1454 if (GET_CODE (exp) == AND || GET_CODE (exp)== IOR)
1455 return attr_rtx (GET_CODE (exp), copy_boolean (XEXP(exp, 0)),
1456 copy_boolean (XEXP (exp,1)));
1457 if (GET_CODE (exp) == MATCH_OPERAND)
1458 {
1459 XSTR (exp, 1) = DEF_ATTR_STRING(XSTR (exp, 1));
1460 XSTR (exp, 2) = DEF_ATTR_STRING(XSTR (exp, 2));
1461 }
1462 else if (GET_CODE (exp) == EQ_ATTR)
1463 {
1464 XSTR (exp, 0) = DEF_ATTR_STRING(XSTR (exp, 0));
1465 XSTR (exp, 1) = DEF_ATTR_STRING(XSTR (exp, 1));
1466 }
1467
1468 return exp;
1469 }
在make_canonical的1436行,XVECEXP (exp, 0, i + 1)包含“true”,而defval包含“false”,rtx_equal_p返回0。exp将被返回。
继续get_attr_value,由make_canoncial返回的exp接着被compares_alternatives_p检查define_attr是否包含形如eq_attr(“alternative”, “1”)的表达式,它们在define_attr模式中的这些格式下不被支持。
4321 static int
4322 compares_alternatives_p (rtx exp) ingenattrtab
4323 {
4324 int i, j;
4325 const char*fmt;
4326
4327 if (GET_CODE (exp) == EQ_ATTR && XSTR(exp, 0) == alternative_name)
4328 return 1;
4329
4330 for (i = 0,fmt = GET_RTX_FORMAT (GET_CODE (exp));
4331 i< GET_RTX_LENGTH (GET_CODE (exp)); i++)
4332 switch(*fmt++)
4333 {
4334 case 'e':
4335 case 'u':
4336 if (compares_alternatives_p(XEXP (exp, i)))
4337 return 1;
4338 break;
4339
4340 case 'E':
4341 for (j = 0; j< XVECLEN (exp, i); j++)
4342 if (compares_alternatives_p(XVECEXP (exp, i, j)))
4343 return 1;
4344 break;
4345 }
4346
4347 return 0;
4348 }
由get_attr_value返回的rtx对象被赋予该属性attr_desc的default_val域。记住这个 attr_desc被保存在attrs里。
- GCC后端及汇编发布(17)
- GCC后端及汇编发布(1)
- GCC后端及汇编发布(2)
- GCC后端及汇编发布(3)
- GCC后端及汇编发布(4)
- GCC后端及汇编发布(5)
- GCC后端及汇编发布(6)
- GCC后端及汇编发布(7)
- GCC后端及汇编发布(8)
- GCC后端及汇编发布(9)
- GCC后端及汇编发布(10)
- GCC后端及汇编发布(11)
- GCC后端及汇编发布(12)
- GCC后端及汇编发布(13)
- GCC后端及汇编发布(14)
- GCC后端及汇编发布(15)
- GCC后端及汇编发布(16)
- GCC后端及汇编发布(18)
- THE HISTORY OF THE INTERNET
- 基本XML的DELPHI解析基本搞定了!
- 三次握手
- GCC后端及汇编发布(16)
- GCC's bacl-end & assemble emission (16)
- GCC后端及汇编发布(17)
- ubuntu 软件安装几种方法
- GCC's bacl-end & assemble emission (17)
- GCC后端及汇编发布(18)
- 链表和数组的区别
- 原来代码可以写成爱情故事
- Matlab通信仿真常用函数
- GCC's bacl-end & assemble emission (18)
- 如何使用 Yahoo! Finance stock API 获取股票数据