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对象,载入内存。

t37

38DEFINE_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对象载入内存。

t39

39DEFINE_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返回的attrdefault_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”用于代表一个对象(即REGMEM)的rtx编码

Ø             <”用于一个比较(即EQNELT)的rtx编码

Ø             1”用于一元算术表达式(即NEGNOT)的rtx编码

Ø             c”用于可交换二元表达式(即PLUSMULT)的rtx编码

Ø             3”用于非位域三元操作(IF_THEN_ELSE)的rtx编码

Ø             2”用于非可交换二元表达式(即MINUSDIV)的rtx编码

Ø             b”用于一个位域操作(ZERO_EXTRACTSIGN_EXTRACT)的rtx编码

Ø             i”用于一个机器指令(INSNJUMP_INSNCALL_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,在4267check_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是否被正确地构建,它还尝试尽可能地简化条件代码。这个函数为这个值返回一个可能被修改过的替代的表达式。参考39rtx对象的第三个孩子。

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_ELSErtx对象。另外,它把一个属性值“*”,替换为默认属性值。

t40

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_canonical1436行,XVECEXP (exp, 0, i + 1)包含“true”,而defval包含“false”,rtx_equal_p返回0exp将被返回。

继续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_descdefault_val域。记住这个 attr_desc被保存在attrs里。

原创粉丝点击