GCC后端及汇编发布(16)

本文介绍了genattrtab工具的工作原理及其在GCC编译器中的作用。该工具负责生成与指令属性相关的代码,包括属性的定义和使用。文章深入探讨了genattrtab的源码实现,包括如何读取机器描述文件、构建数据结构以及生成相应的代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

9.        genattrtab 工具

9.1. 概览

上面我们看到了工具 genattr 产生文件 insn-attr.h 。这个文件包含了函数的声明。现在是时候看一下这些函数的定义从何而来。在这里它们由 genattratab 输出。再次的,在本节我们仍然使用上一级的例子。

通常,对于目标平台,有两种机器描述文件。第一种定义了,可以识别输入的 RTL 指令,并为目标平台提供了输出汇编信息的模式。这个文件为所有使用同一个指令集的机器所共享。在 genrecog工具 genoutput工具 中,我们已经看到这一点。

而另一个文件是特定于架构的。当前,有两种方式来描述架构,一种是通过利用描述芯片功能单元的 define_function_unit (参考 DEFINE_FUNCTION_UNIT模式的概览 ),而更新的方式是使用以指令的角度来描述芯片的 define_insn_reservation (参考 DEFINE_INSN_RESERVATION模式的概览 )。

除了这些模式,我们还需要其它模式来提供指令的细节。对于旧的方式,可以找到 define_attr define_insn define_delay 。而对于新的方式,则使用 define_attr define_insn define_delay define_automaton define_bypass present_set 等。

9.2. 程序入口

 

5988 int

5989 main (int argc, char **argv)                                                                 in genattrtab.c

5990 {

5991   rtx desc;

5992   struct attr_desc *attr;

5993   struct insn_def *id;

5994   rtx tem;

5995   int i;

5996

5997   progname = "genattrtab";

5998

5999   if (argc <= 1)

6000     fatal ("no input file name");

6001

6002   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)

6003     return (FATAL_EXIT_CODE);

6004

6005   obstack_init (hash_obstack );

6006   obstack_init (temp_obstack );

6007

6008   /* Set up true and false rtx's */

6009   true_rtx = rtx_alloc (CONST_INT);

6010   XWINT (true_rtx , 0) = 1;

6011   false_rtx = rtx_alloc (CONST_INT);

6012   XWINT (false_rtx , 0) = 0;

6013   ATTR_IND_SIMPLIFIED_P (true_rtx ) = ATTR_IND_SIMPLIFIED_P (false_rtx ) = 1;

6014   ATTR_PERMANENT_P (true_rtx ) = ATTR_PERMANENT_P (false_rtx ) = 1;

6015

6016   alternative_name = DEF_ATTR_STRING ("alternative");

6017   length_str = DEF_ATTR_STRING ("length");

6018   delay_type_str = DEF_ATTR_STRING ("*delay_type");

6019   delay_1_0_str = DEF_ATTR_STRING ("*delay_1_0");

6020   num_delay_slots_str = DEF_ATTR_STRING ("*num_delay_slots");

6021

6022   printf ("/* Generated automatically by the program `genattrtab'/n/

6023         from the machine description file `md'.  *//n/n");

6024      

6025         /* Read the machine description.  */

6026      

6027         initiate_automaton_gen (argc, argv);

 

首先我们看一下上面所使用的宏的定义。

 

98    #define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG ((RTX), unchanging)) in genattrtab.c

100  #define ATTR_PERMANENT_P(RTX) ( RTX_FLAG ((RTX), integrated))        in genattrtab.c

402  #define RTX_FLAG(RTX, FLAG) ((RTX)->FLAG)                                       in rtl.h

 

至于 DEF_ATTR_STRING 它引用函数 attr _string 。这个函数 将把这个字符串保存入哈希表( attr_hash_table )。

 

382  #define DEF_ATTR_STRING(S) ( attr_string ((S), strlen (S)))                      in genattrtab.c

 

778  stati c char *

779  attr_string (const char *str, int len)                                                       in genattrtab.c

780  {

781    struct attr_hash *h;

782    int hashcode;

783    int i;

784    char *new_str;

785 

786    /* Compute the hash code.  */

787    hashcode = (len + 1) * 613 + (unsigned) str[0];

788    for (i = 1; i <= len; i += 2)

789      hashcode = ((hashcode * 613) + (unsigned) str[i]);

790    if (hashcode < 0)

791      hashcode = -hashcode;

792 

793    /* Search the table for the string.  */

794    for (h = attr_hash_table [hashcode % RTL_HASH_SIZE]; h; h = h->next)

795      if (h->hashcode == -hashcode && h->u.str[0] == str[0]

796          && !strncmp (h->u.str, str, len))

797        return h->u.str;                 /* <-- return if found.  */

798 

799    /* Not found; create a permanent copy and add it to the hash table.  */

800    new_str = obstack_alloc (hash_obstack , len + 1);

801    memcpy (new_str, str, len);

802    new_str[len] = '/0';

803    attr_hash_add_string (hashcode, new_str);

804 

805    return new_str;                 /* Return the new string.  */

806  }

 

794 行,哈希表 attr_hash_table 包含了类型为 attr_hash 的元素,这个类型具有如下定义。

 

493  struct attr_hash                                                                                    in genattrtab.c

494  {

495    struct attr_hash *next;       /* Next structure in the bucket.  */

496    int hashcode;                    /* Hash code of this rtx or string.  */

497    union

498    {

499      char *str;        /* The string (negative hash codes) */

500      rtx rtl;                   /* or the RTL recorded here.  */

501    } u;

502  };

9.3. 准备工作

像通常一样,这个工具需要读入机器描述文件,并为之构建数据结构。

 

9634 void

9635 initiate_automaton_gen (int argc, char **argv)                                      in genattrtab.c

9636 {

9637   const char *base_name;

9638   int i;

9639

9640   ndfa_flag = 0;

9641   split_argument = 0;   /* default value */

9642   no_minimization_flag = 0;

9643   time_flag = 0;

9644   v_flag = 0;

9645   w_flag = 0;

9646   progress_flag = 0;

9647   for (i = 2; i < argc; i++)

9648     if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)

9649       no_minimization_flag = 1;

9650     else if (strcmp (argv [i], TIME_OPTION) == 0)

9651       time_flag = 1;

9652     else if (strcmp (argv [i], V_OPTION) == 0)

9653       v_flag = 1;

9654     else if (strcmp (argv [i], W_OPTION) == 0)

9655       w_flag = 1;

9656     else if (strcmp (argv [i], NDFA_OPTION) == 0)

9657       ndfa_flag = 1;

9658     else if (strcmp (argv [i], PROGRESS_OPTION) == 0)

9659        progress_flag = 1;

9660     else if (strcmp (argv [i], "-split") == 0)

9661     {

9662       if (i + 1 >= argc)

9663         fatal ("-split has no argument.");

9664       fatal ("option `-split' has not been implemented yet/n");

9665       /* split_argument = atoi (argument_vect [i + 1]); */

9666     }

9667   VLA_PTR_CREATE (decls , 150, "decls");

9668   /* Initialize IR storage.  */

9669   obstack_init (&irp );

9670   initiate_automaton_decl_table ();

9671   initiate_insn_decl_table ();

9672   initiate_decl_table ();

9673   output_file = stdout;

9674   output_description_file = NULL;

9675   base_name = base_file_name (argv[1]);

9676   obstack_grow (&irp , base_name,

9677       strlen (base_name) - strlen (file_name_suffix (base_name)));

9678   obstack_grow (&irp , STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,

9679       strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);

9680   obstack_1grow (&irp , '/0');

9681   output_description_file_name = obstack_base (&irp );

9682   obstack_finish (&irp );

9683 }

9.3.1. 可变长度数组指针

在这个工具中,使用了一个叫做可变长度数组指针( variable length array pointer )的结构。在上面 9667 行是一个例子。

 

547  #define VLA_PTR_CREATE(vla, allocated_length, name)  /                  in genautomata.c

548    do                                                                /

549    {  /

550      vla_ptr_t *const _vla_ptr = &(vla);                                /

551         /

552      VARRAY_GENERIC_PTR_INIT (_vla_ptr->varray, allocated_length, name);/

553      _vla_ptr->length = 0;                                              /

554    }                                                          /

555    while (0)

 

可变长度数组指针具有如下定义:

 

138  typedef struct {                                                                                  in genautomata.c

139    size_t length;      /* current size of vla.  */

140    varray_type varray; /* container for vla.  */

141  } vla_ptr_t;

 

132  struct varray_head_tag GTY(()) {                                                                in varray.h

133    size_t    num_elements;  /* Maximum element number allocated.  */

134    size_t     elements_used;  /* The number of elements used, if

135                              using VARRAY_PUSH/VARRAY_POP.  */

136    enum varray_data_enum type;   /* The kind of elements in the varray.  */

137    const char   *name;         /* name of the varray for reporting errors */

138    varray_data   GTY ((desc ("%0.type"))) data;  /* The data elements follow,

139                                              must be last.  */

140  };

141  typedef struct varray_head_tag *varray_type;

 

varray_data_enum 显示 vla 可以保存何种数据。其值可以与 varray_data 的成员一一对应。

 

63    enum varray_data_enum {                                                                           in varray .h

64      VARRAY_DATA_C,

65      VARRAY_DATA_UC,

66      VARRAY_DATA_S,

67      VARRAY_DATA_US,

68      VARRAY_DATA_I,

69      VARRAY_DATA_U,

70      VARRAY_DATA_L,

71      VARRAY_DATA_UL,

72      VARRAY_DATA_HINT,

73      VARRAY_DATA_UHINT,

74      VARRAY_DATA_GENERIC,

75      VARRAY_DATA_CPTR,

76      VARRAY_DATA_RTX,

77      VARRAY_DATA_RTVEC,

78      VARRAY_DATA_TREE,

79      VARRAY_DATA_BITMAP,

80      VARRAY_DATA_REG,

81      VARRAY_DATA_CONST_EQUIV,

82      VARRAY_DATA_BB,

83      VARRAY_DATA_TE,

84      NUM_VARRAY_DATA

85    };

 

注意到 varray_data 实际上是一个可变数组,它可以是任意长度,只要系统能支持。

 

88    typedef union varray_data_tag GTY (()) {                                                     in varray.h

89      char              GTY ((length ("%0.num_elements"),

90                       tag ("VARRAY_DATA_C"))) c[1];

91      unsigned char     GTY ((length ("%0.num_elements"),

92                       tag ("VARRAY_DATA_UC"))) uc[1];

93      short        GTY ((length ("%0.num_elements"),

94                       tag ("VARRAY_DATA_S")))   s[1];

95      unsigned short    GTY ((length ("%0.num_elements"),

96                       tag ("VARRAY_DATA_US"))) us[1];

97      int                     GTY ((length ("%0.num_elements"),

98                       tag ("VARRAY_DATA_I")))   i[1];

99      unsigned int       GTY ((length ("%0.num_elements"),

100                     tag ("VARRAY_DATA_U"))) u[1];

101    long                  GTY ((length ("%0.num_elements"),

102                     tag ("VARRAY_DATA_L"))) l[1];

103    unsigned long     GTY ((length ("%0.num_elements"),

104                     tag ("VARRAY_DATA_UL"))) ul[1];

105    HOST_WIDE_INT    GTY ((length ("%0.num_elements"),

106                     tag ("VARRAY_DATA_HINT")))   hint[1];

107    unsigned HOST_WIDE_INT GTY ((length ("%0.num_elements"),

108                     tag ("VARRAY_DATA_UHINT"))) uhint[1];

109    PTR                  GTY ((length ("%0.num_elements"), use_param (""),

110                     tag ("VARRAY_DATA_GENERIC")))   generic[1];

111    char                   *GTY ((length ("%0.num_elements"),

112                     tag ("VARRAY_DATA_CPTR"))) cptr[1];

113    rtx                     GTY ((length ("%0.num_elements"),

114                     tag ("VARRAY_DATA_RTX"))) rtx[1];

115    rtvec                  GTY ((length ("%0.num_elements"),

116                     tag ("VARRAY_DATA_RTVEC"))) rtvec[1];

117    tree                   GTY ((length ("%0.num_elements"),

118                     tag ("VARRAY_DATA_TREE"))) tree[1];

119    struct bitmap_head_def *GTY ((length ("%0.num_elements"),

120                     tag ("VARRAY_DATA_BITMAP"))) bitmap[1];

121    struct reg_info_def     *GTY ((length ("%0.num_elements"), skip (""),

122                     tag ("VARRAY_DATA_REG"))) reg[1];

123    struct const_equiv_data GTY ((length ("%0.num_elements"),

124                     tag ("VARRAY_DATA_CONST_EQUIV"))) const_equiv[1];

125    struct basic_block_def *GTY ((length ("%0.num_elements"), skip (""),

126                     tag ("VARRAY_DATA_BB"))) bb[1];

127    struct elt_list      *GTY ((length ("%0.num_elements"),

128                     tag ("VARRAY_DATA_TE"))) te[1];

129  } varray_data;

 

上面在 VLA_PTR_CREATE 552 VARRAY_GENERIC_PTR_INIT 为该 varray 分配内存 并且元素的类型将是 VARRAY_DATA_GENERIC varray_data PTR

 

177  #define VARRAY_GENERIC_PTR_INIT(va, num, name) /                                   in varray.h

178    va = varray_init (num, VARRAY_DATA_GENERIC, name)

 

115  varray_type

116  varray_init (size_t num_elements, enum varray_data_enum element_kind,       in varray.c

117              const char *name)

118  {

119    size_t data_size = num_elements * element[element_kind].size;

120    varray_type ptr;

121  #ifdef GATHER_STATISTICS

122    struct varray_descriptor *desc = varray_descriptor (name);

123 

124    desc->created++;

125    desc->allocated += data_size + VARRAY_HDR_SIZE;

126  #endif

127    if (element[element_kind].uses_ggc)

128      ptr = ggc_alloc_cleared (VARRAY_HDR_SIZE + data_size);

129    else

130      ptr = xcalloc (VARRAY_HDR_SIZE + data_size, 1);

131 

132    ptr->num_elements = num_elements;

133    ptr->elements_used = 0;

134    ptr->type = element_kind;

135    ptr->name = name;

136    return ptr;

137  }

 

然后接着,用于声明的哈希表由下面的函数来初始化。

 

2237 static void

2238 initiate_automaton_decl_table (void)                                                    in genattrtab.c

2239 {

2240   work_automaton_decl.mode = dm_automaton;

2241   automaton_decl_table = htab_create (10, automaton_decl_hash,

2242                                   automaton_decl_eq_p, (htab_del) 0);

2243 }

 

2336 static void

2337 initiate_insn_decl_table (void)                                                             in genattrtab.c

2338 {

2339   work_insn_decl.mode = dm_insn_reserv;

2340   insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,

2341                             (htab_del) 0);

2342 }

 

2438 static void

2439 initiate_decl_table (void)                                                                    in genattrtab.c

2440 {

2441   work_decl.mode = dm_unit;

2442   decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);

2443 }

 

接着 main ,在分配了所需的资源之后,系统开始读入机器描述文件。

 

main (continued)

 

5988   while (1)

5989   {

5990     int lineno;

5991

5992     desc = read_md_rtx (&lineno, &insn_code_number );

5993     if (desc == NULL)

5994       break ;

5995

5996     switch (GET_CODE (desc))

5997     {

5998       case DEFINE_INSN:

5999       case DEFINE_PEEPHOLE:

6000       case DEFINE_ASM_ATTRIBUTES:

6001         gen_insn (desc, lineno);

6002         break ;

6003

6004       case DEFINE_ATTR:

6005         gen_attr (desc, lineno);

6006         break ;

6007

6008       case DEFINE_DELAY:

6009         gen_delay (desc, lineno);

6010         break ;

6011

6012       case DEFINE_FUNCTION_UNIT:

6013         gen_unit (desc, lineno);

6014         break ;

6015

6016       case DEFINE_CPU_UNIT:

6017          gen_cpu_unit (desc);

6018         break ;

6019

6020       case DEFINE_QUERY_CPU_UNIT:

6021         gen_query_cpu_unit (desc);

6022         break ;

6023

6024       case DEFINE_BYPASS:

6025         gen_bypass (desc);

6026         break ;

6027

6028       case EXCLUSION_SET:

6029         gen_excl_set (desc);

6030         break ;

6031

6032       case PRESENCE_SET:

6033         gen_presence_set (desc);

6034         break ;

6035

6036       case FINAL_PRESENCE_SET:

6037         gen_final_presence_set (desc);

6038          break ;

6039

6040       case ABSENCE_SET:

6041         gen_absence_set (desc);

6042         break ;

6043

6044       case FINAL_ABSENCE_SET:

6045         gen_final_absence_set (desc);

6046          break ;

6047

6048       case DEFINE_AUTOMATON:

6049         gen_automaton (desc);

6050         break ;

6051

6052       case AUTOMATA_OPTION:

6053         gen_automata_option (desc);

6054         break ;

6055

6056       case DEFINE_RESERVATION:

6057         gen_reserv (desc);

6058         break;

6059

6060       case DEFINE_INSN_RESERVATION:

6061         gen_insn_reserv (desc);

6062         break ;

6063

6064       default :

6065         break ;

6066     }

6067     if (GET_CODE (desc) != DEFINE_ASM_ATTRIBUTES)

6068       insn_index_number ++;

6069   }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值